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

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

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

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

機械学習

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

Python

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

Q&A

解決済

1回答

2912閲覧

未知データに対しての推論結果が全て同じ値となる

mmmw

総合スコア23

深層学習

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

機械学習

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

Python

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

0グッド

0クリップ

投稿2021/07/06 12:36

編集2021/07/07 08:30

前提・実現したいこと

CNN(ResNet18)を用いて、正常品か欠損品かを0,1で判断したい。
モデル学習後、未知データに対して推論を行うと推論結果が全て同じになる(全て0 or 全て1)

testデータ推論時に、正常品1,欠陥品0と出力されるようにしたい。
ハイパラメータの設定が上手くいっていないため出力がおかしなことになっていると考えている。
(学習率、モーメンタムなど、)

発生している問題・エラーメッセージ

filename,pred 1009937.jpeg,0 109996.jpeg,0 119892.jpeg,0 129893.jpeg,0 139981.jpeg,0 149997.jpeg,0 ....... ....... ....... 289969.jpeg,0 29934.jpeg,0 299953.jpeg,0 309928.jpeg,0 319945.jpeg,0 329953.jpeg,0

該当のソースコード

python

1# 事前学習無のResNet18作成 2from torchvision import models 3model_ft = models.resnet18(pretrained=False) 4 5# out_feature 書き換え 6import torch.nn as nn 7model_ft.fc = nn.Linear(in_features=512, out_features=2, bias=True) 8 9 10# 推論用データ整理 <-----------ここのハイパラメータの調整が上手くいっていないからと考えている。 11import torch.optim as optim 12model_ft = get_model(target_num=TARGET_NUM,isPretrained=False) 13optimizer = optim.SGD(model_ft.parameters(),lr=0.001, momentum=0.9) 14criterion = nn.CrossEntropyLoss() 15 16 17 18# モデル学習 19import torch 20import torch.nn as nn 21import torch.optim as optim 22from torch.utils.data import Dataset 23from torchvision import datasets, models, transforms 24from PIL import Image, ImageFilter 25# モデル訓練用関数 26def train_model(model, dataset_sizes, criterion, optimizer, num_epochs,is_saved = False): 27 best_acc = 0.0 28 # エポック数だけ下記工程の繰り返し 29 for epoch in range(num_epochs): 30 for phase in ['train', 'val']: 31 print('{}:フェイズ'.format(phase)) 32 # 訓練フェイズと検証フェイズの切り替え 33 if phase == 'train': 34 model.train() 35 else: 36 model.eval() 37 running_loss = 0.0 38 running_corrects = 0 39 # dataloadersからバッチサイズだけデータ取り出し、下記工程(1−5)の繰り返し 40 for i,(inputs, labels) in enumerate(image_dataloaders[phase]): 41 inputs = inputs.to(DEVICE) 42 labels = labels.to(DEVICE) 43 # 1. optimizerの勾配初期化 44 optimizer.zero_grad() 45 # 2.モデルに入力データをinputし、outputを取り出す 46 outputs = model(inputs) 47 _, preds = torch.max(outputs, 1) 48 # 3. outputと正解ラベルから、lossを算出 49 loss = criterion(outputs, labels) 50 print(' loaders:{}回目'.format(i+1) ,' loss:{}'.format(loss)) 51 if phase == 'train': 52 # 4. 誤差逆伝播法により勾配の算出 53 loss.backward() 54 # 5. optimizerのパラメータ更新 55 optimizer.step() 56 running_loss += loss.item() * inputs.size(0) 57 running_corrects += torch.sum(preds == labels.data) 58 59 #平均のlossを算出 60 epoch_loss = running_loss / len(dataset_sizes[phase].dataset) 61 #どれだけ正解していたのかAccuracyを求めている 62 epoch_acc = running_corrects.double() / len(dataset_sizes[phase].dataset) 63 print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc)) 64 # C. 今までのエポックでの精度よりも高い場合はモデルの保存 65 if phase == 'val' and epoch_acc > best_acc: 66 best_acc = epoch_acc 67 if(is_saved): 68 torch.save(model.state_dict(), './original_model_{}.pth'.format(epoch)) 69 print('Best val Acc: {:4f}'.format(best_acc)) 70 print('./original_model_{}.pth'.format(epoch)) 71 72 73 74# 未知データ推論、取り出し <------------------------この過程の前に,推論用データの前処理等は行っている。 75DEVICE='cpu' 76pred = [] 77for i,(inputs,labels) in enumerate(test_dataloader): 78 inputs = inputs.to(DEVICE) 79 # 学習済みモデルを推論モードに設定 80 loaded_model.eval() 81 # 学習済みモデルにデータをインプットし、推論をさせる 82 outputs = loaded_model(inputs) 83 # アウトプットから推定されたラベルを取得 84 _, preds = torch.max(outputs, 1) 85 # 事前に用意したリストに推論結果(0 or 1)を格納 86 pred.append(preds.item()) 87df_test['pred'] = pred

追加コード

python

1#train_Dataloader 2import torch 3image_dataloaders = { 4 'train': torch.utils.data.DataLoader(image_datasets['train'], batch_size=4,shuffle=True, num_workers=0, drop_last=True), 5 'val': torch.utils.data.DataLoader(image_datasets['val'], batch_size=4,shuffle=False, num_workers=0, drop_last=True), 6} 7train_dataloader = torch.utils.data.DataLoader(image_datasets['train'], 8 batch_size=4, 9 shuffle=True, 10 num_workers=0, 11 drop_last=True) 12val_dataloader = torch.utils.data.DataLoader(image_datasets['val'], 13 batch_size=4, 14 shuffle=False, 15 num_workers=0, 16 drop_last=True) 17 18 19#train_model呼び出し 20dataset_sizes = {'train':train_dataloader, 'val':val_dataloader} 21train_model(model_ft,dataset_sizes,criterion,optimizer,40,False) 22 23 24#学習済みmodelのロード,loaded_modelの定義 25import pickle 26import torch.nn as nn 27import torch 28from torchvision import datasets, models, transforms 29 30DEVICE= "cpu" 31def get_model(target_num,isPretrained=False): 32 model_ft = models.resnet18(pretrained=isPretrained) 33 model_ft.fc = nn.Linear(512, target_num) 34 model_ft = model_ft.to(DEVICE) 35 return model_ft 36best_model = get_model(target_num=2) 37# モデルを保存する 38modelname = './original_model_39.pth' 39pickle.dump(best_model, open(modelname, 'wb')) 40# 保存したモデルをロードする 41loaded_model = pickle.load(open(modelname, 'rb')) 42 43 44 45

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

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

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

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

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

quickquip

2021/07/06 12:39

質問が書かれていないようです。
jbpb0

2021/07/06 13:13

学習データでの正常品と欠損品のデータ数は、だいたい同じくらいでしょうか?
mmmw

2021/07/06 13:18

train data 正常品80 欠損品120 val data 正常品20 欠損品30 です。
jbpb0

2021/07/06 15:14

> train data 正常品80 欠損品120 極端にどちらかが多いと、うまく学習できない場合がありますが、80:120なら大丈夫でしょうね
jbpb0

2021/07/06 21:28

学習後に、学習データでテストしたら、正解率は上がるのでしょうか? 学習時のlossは、学習が進んだら、順調に減っていたのでしょうか?
mmmw

2021/07/06 22:45

学習時、 lossは順調に減少し、 正答率epoch_accは0.96まで上がりました。
toast-uz

2021/07/06 22:55

train_modelを呼び出しているところ、loaded_modelの定義、などのコードもお願いします。 保存したモデルをうまくロードできていないのでは・・・?
jbpb0

2021/07/06 23:18 編集

> 正答率epoch_accは0.96まで上がりました。 それは学習時のものですよね 学習後にテストデータでテストしてるところに、テストデータではなく学習データと同じものを使ったら、どうなりますか? 96%くらい合いますか?
mmmw

2021/07/07 08:32

コード追加しました。 学習データと同じモノでも90~96%くらいでした。
jbpb0

2021/07/07 08:40 編集

> 学習データと同じモノでも90~96%くらいでした。 全く同じコードで、学習後にテストするデータを差し替えただけで、 ・学習データと同じものでテストしたら正解率が90%以上 ・未知の画像だとダメダメ なんですか? もしそうなら、学習に使ったデータと、未知の画像が、全く傾向が違うものなのではないですか? 確認ですが、コードは全く同じですよね? 未知の画像に行ってる前処理とかも、全く同じように学習と同じデータでのテスト時にもやってるのですよね?
quickquip

2021/07/07 08:56 編集

このコードの引用では、どういう順番でコードを実行しているのかがまったく分かりません。 追加されたコードの #学習済みmodelのロード,loaded_modelの定義 の行以降が特に、なぜこの順番でコードを書いたのかという感じです。
jbpb0

2021/07/07 09:15

> コード追加しました。 「#学習済みmodelのロード,loaded_modelの定義」 以下が、何をしたいのかがよく分かりません 学習時に torch.save(model.state_dict()... で保存したのだから、推論前にはそれを loaded_model = get_model(target_num=2) loaded_model.load_state_dict(torch.load(... みたいにして読み込めばいいのでは? 参考 https://qiita.com/jyori112/items/aad5703c1537c0139edb
jbpb0

2021/07/14 23:53

> train_model(model_ft,dataset_sizes,criterion,optimizer,40,False) の一番最後の「False」を「True」に変えたら、解決しました?
mmmw

2021/07/15 03:36

はい! 無事解決しました! 丁寧にありがとうございました!
guest

回答1

0

ベストアンサー

学習して保存したファイルが、推論時に読み込めてないのだと思います

学習時に

torch.save(model.state_dict()...

で保存したのだから、推論前にはそれを

loaded_model = get_model(target_num=2)
loaded_model.load_state_dict(torch.load(...

みたいにして読み込めばいいはず

参考
pytorchで書いたモデルを保存するときの落とし穴

【追記】

python

1train_model(model_ft,dataset_sizes,criterion,optimizer,40,False)

の一番最後の「False」を「True」に変えてください
「False」だと、下記の「if」のブロック内に入らないので、「torch.save(...」が実行されず、ファイルが保存されません

python

1 if(is_saved): 2 torch.save(model.state_dict(), './original_model_{}.pth'.format(epoch))

投稿2021/07/11 08:17

編集2021/07/15 12:56
jbpb0

総合スコア7651

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

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

mmmw

2021/07/12 13:48

# モデルを保存する modelname = './original_model_39.pth' torch.save(best_model.state_dict(), './original_model_39.pth') # 保存したモデルをロードする best_model.load_state_dict(torch.load('./original_model_39.pth')) 上記のようにして推論を行いましたが結果は全て1となってしまいました。
mmmw

2021/07/12 13:51

DEVICE='cpu' pred = [] # データの取り出し for i,(inputs,labels) in enumerate(test_dataloader): inputs = inputs.to(DEVICE) # 学習済みモデルを推論モードに設定 best_model.eval() # 学習済みモデルにデータをインプットし、推論をさせる outputs = best_model(inputs) print(outputs) # アウトプットから推定されたラベルを取得 _, preds = torch.max(outputs, 1) print(preds) # 事前に用意したリストに推論結果(0 or 1)を格納 pred.append(preds.item()) df_test['pred'] = pred 推論時 print(outputs)の出力 tensor([[-0.8853, 0.4932]], grad_fn=<AddmmBackward>) tensor([[-1.1691, 0.6413]], grad_fn=<AddmmBackward>) tensor([[-1.1033, 0.5890]], grad_fn=<AddmmBackward>) tensor([[-0.9872, 0.5423]], grad_fn=<AddmmBackward>) tensor([[-1.0249, 0.7072]], grad_fn=<AddmmBackward>) tensor([[-1.0435, 0.6158]], grad_fn=<AddmmBackward>) tensor([[-1.0264, 0.5959]], grad_fn=<AddmmBackward>) tensor([[-1.0207, 0.5663]], grad_fn=<AddmmBackward>) tensor([[-0.9573, 0.5645]], grad_fn=<AddmmBackward>) tensor([[-1.1792, 0.7562]], grad_fn=<AddmmBackward>) tensor([[-1.0705, 0.6143]], grad_fn=<AddmmBackward>) tensor([[-1.0799, 0.6218]], grad_fn=<AddmmBackward>) tensor([[-1.1085, 0.6325]], grad_fn=<AddmmBackward>) tensor([[-0.8851, 0.5191]], grad_fn=<AddmmBackward>) tensor([[-0.9672, 0.4900]], grad_fn=<AddmmBackward>) tensor([[-1.0455, 0.6422]], grad_fn=<AddmmBackward>) tensor([[-1.1043, 0.6111]], grad_fn=<AddmmBackward>) tensor([[-0.9879, 0.5619]], grad_fn=<AddmmBackward>) tensor([[-0.8457, 0.5090]], grad_fn=<AddmmBackward>) tensor([[-1.1233, 0.6662]], grad_fn=<AddmmBackward>) tensor([[-1.0699, 0.5969]], grad_fn=<AddmmBackward>) tensor([[-1.0843, 0.6357]], grad_fn=<AddmmBackward>) tensor([[-1.0144, 0.6174]], grad_fn=<AddmmBackward>) tensor([[-1.0377, 0.5507]], grad_fn=<AddmmBackward>) tensor([[-1.2456, 0.6934]], grad_fn=<AddmmBackward>) tensor([[-1.0622, 0.6313]], grad_fn=<AddmmBackward>) tensor([[-1.0636, 0.5362]], grad_fn=<AddmmBackward>) tensor([[-1.0886, 0.5673]], grad_fn=<AddmmBackward>) tensor([[-1.0653, 0.5717]], grad_fn=<AddmmBackward>) tensor([[-1.2548, 0.7473]], grad_fn=<AddmmBackward>) tensor([[-1.0888, 0.5714]], grad_fn=<AddmmBackward>) tensor([[-1.0377, 0.5115]], grad_fn=<AddmmBackward>) tensor([[-1.2323, 0.7421]], grad_fn=<AddmmBackward>) tensor([[-1.1485, 0.5583]], grad_fn=<AddmmBackward>) tensor([[-0.9932, 0.5815]], grad_fn=<AddmmBackward>) tensor([[-1.0676, 0.6239]], grad_fn=<AddmmBackward>) tensor([[-0.9621, 0.5216]], grad_fn=<AddmmBackward>) tensor([[-1.0553, 0.5725]], grad_fn=<AddmmBackward>) tensor([[-1.0944, 0.4924]], grad_fn=<AddmmBackward>) tensor([[-1.0327, 0.6520]], grad_fn=<AddmmBackward>) tensor([[-1.0865, 0.5760]], grad_fn=<AddmmBackward>) tensor([[-1.0192, 0.5931]], grad_fn=<AddmmBackward>) tensor([[-1.0974, 0.6040]], grad_fn=<AddmmBackward>) tensor([[-0.9593, 0.6139]], grad_fn=<AddmmBackward>) tensor([[-1.1394, 0.6442]], grad_fn=<AddmmBackward>) tensor([[-1.0430, 0.5631]], grad_fn=<AddmmBackward>) tensor([[-1.0722, 0.5764]], grad_fn=<AddmmBackward>) tensor([[-1.2496, 0.7532]], grad_fn=<AddmmBackward>) tensor([[-1.0176, 0.5748]], grad_fn=<AddmmBackward>) tensor([[-1.1585, 0.6079]], grad_fn=<AddmmBackward>) tensor([[-0.9577, 0.5878]], grad_fn=<AddmmBackward>) tensor([[-0.8968, 0.5290]], grad_fn=<AddmmBackward>) tensor([[-1.0076, 0.5999]], grad_fn=<AddmmBackward>) tensor([[-1.1908, 0.7615]], grad_fn=<AddmmBackward>) tensor([[-1.0322, 0.5917]], grad_fn=<AddmmBackward>) tensor([[-1.1246, 0.5309]], grad_fn=<AddmmBackward>) tensor([[-1.0327, 0.6321]], grad_fn=<AddmmBackward>) tensor([[-1.1346, 0.5611]], grad_fn=<AddmmBackward>) tensor([[-1.0876, 0.5585]], grad_fn=<AddmmBackward>) tensor([[-1.0674, 0.5161]], grad_fn=<AddmmBackward>) tensor([[-1.0935, 0.6111]], grad_fn=<AddmmBackward>) tensor([[-1.0719, 0.6171]], grad_fn=<AddmmBackward>) tensor([[-1.0685, 0.5682]], grad_fn=<AddmmBackward>) tensor([[-1.1760, 0.7044]], grad_fn=<AddmmBackward>) tensor([[-0.9218, 0.5737]], grad_fn=<AddmmBackward>) tensor([[-1.1098, 0.5763]], grad_fn=<AddmmBackward>) tensor([[-1.0538, 0.6444]], grad_fn=<AddmmBackward>) tensor([[-0.9151, 0.5954]], grad_fn=<AddmmBackward>) tensor([[-1.0879, 0.6704]], grad_fn=<AddmmBackward>) tensor([[-0.9731, 0.6462]], grad_fn=<AddmmBackward>) tensor([[-1.0484, 0.5898]], grad_fn=<AddmmBackward>) tensor([[-1.1741, 0.7469]], grad_fn=<AddmmBackward>) tensor([[-1.0645, 0.5611]], grad_fn=<AddmmBackward>) tensor([[-1.0665, 0.6149]], grad_fn=<AddmmBackward>) tensor([[-0.9382, 0.5231]], grad_fn=<AddmmBackward>) tensor([[-1.0286, 0.6163]], grad_fn=<AddmmBackward>) tensor([[-1.0311, 0.5607]], grad_fn=<AddmmBackward>) tensor([[-0.9333, 0.5564]], grad_fn=<AddmmBackward>) tensor([[-1.0346, 0.7192]], grad_fn=<AddmmBackward>) tensor([[-1.0548, 0.6115]], grad_fn=<AddmmBackward>) tensor([[-1.0845, 0.5361]], grad_fn=<AddmmBackward>) tensor([[-1.0824, 0.6066]], grad_fn=<AddmmBackward>) tensor([[-1.0142, 0.5809]], grad_fn=<AddmmBackward>) tensor([[-0.9936, 0.5825]], grad_fn=<AddmmBackward>) tensor([[-1.0563, 0.5492]], grad_fn=<AddmmBackward>) tensor([[-1.0346, 0.5965]], grad_fn=<AddmmBackward>) tensor([[-1.1155, 0.6583]], grad_fn=<AddmmBackward>) tensor([[-0.9975, 0.5068]], grad_fn=<AddmmBackward>) tensor([[-1.0644, 0.5095]], grad_fn=<AddmmBackward>) tensor([[-1.1065, 0.6197]], grad_fn=<AddmmBackward>) tensor([[-1.1591, 0.7534]], grad_fn=<AddmmBackward>) tensor([[-1.0675, 0.5804]], grad_fn=<AddmmBackward>) tensor([[-1.1412, 0.5738]], grad_fn=<AddmmBackward>) tensor([[-1.0799, 0.5972]], grad_fn=<AddmmBackward>) tensor([[-0.9989, 0.6235]], grad_fn=<AddmmBackward>) tensor([[-1.0503, 0.5523]], grad_fn=<AddmmBackward>) tensor([[-1.0855, 0.5865]], grad_fn=<AddmmBackward>) tensor([[-1.1982, 0.7267]], grad_fn=<AddmmBackward>) tensor([[-1.0635, 0.6263]], grad_fn=<AddmmBackward>) tensor([[-1.0470, 0.5836]], grad_fn=<AddmmBackward>) 推論時 print(pred)の出力 tensor([1]) tensor([1]) tensor([1]) tensor([1]) tensor([1]) tensor([1]) ... tensor([1]) tensor([1]) となりました。
jbpb0

2021/07/12 14:21 編集

> # モデルを保存する modelname = './original_model_39.pth' torch.save(best_model.state_dict(), './original_model_39.pth') は要らないです モデルの保存は、最初から質問に書かれてるコードの def train_model(... 内の # C. 今までのエポックでの精度よりも高い場合はモデルの保存 if phase == 'val' and epoch_acc > best_acc: best_acc = epoch_acc if(is_saved): torch.save(model.state_dict(), './original_model_{}.pth'.format(epoch)) で行われるのだから、それ以外のところでやったらダメです 質問に追加したコードの「#train_model呼び出し」の train_model(... を実行することにより、上記コードが実行されて、一番良かった時のモデルが保存されて、そのファイル名が print('./original_model_{}.pth'.format(epoch)) で表示されますよね 推論時は、そのファイル名を指定して、 > # 保存したモデルをロードする best_model.load_state_dict(torch.load('./original_model_39.pth')) を行なってください
mmmw

2021/07/12 14:33 編集

上記の方法で行ってみました。 ロード時にモデルが見つからないと下記エラーがでます。 [Errno 2] No such file or directory: './original_model_39.pth' フォルダをのぞいてもモデルが保存されていません。 最初から質問に書いているコードの if(is_saved): torch.save(model.state_dict(), './original_model_{}.pth'.format(epoch)) でうまくモデルが保存できていないのでしょうか...
jbpb0

2021/07/15 23:00 編集

> train_model(model_ft,dataset_sizes,criterion,optimizer,40,False) の一番最後の「False」を「True」に変えてみてください 「False」だと、下記の「if」のブロック内に入らないので、「torch.save(...」が実行されず、ファイルが保存されないと思います > if(is_saved): torch.save(model.state_dict(), './original_model_{}.pth'.format(epoch))
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問