Index ソフト・ハード PyTorch | mnistSample |
深層学習 GPU使用 datasets MyDataset init_mnist() mnistTorch.py ローダー ロード モデル optimizer training_data 機能・要件 構成・方式 タスク ライブラリ 導入 sample datasets myData |
MNIST深層学習 (mnist_torch.py、CentOS7または、Windows10で実施)
# mnistDeepConvNetTorch.py
import argparse # コマンドライン引数を解析(ハイフォンはアンダーバーに置き換わる。)
import logging
import numpy as np
import os.path
import os
import pickle
import torch
import torch.nn as nn
import torch.nn.functional as f
from torch.utils.data import Dataset, DataLoader
from mnistTorch import init_mnist
#from torchvision import datasets
#from torchvision.io import read_image
#from torchvision.transforms import ToTensor, Lambda
class MNISTDataset(Dataset):# データセット(MyDatasetを使用)
def __init__(self,images_path, labels_path):
Dataset.__init__(self)
with open(images_path, 'rb') as images_path:
self.images = torch.tensor(pickle.load(images_path)) # tensor化
print("self.images :",self.images[0])
with open(labels_path, 'rb') as labels_path:
self.labels = pickle.load(labels_path)
print("self.labels :",self.labels[0])
return
def __len__(self):
return len(self.images)
def __getitem__(self, index):
return (self.images[index], self.labels[index])
def main():
parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
parser.add_argument('--verbose', action='store_true', default=False, help='enables verbose logging') # ログ表示(デバック時)
parser.add_argument('--batch_size', type=int, default=64, metavar='N', help='input batch size for training (default: 64)') # 訓練時バッチサイズ
parser.add_argument('--test_batch_size', type=int, default=1000, metavar='N',help='input batch size for testing (default: 1000)') # テスト時バッチサイズ
parser.add_argument('--no_shuffle', action='store_true', default=False, help='disables dataset shuffling') # 訓練データをシャッフルしない。
parser.add_argument('--epochs', type=int, default=20, metavar='N', help='number of epochs to train (default: 10)') # 訓練時のエポック数
parser.add_argument('--lr', type=float, default=0.001, metavar='LR', help='learning rate (default: 0.01)') # 学習率
parser.add_argument('--seed', type=int, default=1, metavar='S', help='random seed (default: 1)') # 乱数のシードを指定
parser.add_argument('--no_cuda', action='store_true', default=False, help='disables CUDA training') # GPUがあってもCUDAを使用しない。(デバック時)
parser.add_argument('--dry_run', action='store_true', default=False, help='quickly check a single pass') # デック用に1バッチ実行
parser.add_argument('--log_interval', type=int, default=10, metavar='N', help='how many batches to wait before logging training status') # 進捗表示間隔
parser.add_argument('--save_model', type=str, metavar='path', default=None, help='saves model to file') # モデル(ネット)を保存、読み込むパス
parser.add_argument('--datadir', type=str, default="data") #
args = parser.parse_args()
torch.manual_seed(args.seed) # 乱数シードを設定
level = (logging.DEBUG if args.verbose else logging.INFO) # ログ出力を設定
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=level)
use_cuda = not args.no_cuda and torch.cuda.is_available() # CUDA の使用・不使用
device = torch.device("cuda" if use_cuda else "cpu")
print("device :",device)
train_kwargs = {'batch_size': args.batch_size, 'shuffle': not args.no_shuffle} # バッチサイズその他のパラメータを設定
test_kwargs = {'batch_size': args.test_batch_size}
if use_cuda:
cuda_kwargs = {'pin_memory': True}
train_kwargs.update(cuda_kwargs)
test_kwargs.update(cuda_kwargs)
print("args :",args)
# データセット(datasets.MNISTを使用)
#training_data = datasets.MNIST(root="data", train=True, download=True, transform=ToTensor())
#test_data = datasets.MNIST(root="data", train=False, download=True, transform=ToTensor())
# データセット(datasets.FashionMNISTを使用)
#training_data = datasets.FashionMNIST(root="data", train=True, download=True, transform=ToTensor())
#test_data = datasets.FashionMNIST(root="data", train=False, download=True, transform=ToTensor())
# 訓練データ読み込み(MyDataset)
init_mnist() # データロード
train_dataset = MNISTDataset(
os.path.join(args.datadir, 'train-images-idx3-ubyte'),
os.path.join(args.datadir, 'train-labels-idx1-ubyte')
)
print("train_dataset :", train_dataset[0])
# テストデータ読み込み
test_dataset = MNISTDataset(
os.path.join(args.datadir, 't10k-images-idx3-ubyte'),
os.path.join(args.datadir, 't10k-labels-idx1-ubyte')
)
train_dataloader = DataLoader(training_data, **train_kwargs, num_workers=2) # 訓練データ読み込み
test_dataloader = DataLoader(test_data, **train_kwargs, num_workers=2) # テストデータ読み込み
model = MyNet() # モデル作成(ネットワーク構造の構築)
if args.save_model is not None:
logging.info(f'Loading: {args.save_model}...') # モデルをファイルから読み込む
try:
params = torch.load(args.save_model, map_location=device)
model.load_state_dict(params)
except FileNotFoundError as e:
logging.error(f'Error: {e}')
model = model.to(device)
print("model :", model)
optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # 最適化器と学習率 lr=0.001
print("optimizer :", optimizer)
# エポック回だけ訓練・テストを繰り返す。
for epoch in range(args.epochs):
logging.info(f'*** epoch={epoch+1}/{args.epochs} ***')
train(model, device, train_loader, optimizer, log_interval=args.log_interval, dry_run=args.dry_run)
test(model, device, test_loader)
# モデルをファイルに保存する。
# if args.save_model is not None:
# logging.info(f'Saving: {args.save_model}...')
# params = model.state_dict()
# torch.save(params, args.save_model)
# model = models.vgg16(pretrained=True)
PATH = "./model_weight.pth"
torch.save(model.state_dict(), PATH) # 学習済パラメータを辞書に保存
torch.save(model, 'model.pth') # 形状を含み保存
return
class MyNet(nn.Module): # ネットワーク構造の定義
def __init__(self): # 各レイヤーの初期化①
super(MyNet,self).__init__()
self.conv1 = nn.Conv2d(1,32,3,1) # 畳み込み
self.conv2 = nn.Conv2d(32,64,3,1) # 畳み込み
self.pool = nn.MaxPool2d(2,2) # Max Pooling(1/2)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(12*12*64,128) # 全接続 (fully connected)
self.fc2 = nn.Linear(128,10)
return
def forward(self,x): # ミニバッチ x を処理
x = self.conv1(x)
x = f.relu(x)
x = self.conv2(x)
x = f.relu(x)
x = self.pool(x)
x = self.dropout1(x)
x = x.view(-1,12*12*64)
x = self.fc1(x)
x = f.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
return f.log_softmax(x, dim=1)
def train(model, device, loader, optimizer, log_interval=1, dry_run=False): # 1エポック分の訓練
model.train() # 訓練モードに
for (idx, (images, labels)) in enumerate(loader): # 各ミニバッチを処理
inputs = images.float().to(device) # 入力をfloat型のテンソルに変換
targets = labels.long().to(device) # 正解をlong型のテンソルに変換
optimizer.zero_grad() # すべての勾配(.grad)をクリア
outputs = model(inputs) # 与えたミニバッチをニューラルネットワークで処理
loss = f.cross_entropy(outputs, targets) # 損失を計算
loss.backward() # 勾配を計算
optimizer.step() # 重み、バイアスを更新
if idx % 100 == 99:
# if dry_run or ((idx+1) % log_interval) == 0: # 現在の状況を表示
avg_loss = loss.item() / len(outputs)
# logging.info(f'train: batch={idx+1}/{len(loader)}, loss={avg_loss:.4f}')
# if dry_run: # dry_run モードの場合、1回で終了
# break
return
def test(model, device, loader): # テスト
model.eval() # 検証/テストモード
correct = 0
with torch.no_grad(): # 以下の処理ではautograd機能を使わない。
for (idx, (images, labels)) in enumerate(loader): # 各ミニバッチを処理
inputs = images.float().to(device) # 入力をfloat型のテンソルに変換
targets = labels.long().to(device) # 正解をlong型のテンソルに変換
outputs = model(inputs) # 与えたミニバッチをニューラルネットワークで処理
n = 0 # 正解かどうかを判定
for (y,label) in zip(outputs, targets):
i = torch.argmax(y)
if i == label:
n += 1
logging.debug(f'test: batch={idx+1}/{len(loader)}, correct={n}/{len(outputs)}')
correct += n
total = len(loader.dataset) # 結果を表示
logging.info(f'test: total={correct}/{total} ({100*correct/total:.2f}%)')
return
if __name__ == "__main__": main()
mnistTorch.py
#!/usr/bin/env python3
# mnistTorch.py
import gzip
import numpy as np
import os
import os.path
import pickle
import urllib.request
url_base = 'http://yann.lecun.com/exdb/mnist/'
key_file = {
'train_img':'train-images-idx3-ubyte.gz',
'train_label':'train-labels-idx1-ubyte.gz',
'test_img':'t10k-images-idx3-ubyte.gz',
'test_label':'t10k-labels-idx1-ubyte.gz'
}
dataset_dir = os.path.dirname(os.path.abspath(__file__)) # 現在のDir
save_train_img = dataset_dir + "/data" + "/train-images-idx3-ubyte" # セーブするファイル
save_train_label = dataset_dir + "/data" + "/train-labels-idx1-ubyte"
save_test_img = dataset_dir + "/data" + "/t10k-images-idx3-ubyte"
save_test_label = dataset_dir + "/data" + "/t10k-labels-idx1-ubyte"
def init_mnist():
print("***download***")
download_mnist()
print("***convert***")
dataset = _convert() # 正規化、reshape
# pklwithファイルで保存
with open(save_train_img, 'wb') as f:
pickle.dump(dataset['train_img'], f, -1)
with open(save_train_label, 'wb') as f:
pickle.dump(dataset['train_label'], f, -1)
with open(save_test_img, 'wb') as f:
pickle.dump(dataset['test_img'], f, -1)
with open(save_test_label, 'wb') as f:
pickle.dump(dataset['test_label'], f, -1)
def download_mnist():
for v in key_file.values():
_download(v)
print("Download Done!")
def _download(file_name):
file_path = dataset_dir + "/data" + "/" + file_name
if os.path.exists(file_path):
return
print("Downloading " + file_name + " ... ")
urllib.request.urlretrieve(url_base + file_name, file_path)
def _convert():
dataset = {}
dataset['train_img'] = _load_img(key_file['train_img'])
# np.set_printoptions(linewidth=118)
# print(dataset['train_img'][999].reshape((28, 28)))
dataset['test_img'] = _load_img(key_file['test_img'])
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].astype(np.float32)
dataset[key] /= 255.0
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].reshape(-1, 1, 28, 28)
dataset['train_label'] = _load_label(key_file['train_label'])
dataset['test_label'] = _load_label(key_file['test_label'])
return dataset
def _load_img(file_name):
img_size = 784
file_path = dataset_dir + "/data" + "/" + file_name
print("Converting " + file_name + " to NumPy Array ...")
with gzip.open(file_path, 'rb') as f:
data = np.frombuffer(f.read(), np.uint8, offset=16)
data = data.reshape(-1, img_size)
return data
def _load_label(file_name):
file_path = dataset_dir + "/data" + "/" + file_name
print("Converting " + file_name + " to NumPy Array ...")
with gzip.open(file_path, 'rb') as f:
labels = np.frombuffer(f.read(), np.uint8, offset=8)
return labels
if __name__ == '__main__':init_mnist()
training_data
print("taining_data :",taining_data) # training_data の内容
taining_data : Dataset MNIST
Number of datapoints: 60000
Root location: data
Split: Train
StandardTransform
Transform: ToTensor()
print("taining_data[999] :",taining_data[999]) # 999番目のdataを参照
taining_data[999] :(tensor([[[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.0000, 0.0000],
・・・
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.0000, 0.0000]]]), 6)
|
All Rights Reserved. Copyright (C) ITCL |