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

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

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

CUDAは並列計算プラットフォームであり、Nvidia GPU(Graphics Processing Units)向けのプログラミングモデルです。CUDAは様々なプログラミング言語、ライブラリ、APIを通してNvidiaにインターフェイスを提供します。

深層学習

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

PyTorch

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

機械学習

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

Python

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

Q&A

解決済

1回答

6560閲覧

いくらepochを大きくしても損失関数lossの値が下がらないのはなぜ??

oinari03

総合スコア59

CUDA

CUDAは並列計算プラットフォームであり、Nvidia GPU(Graphics Processing Units)向けのプログラミングモデルです。CUDAは様々なプログラミング言語、ライブラリ、APIを通してNvidiaにインターフェイスを提供します。

深層学習

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

PyTorch

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

機械学習

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

Python

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

0グッド

0クリップ

投稿2020/09/03 07:02

やりたいこと

損失関数の値をできるだけ小さい値に収束させたい

ところが、10,100,300とepochの値を増やしても、同じ位置に収束してしまっていて?、できるだけlossの値を下げようと思っています。

しかし、epochをこれ以上上げるべきなのか、どれだけ上げるべきなのか、はたまた違う要因があるのか、ご指摘くださると幸いです。

<前提>
256x256x3の犬と猫の画像をcnnで分類しています。
pc: gpu
windows
wsl ubuntu18.04
python3.7.7

実行結果(train.py)

epoch=300くらいだったと思います。
大体0.69~ 0.74くらいを行ったり来たりです。
これをもう少し下げたいです。

・ ・ ・ torch.Size([32, 9216]) tensor(0.6920, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([1, 9216]) tensor(0.7015, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6942, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6942, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6916, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6921, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([1, 9216]) tensor(0.7015, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6936, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6937, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6931, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([32, 9216]) tensor(0.6920, device='cuda:0', grad_fn=<NllLossBackward>) torch.Size([1, 9216]) tensor(0.6848, device='cuda:0', grad_fn=<NllLossBackward>)

コード(train.py)

こちらが実行ファイルです。model.pyやdataset.pyを別々に作ってそこから呼び出してlossの値を確認しています。

python

1import torch 2import torch.nn as nn 3import torch.nn.functional as F 4 5import torch.optim as optim 6import model,dataset 7from model import * 8 9from tqdm import tqdm 10from torch.autograd import Variable 11 12 13 14 15#一つの機能を作ったら→pritで確認 16device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 17 18 19# 上でgpuの設定device 20if __name__ == "__main__": 21 # modelの定義 22 model = model.Net().to(device) 23 print(model) 24 25 26 27 # optimizerの定義 28 optimizer = torch.optim.SGD( 29 model.parameters(), lr=0.001, momentum=0.9, weight_decay=0.0001) 30 31 # datasetの定義 32 # training 33 train_dataset = dataset.MyDatasets( 34 root_dir="./animal_dataset", 35 key="train", 36 ) 37 train_loader = torch.utils.data.DataLoader( 38 train_dataset, 39 batch_size=32, 40 shuffle= True 41 ) 42 43 # validation 44 valid_dataset = dataset.MyDatasets( 45 root_dir="./animal_dataset", 46 key="val", 47 ) 48 49 valid_loader = torch.utils.data.DataLoader( 50 valid_dataset, 51 batch_size=32, 52 shuffle= True 53 ) 54 55 56 # iterationの確定 57 sample_size = len(train_dataset) #129 58 num_iters = sample_size // 32 #129 // 32 = 4.03 59 60 #loss 61 criterion = nn.CrossEntropyLoss() 62 63 #start epoch 64 for epoch in range(300): # loop over the dataset multiple times 65 running_loss = 0.0 66 for i, data in enumerate(train_loader, 0): 67 # get the inputs; data is a list of [inputs, labels] 68 inputs, labels = data[0].to(device), data[1].to(device) 69 # zero the parameter gradients 70 optimizer.zero_grad() 71 # forward + backward + optimize 72 outputs = model(inputs) 73 loss = criterion(outputs, labels) 74 print(loss) 75 76 # loss.backward() 77 # optimizer.step() 78 79 # # print statistics 80 # running_loss += loss.item() 81 # if i % 2000 == 1999: # print every 2000 mini-batches 82 # print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) 83 # running_loss = 0.0 84 85 print('Finished Training') 86

cnnのmodel.pyです。

import torch import torch.nn as nn import torch.nn.functional as F """ 入力は256x256のRGB画像 出力は0or1の2次元ベクトルになるはず """ class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.relu = nn.ReLU() # input: RGB 3 ,output : 16, kernel 3(default) self.conv1 = nn.Conv2d(3, 16, 3) # print(self.conv1.weight) self.pool1 = nn.MaxPool2d(2,stride=2) self.conv2 = nn.Conv2d(16, 32, 3) self.pool2 = nn.MaxPool2d(2,stride=2) self.conv3 = nn.Conv2d(32, 64, 3) self.pool3 = nn.MaxPool2d(2,stride=2) self.conv4 = nn.Conv2d(64, 128, 3) self.pool4 = nn.MaxPool2d(2,stride=2) self.conv5 = nn.Conv2d(128, 256, 3) self.pool5 = nn.MaxPool2d(2,stride=2) # an affine operation: y = Wx + b # linearにおけるout_featuresとはなんだろうか self.fc1 = nn.Linear(9216, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 2) def forward(self, x): # conv relu poolの流れを実行してみる x = self.conv1(x) x = self.relu(x) x = self.pool1(x) x = self.conv2(x) x = self.relu(x) x = self.pool2(x) x = self.conv3(x) x = self.relu(x) x = self.pool3(x) x = self.conv4(x) x = self.relu(x) x = self.pool4(x) x = self.conv5(x) x = self.relu(x) x = self.pool5(x) x = x.view(x.size()[0], -1) print(x.shape) x = self.fc1(x) x = self.relu(x) x = self.fc2(x) x = self.relu(x) x = self.fc3(x) return F.log_softmax(x,dim=1) if __name__ == "__main__": input = torch.randn(1,3,256,256) net = Net() print(net(input)) #動作確認

動作確認用でいろいろ入っていますが....
こんな感じです。cnnの作り方がよろしくないのでしょうか....

まとめ

以上の情報からlossをいかに低い値で収束させることができましたらお願いできますとありがたいです。

どういった原因があるのか、どこを編集すればいい結果が得られるのかがわかりません。
未熟のみであるので、足らない点があればご指摘してくださると助かります。

どうかよろしくお願いいたします。

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

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

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

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

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

tiitoi

2020/09/03 07:15

画像枚数にもよりますが、学習済みモデルを使わない学習なら70~75%とかそんなもんだと思います。学習済みモデル使えば90%近くまでいくとは思いますが。
oinari03

2020/09/03 07:20

画像枚数は 犬 train:70 val:30 猫 train: 70 val:30 くらいです。 学習済みモデルをつかう以外の方法でもう少しlossの値をを下げる方法はないのでしょうか...?
tiitoi

2020/09/03 07:25

画像枚数を増やすことが必要です。 その枚数で学習するのであれば、オーグメンテーションや学習率の調整で多少は改善する可能性はありますが、フルスクラッチ学習 (0からの学習) にしては学習枚数が少なすぎるので、学習済みモデルを使わないと大きな改善は経験上困難と思います。
oinari03

2020/09/03 07:36

なるほど、ご経験上であるとしたらたすかります。 大変失礼かと思いますが、 学習曲線(lossの値をepochごとにプロットしたグラフ)を作っていったん学習を見てみようと思うのですが、どのように実装すればいいのでしょうか...? 恐縮ですが、ご教授いただければと思います。
tiitoi

2020/09/03 07:50

回答のほうに記載しました。
guest

回答1

0

ベストアンサー

学習曲線(lossの値をepochごとにプロットしたグラフ)を作っていったん学習を見てみようと思うのですが、どのように実装すればいいのでしょうか...?

エポックごとにそのエポックの loss の平均を計算し、それをリストに追加していって、あとから matplotlib で描画すればよいと思います。

変更箇所一部抜粋

losses = [] for epoch in range(300): # loop over the dataset multiple times epoch_loss = [] 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) # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = model(inputs) loss = criterion(outputs, labels) epoch_loss.append(float(loss)) losses.append(np.mean(epoch_loss)) # そのエポックの損失の平均を記録

最後に以下を実行

python

1import numpy as np 2from matplotlib import pyplot as plt 3 4def plot_history(losses): 5 fig, ax = plt.subplots() 6 7 epochs = np.arange(1, len(losses) + 1) 8 9 # 損失の推移 10 ax.set_title("Loss") 11 ax.plot(epochs, losses) 12 ax.set_xlabel("Epoch") 13 14 plt.show() 15 16 17plot_history(losses)

投稿2020/09/03 07:50

編集2020/09/03 08:31
tiitoi

総合スコア21956

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

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

oinari03

2020/09/03 08:20 編集

何から何まで本当にありがとうございます。 グラフにするコードを全体内に入れましたので、ご確認していただければと思います。 mean()は使えなかったので、epoch_numで割る形に変更しましたが、意図はあっていますでしょうか。 ``` 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 #一つの機能を作ったら→pritで確認 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 上でgpuの設定device if __name__ == "__main__": # modelの定義 model = model.Net().to(device) print(model) # optimizerの定義 optimizer = torch.optim.SGD( model.parameters(), lr=0.001, 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=32, shuffle= True ) # validation valid_dataset = dataset.MyDatasets( root_dir="./animal_dataset", key="val", ) valid_loader = torch.utils.data.DataLoader( valid_dataset, batch_size=32, 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 // 32 #129 // 32 = 4.03 #loss criterion = nn.CrossEntropyLoss() losses = [] #start epoch epoch_num = 10 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) # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = model(inputs) loss = criterion(outputs, labels) epoch_loss += loss losses.append(np.mean(epoch_loss)) print('Finished Training') 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) ```
tiitoi

2020/09/03 08:15 編集

すいません。loss.mean() のところ間違ってたので、回答を修正しました。 それを反映させて、エポック数10とかで動かしてみてとりあえずグラフが表示されることを確認してみてはどうでしょうか
oinari03

2020/09/03 08:24

修正ありがとうございます。 ただ、グラフの表示の部分なのですが、回答のように修正させていただきましたが、np.mean()のように修正させていただきましたが、グラフの表示を確認できませんでした。 以下のようなエラーを吐いてしまったため、お時間があればご回答願いますとありがたいです。 ``` torch.Size([32, 9216]) torch.Size([32, 9216]) torch.Size([32, 9216]) torch.Size([32, 9216]) torch.Size([1, 9216]) Traceback (most recent call last): File "train.py", line 87, in <module> losses.append(np.mean(epoch_loss)) File "<__array_function__ internals>", line 6, in mean File "/home/hirayama/mymodel/venv/lib/python3.7/site-packages/numpy/core/fromnumeric.py", line 3370, in mean return mean(axis=axis, dtype=dtype, out=out, **kwargs) TypeError: mean() received an invalid combination of arguments - got (out=NoneType, axis=NoneType, dtype=NoneType, ), but expected one of: * (*, torch.dtype dtype) * (tuple of names dim, bool keepdim, *, torch.dtype dtype) * (tuple of ints dim, bool keepdim, *, torch.dtype dtype) ```
tiitoi

2020/09/03 08:32

もう一点修正必要でした loss が torch.float32 型になっているので、float() でPython のfloat 型に変換が必要です。 epoch_loss.append(loss) ↓ epoch_loss.append(float(loss))
oinari03

2020/09/03 09:00

長々とありがとうございます!!!! なんとかグラフを表示することができました。 グラフとしては かなりギザギザで、まったく収束していないグラフになってしまいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問