サイトと同じ精度を実現したい
pytorch初学者です。大学で音声感情認識の研究をしていて、実装がうまく行かなかったので練習に立ち返ることにし、MNISTをCNNで学習させるプログラムをコピペして実行しました。出典はこちらです。
でも実際に動かしてみると、出典サイトでは96%程度のテスト精度が出ていたのに対し、手元の環境では54.6%しか出ませんでした。
データセットも前処理もモデルも同じなのになぜこうも結果に差が出るのかがわからずとてもモヤモヤしています。音声感情認識のモデルを実装したときも、論文のとおりに作っても中々精度が出ず、方向性がわからなくなり練習に戻ってきました。
知りたいこと
・訓練ロスとテストロス、訓練精度とテスト精度の記録を入れた
・torch.to()関数でGPUを利用するようにした
以外はすべてサイトのコピペです。やっていることは同じなのになぜこうも精度が違うのかが知りたいです。問題のコードと、40エポック経過後のロスと精度の推移を添付します。どうかよろしくお願いします。
補足:上記2つの改変を消して実行してみましたが、結果は変わらなかったのでこれらは原因ではないことがわかりました。
実行環境
CPU: Intel® Xeon(R) Silver 4208 CPU @ 2.10GHz × 16
GPU: NVIDIA GeForce RTX 2080 Ti/PCIe/SSE2
OS: Ubuntu 18.04.5 LTS
開発環境: Jupyter Notebook
コード
すべてJupyter Notebook上で実行しました。実行したセルごとにまとめて添付します。
モジュールのインポート
python
1import torch 2import torchvision 3import torchvision.transforms as transforms 4import numpy as np 5import matplotlib.pyplot as plt 6import torch.nn as nn 7import torch.nn.functional as F 8import torch.optim as optim
MNISTをロードする
python
1transform = transforms.Compose( 2 [transforms.ToTensor(), 3 transforms.Normalize((0.5, ), (0.5, ))]) 4 5trainset = torchvision.datasets.MNIST(root='../data', 6 train=True, 7 download=True, 8 transform=transform) 9trainloader = torch.utils.data.DataLoader(trainset, 10 batch_size=100, 11 shuffle=True, 12 num_workers=2) 13 14testset = torchvision.datasets.MNIST(root='../data', 15 train=False, 16 download=True, 17 transform=transform) 18testloader = torch.utils.data.DataLoader(testset, 19 batch_size=100, 20 shuffle=False, 21 num_workers=2) 22 23classes = tuple(np.linspace(0, 9, 10, dtype=np.uint8))
CNNモデルの定義
python
1class Net(nn.Module): 2 def __init__(self): 3 super(Net, self).__init__() 4 self.conv1 = nn.Conv2d(1, 32, 3) # 28x28x32 -> 26x26x32 5 self.conv2 = nn.Conv2d(32, 64, 3) # 26x26x64 -> 24x24x64 6 self.pool = nn.MaxPool2d(2, 2) # 24x24x64 -> 12x12x64 7 self.dropout1 = nn.Dropout2d() 8 self.fc1 = nn.Linear(12 * 12 * 64, 128) 9 self.dropout2 = nn.Dropout2d() 10 self.fc2 = nn.Linear(128, 10) 11 12 def forward(self, x): 13 x = F.relu(self.conv1(x)) 14 x = self.pool(F.relu(self.conv2(x))) 15 x = self.dropout1(x) 16 x = x.view(-1, 12 * 12 * 64) 17 x = F.relu(self.fc1(x)) 18 x = self.dropout2(x) 19 x = self.fc2(x) 20 return x
学習用コード
python
1model = Net().to('cuda') 2 3criterion = nn.CrossEntropyLoss() 4optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) 5epochs = 40 6 7#ロスと精度記録用のリスト 8train_loss = [] 9test_loss = [] 10train_accuracy = [] 11test_accuracy = [] 12 13for epoch in range(epochs): 14 running_loss = 0.0 15 16 #学習する 17 for i, (inputs, labels) in enumerate(trainloader, 0): 18 # zero the parameter gradients 19 optimizer.zero_grad() 20 21 # forward + backward + optimize 22 inputs = inputs.to('cuda') 23 labels = labels.to('cuda') 24 outputs = model(inputs) 25 loss = criterion(outputs, labels) 26 loss.backward() 27 optimizer.step() 28 # print statistics 29 running_loss += loss.item() 30 if i % 100 == 99: 31 print('[{:d}, {:5d}] loss: {:.3f}' 32 .format(epoch + 1, i + 1, running_loss / 100)) 33 34 train_loss.append(running_loss / i) 35 36 37 correct = 0 38 total = 0 39 # テストデータを一周 40 with torch.no_grad(): 41 running_test_loss = 0 42 for index, (images, labels) in enumerate(testloader): 43 images = images.to('cuda') 44 labels = labels.to('cuda') 45 outputs = model(images) 46 loss = criterion(outputs, labels) 47 running_test_loss += loss.item() 48 _, predicted = torch.max(outputs.data, 1) 49 total += labels.size(0) 50 correct += (predicted == labels).sum().item() 51 52 test_loss.append(running_test_loss / index) 53 test_accuracy.append(correct / total) 54 55 correct = 0 56 total = 0 57 # 訓練データを一周 58 with torch.no_grad(): 59 running_loss = 0 60 for index, (images, labels) in enumerate(trainloader): 61 images = images.to('cuda') 62 labels = labels.to('cuda') 63 outputs = model(images) 64 _, predicted = torch.max(outputs.data, 1) 65 total += labels.size(0) 66 correct += (predicted == labels).sum().item() 67 train_accuracy.append(correct / total) 68 69print('Finished Training')
結果の出力
ロスの出力と結果
python
1plt.plot(train_loss, label='train_loss') 2plt.plot(test_loss, label='test_loss') 3plt.legend() 4plt.plot()
精度の出力と結果
python
1plt.plot(train_accuracy, label='train_accuracy') 2plt.plot(test_accuracy, label='test_accuracy') 3plt.legend() 4plt.plot()
追記:やってみたこと
・見た感じ、パラメータ数が足りていないのかと思ったので、畳み込み層を1つ追加してみた
→精度は変わらなかった
回答1件
あなたの回答
tips
プレビュー