やりたいこと
犬と猫を見分ける画像分類問題を取り扱うために、pytorchで実装を試みています。
このとき、データセットの作成、モデルの作成、lossの作成から学習部分の実装は大体終わっていて、次にaccuracyを求めたいと考えています。いわゆる精度&推論というところだと思います。
このときのデータセット(256x256x3)として、少ないですが、以下のようになっています。
├─animal_dataset ├─train │ ├─cat(70枚くらい) │ └─dog(70枚くらい) └─val ├─cat(30枚くらい) └─dog(30枚くらい)
また、lossの収束としては、batchsize=4,epoch=100で以下のようなグラフに収束しました。
本当にやりたいこと
ここからが本当にやりたいことです。
lossの値を出したように精度(accuracy)を確認したいです。
ただ、チュートリアルにあるようなコードを使っても正しいかどうかわからないという点にくろうしています。
そもそも評価ってどうすればいいのか。何をもとに評価しているのか...
そのため、以下に示すコードから間違っている点を指摘していただきたいです。
ソースコード
eval.py(実行コード)
import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import model,dataset from model import * from tqdm import tqdm from torch.autograd import Variable import numpy as np from matplotlib import pyplot as plt device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') if __name__ == "__main__": # modelの定義 model = model.Net().to(device) # 推論モード model.eval() # optimizerの定義 optimizer = torch.optim.SGD( model.parameters(), lr=0.0001, momentum=0.9, weight_decay=0.0001) #パラメータの読み込み model.load_state_dict(torch.load("model_cpu.pth", map_location=device)) # validationのデータセット valid_dataset = dataset.MyDatasets( root_dir="./animal_dataset", key="val", ) valid_loader = torch.utils.data.DataLoader( valid_dataset, batch_size=4, shuffle= True ) # 評価関数の作成 correct = 0 total = 0 acc = [] with torch.no_grad(): for data in valid_loader: inputs, labels = data[0].to(device), data[1].to(device) # print("label={}".format(labels)) # print("inputs={}".format(inputs)) outputs = model(inputs).to(device) # print(outputs.data) # 確率 _, predicted = torch.max(outputs.data, 1) # print(predicted) total += labels.size(0) # print(total) correct += (predicted == labels).sum().item() # print(correct) acc.append(float(correct/total)) print("Accuracy of the network on the 100 test images: %d %%" % (100*correct/total)) def plot_acc(acc): fig, ax = plt.subplots() epochs = np.arange(1,len(acc)+1) ax.set_title("accuracy") ax.plot(epochs, acc) ax.set_xlabel("Epoch") print("epochs: {}".format(epochs)) print("acc: {}".format(acc)) plt.savefig("acc.png") plot_acc(acc)
出力結果
様々な点にprintを入れて出力を見ています。
・精度画像の出力
なかなかにひどいです。(確実に間違っているのですがどこが違うのかわかりません。)
・printの結果
eval.pyの以下にprintを入れた時の出力結果です。
_, predicted = torch.max(outputs.data, 1) print(predicted) torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([4, 984064]) tensor([0, 0, 0, 0], device='cuda:0') torch.Size([2, 984064]) tensor([0, 0], device='cuda:0') Accuracy of the network on the 100 test images: 50 %
なんかこの0が並んでるのが違和感です。
追記
プログラムにepochsとaccの内容をprintしました。
. . . torch.Size([2, 984064]) Accuracy of the network on the 100 test images: 50 % epochs: [1] acc: [0.5]
このようになっていました。
追記2
lossを収束させたコード(train.py)
import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import model,dataset from model import * from tqdm import tqdm from torch.autograd import Variable import numpy as np from matplotlib import pyplot as plt device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 上でgpuの設定device if __name__ == "__main__": # modelの定義 model = model.Net().to(device) model.train() # optimizerの定義 optimizer = torch.optim.SGD( model.parameters(), lr=0.0001, momentum=0.9, weight_decay=0.0001) # datasetの定義 # training train_dataset = dataset.MyDatasets( root_dir="./animal_dataset", key="train", ) train_loader = torch.utils.data.DataLoader( train_dataset, batch_size=4, shuffle= True ) # validation valid_dataset = dataset.MyDatasets( root_dir="./animal_dataset", key="val", ) valid_loader = torch.utils.data.DataLoader( valid_dataset, batch_size=4, shuffle= True ) # batch = len(next(iter(train_loader))) #2 # for i in train_loader: # print(i) # for i in valid_loader: # print(i) # iterationの確定 sample_size = len(train_dataset) #129 # num_iters = sample_size // 4 #loss criterion = nn.CrossEntropyLoss().to(device) losses = [] #start epoch epoch_num = 100 for epoch in range(epoch_num): # loop over the dataset multiple times epoch_loss = 0 for i, data in enumerate(train_loader, 0): # get the inputs; data is a list of [inputs, labels] inputs, labels = data[0].to(device), data[1].to(device) # print("label={}".format(labels)) # print("inputs={}".format(inputs)) outputs = model(inputs).to(device) # print(model) # with torch.no_grad(): loss = criterion(outputs, labels) # loss.requires_grad = True # print(loss) optimizer.zero_grad() loss.backward() optimizer.step() # print(loss) epoch_loss += loss losses.append(np.mean(float(epoch_loss))) print('Finished Training') """ 層を出力 おそらくtorch.save torch.loadをつかう?? """ # for param_tensor in model.state_dict(): print(model.state_dict()['conv1.weight']) model = model.to('cpu') torch.save(model.state_dict(), 'model_cpu.pth') # lossグラフ描画 def plot_history(losses): fig, ax = plt.subplots() epochs = np.arange(1, len(losses) + 1) # 損失の推移 ax.set_title("Loss") ax.plot(epochs, losses) ax.set_xlabel("Epoch") plt.savefig('loss.png') plot_history(losses)
上記で、lossを収束させています。modelはconv1,conv2の2層です。
ただ、model_cpu.pthの容量が大きすぎて中身見れないみたいです。
追記3
eval.pyとtrain.pyでパラメータの保存とloadを書いた時の出力accを表示します。
epochs: [1] acc: [0.5740740740740741]
困っていること
以上の結果から正しい精度&推論を出すためのプログラムの書き方を教えてほしいです。
plot_accのグラフを書く関数がおかしいのか。それとももともと評価するところのプログラムがおかしいのかわかりません。どうかご指摘下ればと思います。
また、初心者故にわからないところ、投稿に不備があるかと思います。
その時はご指摘していただけると助かります。
どうか、今回の精度を出す実装をお手伝いくださればと思います。
よろしくお願いいたします。
参考
ciefer10のチュートリアル。精度のほとんどの部分を参考にしました。
torch.maxの使い方について
グラフの描画から精度まで参考にした記事
回答1件
あなたの回答
tips
プレビュー