目的
Pytorchを使用していてDatasetとDataloaderが何なのかがイメージできなかった。イメージするために『PyTorchでMNISTを扱ってみた (機械学習)』で解説されているMNISTのスクリプトの中のDatasetとDataloadeのイメージ図を作成したので共有する。
尚、『[Pytorch]DatasetとDataloaderのイメージ図(自作Dataset版)』で自作DataをDatasetに格納するスクリプトを紹介しています。
DatasetとDataloaderを作成するスクリプトとイメージ図
#Datasetをロードするスクリプト
train_dataset = torchvision.datasets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download = True)
#Dataloaderを作成するスクリプト
batch_size = 256
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
#Dataloaderからmini batchを1ケずつ取り出すスクリプト
for epoch in range(1, num_epochs+1, 1):
(疑問点) mini batchにできないあまりは無視される?
(参考)MNISTのスクリプト全体
d13a_MNIST.ipynb
#----------------ライブラリのインポート--------------------
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
#--------------乱数シードの固定---------------------------
def setup_all_seed(seed=0):
# numpyに関係する乱数シードの設定
np.random.seed(seed)
# pytorch
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.backends.cudnn.deterministic = True
#--------------Datasetのロード----------------------------
#訓練データ
train_dataset = torchvision.datasets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download = True)
#検証データ
test_dataset = torchvision.datasets.MNIST(root='./data',
train=False,
transform=transforms.ToTensor(),
download = True)
#-------------------Dataloaderの作成--------------------------------
batch_size = 256
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=True)
#----------------ニューラルネットワーク(MLP)の定義-----------------
class Net(nn.Module):
def __init__(self, input_size, hidden1_size, hidden2_size, output_size):
super(Net, self).__init__()
self.fc1 = nn.Linear(input_size, hidden1_size)
self.fc2 = nn.Linear(hidden1_size, hidden2_size)
self.fc3 = nn.Linear(hidden2_size, output_size)
def forward(self, x): # x : 入力
z1 = F.relu(self.fc1(x))
z2 = F.relu(self.fc2(z1))
y = self.fc3(z2)
return y
#----------------モデルのインスタンス化-----------------
input_size = 28*28 #MNISTの画像サイズ x=28,y=28
hidden1_size = 1024
hidden2_size = 512
output_size = 10
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = Net(input_size, hidden1_size, hidden2_size, output_size).to(device)
#print(model)
# ---------------損失関数 criterion:基準-------------
# CrossEntropyLoss:交差エントロピー誤差関数
criterion = nn.CrossEntropyLoss()
#-------最適化法の指定 optimizer:最適化---------------
# SGD:確率的勾配降下法
optimizer = optim.SGD(model.parameters(), lr=0.01)
#------------1epochの学習を行う関数の定義------------------
def train_model(model, train_loader, criterion, optimizer, device='cpu'):
train_loss = 0.0
num_train = 0
# 学習モデルに変換
model.train()
for i, (images, labels) in enumerate(train_loader):
# mini batchに含まれるデータ数をカウント
num_train += len(labels)
# mini batch
images, labels = images.view(-1, 28*28).to(device), labels.to(device)
# 勾配を初期化
optimizer.zero_grad()
# 推論(順伝播)
outputs = model(images)
# 損失の算出
loss = criterion(outputs, labels)
# 誤差逆伝播
loss.backward()
# パラメータの更新
optimizer.step()
# lossを加算
train_loss += loss.item()
# lossの平均値を取る
train_loss = train_loss / num_train
return train_loss
#------------検証データによるモデル評価を行う関数の定義--------------
def test_model(model, test_loader, criterion, optimizer, device='cpu'):
test_loss = 0.0
num_test = 0
# modelを評価モードに変更
model.eval()
with torch.no_grad(): # 勾配計算の無効化
for i, (images, labels) in enumerate(test_loader):
num_test += len(labels)
images, labels = images.view(-1, 28*28).to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
# lossの平均値を取る
test_loss = test_loss / num_test
return test_loss
#----------学習を行う関数の定義 ------------
def lerning(model, train_loader, test_loader, criterion, opimizer, num_epochs, device='cpu'):
train_loss_list = []
test_loss_list = []
# epoch数分繰り返す
for epoch in range(1, num_epochs+1, 1):
train_loss = train_model(model, train_loader, criterion, optimizer, device=device)
test_loss = test_model(model, test_loader, criterion, optimizer, device=device)
print("epoch : {}, train_loss : {:.5f}, test_loss : {:.5f}" .format(epoch, train_loss, test_loss))
train_loss_list.append(train_loss)
test_loss_list.append(test_loss)
return train_loss_list, test_loss_list
#--------------学習の実施---------------------------
num_epochs = 10
train_loss_list, test_loss_list = lerning(model, train_loader, test_loader, criterion, optimizer, num_epochs, device=device)
#---------------学習推移のグラフ化-----------------
plt.plot(range(len(train_loss_list)), train_loss_list, c='b', label='train loss')
plt.plot(range(len(test_loss_list)), test_loss_list, c='r', label='test loss')
plt.xlabel("epoch")
plt.ylabel("loss")
plt.legend()
plt.grid()
plt.show()
#------------------学習結果の確認--------------------
plt.figure(figsize=(20, 10))
for i in range(10):
image, label = test_dataset[i]
image = image.view(-1, 28*28).to(device)
# 推論
prediction_label = torch.argmax(model(image))
ax = plt.subplot(1, 10, i+1)
plt.imshow(image.detach().to('cpu').numpy().reshape(28, 28), cmap='gray')
ax.axis('off')
ax.set_title('label : {}\n Prediction : {}'.format(label, prediction_label), fontsize=15)
plt.show()