質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3226閲覧

state_dictを利用してモデルのパラメータを取得し評価(accuracy)を求めたい

oinari03

総合スコア59

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/09/10 16:10

編集2020/09/11 07:28

やりたいこと

犬と猫を見分ける画像分類問題を取り扱うために、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の使い方について
グラフの描画から精度まで参考にした記事

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2020/09/10 16:31

ax.plot(epochs, acc) に与えている epochs と acc を print() で出力した結果を教えてください
oinari03

2020/09/11 00:39

プログラムにprint()を加え、出力結果を追記しました。
tiitoi

2020/09/11 04:35

そもそも質問のコードは学習じゃなくて全サンプルを推論してその精度を計算しているだけなので、グラフにはならないですよね。 acc: [0.5] が今のモデルの精度です。 質問のコードには学習したモデルを読み込む処理も見当たらないので、重みはランダムに初期化された状態 (学習前の状態) のままであり、よって当てずっぽうに答えて2クラスで正答率が50%になるというのは妥当な結果だと思います。
oinari03

2020/09/11 05:08 編集

ご指摘ありがとうございます。 精度が0.5というのはなかなか悲しいものなのでもう少し上げた精度が欲しいです。 そのために、モデルのパラメータを入れる必要があるという解釈で大丈夫でしょうか? 投稿の質問タイトルの内容の処理をかいてないのが申し訳ないのですが、 今回投稿した意図は、state_dictでモデルのパラメータをloadすれば推論ができる。と見たが、具体的なやり方がわからない。 いったん、モデルパラメータを加えず、チュートリアル通りに推論の処理を書いた次第です。 例えば、state_dictに関しては、以下のコードで for param_tensor in model.state_dict(): print(param_tensor, "\t", model.state_dict()[param_tensor].size()) 以下の出力が得られました。 ``` conv1.weight torch.Size([128, 3, 3, 3]) conv1.bias torch.Size([128]) conv2.weight torch.Size([256, 128, 3, 3]) conv2.bias torch.Size([256]) fc1.weight torch.Size([120, 984064]) fc1.bias torch.Size([120]) fc2.weight torch.Size([84, 120]) fc2.bias torch.Size([84]) fc3.weight torch.Size([2, 84]) fc3.bias torch.Size([2]) ``` これはモデルのパラメータを表していることかと思いますが、どのように推論に落とし込むのかに困っています。 結果的に精度向上になるよな改善点があればご指摘願えればと思います。
tiitoi

2020/09/11 05:26

> モデルのパラメータを入れる必要があるという解釈で大丈夫でしょうか? パラメータを入れるというか、質問のコードはモデルだけ作って学習されていない状態です。 Loss のグラフを作ったということは他のコードで学習したのだと思いますが、だとしたら、そのときに重みを保存して、推論するときはその重みを読み込むという処理が必要です。 質問のコードにはそれが見当たりません。
oinari03

2020/09/11 07:23 編集

根本的にモデルのパラメータをどう処理すればいいかというのが頭に入ってなかったです。 いろいろご指摘いただけたおかげで多分ですが、やっとやろうとしていることを理解しました。 (見当違いだった気がします....) 自分がわからないのはlossを作ったコードから、モデルのパラメータを保存して、今回のeval.pyに引継ぎをする方法ということでした。 失礼かと思いますが、 train.py(lossを収束させたコード)と、自分なりにパラメータを保存するコードをtrain/evalそれぞれに追記いたしましたので、学習後のパラメータを保存して、evalに引き継ぎそれをもとに推論する方法を教えていただけないでしょうか...
guest

回答1

0

ベストアンサー

以下をコードに組み込んでください。

学習時に重みを保存するコード

python

1# モデルを保存する。 2torch.save(model.state_dict(), "model.pth")

推論時に重みを読み込むコード

python

1# 保存したモデルを読み込む。 2model.load_state_dict(torch.load("model.pth"))

Pytorch - モデルをファイルに保存する方法

投稿2020/09/11 08:06

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oinari03

2020/09/11 08:50

お答えいただきありがとうございます。 添付ファイルと解答通り修正して、追記いたしました。 修正後のコードを質問にも追記していますが、手元で確認したところ、精度が ``` Accuracy of the network on the 100 test images: 57 % epochs: [1] acc: [0.5740740740740741] ``` 57%と低い値でした、こちらをもう少し精度よくするにはどんな工夫がありますでしょうか?
tiitoi

2020/09/11 09:22

* 学習データを増やす * オーグメンテーションする * 学習済みモデルを使う etc... 一概にこれをすれば良くなるというのはないので、いろいろ試すしかないですね
oinari03

2020/09/11 12:27

なるほどです。 いつもありがとうございます。会話の中からいろいろ勉強させていただいています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問