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

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

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

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1119閲覧

重みが更新されているのに損失関数の値や精度が向上しない

linkinpark

総合スコア42

PyTorch

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/05/10 02:57

編集2022/05/10 15:49

pytorchを用いて三重螺旋の学習を行わせているのですが、重みが更新されているのに損失関数の値や精度が一向に向上しません。
またネットで調べてみてもどのようにすればよいのかわかりませんでした。ぜひアドバイスが欲しいです。よろしくお願いいたします。

Python

1from __future__ import print_function 2from statistics import mode 3#from math import gamma #コマンドライン引数を受け取る処理をするモジュール 4import torch # ライブラリ「PyTorch」のtorchパッケージをインポート 5import torch.nn as nn # 「ニューラルネットワーク」モジュールの別名定義 6import torch.nn.functional as F #様々な関数を持つクラス 7import torch.optim as optim#adam,SGDなどの最適化手法をもつモジュール 8from torchvision import datasets,transforms#データの前処理に必要なモジュール 9from torch.optim.lr_scheduler import StepLR#学習率の更新を行う関数 10import pandas as pd 11from sklearn.model_selection import train_test_split 12import numpy as np 13import matplotlib.pyplot as plt 14import time 15 16class Net(nn.Module): 17 def __init__(self): 18 super(Net, self).__init__() 19 input_size=torch.tensor([2]) #入力層 20 hidden_size=torch.tensor([20]) #中間層 21 output_size=torch.tensor([3]) #出力層 22 self.fc1 = nn.Linear(input_size,hidden_size) # Linearは「全結合層」を指す(入力層、出力層) 23 self.fc2 = nn.Linear(hidden_size,output_size) # Linearは「全結合層」を指す(入力層、出力層) 24 25 def forward(self, x): 26 x = self.fc1(x) 27 x = torch.sigmoid(x) 28 x = self.fc2(x) 29 output =torch.log_softmax(x, dim=1) 30 return output 31 32 #予測の精度を求める関数 33 34 def accuracy(self,x,t): 35 y = self.forward(x) 36 y=y.cpu().data.numpy() 37 y = np.argmax(y, axis=1)#axis=列方向に見ていく(横) 38 t=t.cpu().data.numpy() 39 accuracy = np.sum(y == t) / float(x.shape[0]) 40 return accuracy 41 42#データ分割 43data = pd.read_table("3class.txt", sep=" ", header=None) 44x = data[0].values 45y = data[1].values 46t = data[2].values 47 48x_train, x_test,y_train,y_test,t_train, t_test = train_test_split(x,y,t,train_size=0.9) 49 50 51train_x=np.array([]) 52for i in range(len(x_train)): 53 train_x = np.append(train_x,[ x_train[i] , y_train[i] ] ) 54 55train_x=train_x.reshape(len(x_train),2).astype(float) 56train_x = torch.FloatTensor(train_x)#Tensor型に変換 57 58test_x=np.array([]) 59for i in range(len(x_test)): 60 test_x = np.append(test_x,[ x_test[i] , y_test[i] ] ) 61 62test_x=test_x.reshape(len(x_test),2).astype(float) 63test_x = torch.FloatTensor(test_x)#Tensor型に変換 64 65t_train = torch.LongTensor(t_train)#Tensor型に変換 66t_test = torch.LongTensor(t_test)#Tensor型に変換 67 68num=int(27*1e+4) 69batch_size=100 70train_size=train_x.shape[0]#2702 71epoch=int(max(int(train_size / batch_size), 1))#27 72lr=0.1 73seed=0 74epoch_num=1 75 76use_cuda =torch.cuda.is_available()#cudaを使えと指定されcudaが使える場合にcudaを使用 77torch.manual_seed(seed)#疑似乱数を作る時に使う、元となる数字。 シード値が同じなら常に同じ乱数が作られる。(再現性がある) 78 79device = torch.device("cuda" if use_cuda else "cpu")#GPUを指定なければCPU 80device=torch.device("cpu") 81#GPUに送る 82train_x=train_x.to(device) 83train_t=t_train.to(device)#修正 84test_x=test_x.to(device) 85test_t=t_test.to(device)#修正 86 87train_loss_list = [] 88test_loss_list = [] 89train = [] 90test = [] 91epoch_num_list=[] 92 93model = Net().to(device)#netインスタンス生成。modelはレイヤーの構成親クラスを継承 94optimizer = optim.SGD(model.parameters(),lr=0.1)#最適化手法,model.parameters():自動で重みとバイアスを設定してくれる 95scheduler = StepLR(optimizer, step_size=1,gamma=0.1)#step_size:更新タイミングのエポック数,gamma:更新率 96 97#print(list(model.parameters())) 98# 開始 99start_time = time.perf_counter() 100 101# ダミー処理 102time.sleep(1) 103 104for i in range(num): 105 #バッチ処理 106 batch_mask = np.random.choice(train_size, batch_size) 107 x_batch = train_x[batch_mask] 108 t_batch = train_t[batch_mask] 109 110 model.train() 111 output = model.forward(x_batch)#推論の結果をoutputに出力 112 loss = F.nll_loss(output,t_batch)#損失関数の関数 113 optimizer.zero_grad()#保持しているデータを初期化(勾配が累積されるため) 114 loss.backward()#誤差逆伝搬法;勾配を求めている 115 optimizer.step()#重みとバイアスをoptimizerを使って更新 116 scheduler.step()#学習率の更新 117 118 if i % (epoch) == 0: 119 model.eval() 120 train_acc = model.accuracy(train_x,train_t) 121 test_acc = model.accuracy(test_x, test_t) 122 train.append(train_acc) 123 test.append(test_acc) 124 output = model.forward(train_x) 125 train_loss_list.append(F.nll_loss(output,train_t)) 126 print(i,epoch_num, train_acc, test_acc,F.nll_loss(output,train_t).item()) 127 output = model.forward(test_x) 128 test_loss_list.append(F.nll_loss(output,test_t)) 129 epoch_num_list.append(epoch_num) 130 epoch_num=epoch_num+1 131# 修了 132end_time = time.perf_counter() 133 134# 経過時間を出力(秒) 135elapsed_time = end_time - start_time 136print(elapsed_time) 137#print(list(model.parameters())) 138 139train=torch.tensor(train) 140test=torch.tensor(test) 141train_loss_list=torch.tensor(train_loss_list) 142test_loss_list=torch.tensor(test_loss_list) 143 144train =train.cpu().data.numpy() 145test = test.cpu().data.numpy() 146train_loss_list = train_loss_list.cpu().data.numpy() 147test_loss_list = test_loss_list.cpu().data.numpy() 148 149plt.ylim([0,1.2]) 150#plt.plot(epoch_num_list,train,color='b',label='train') 151#plt.plot(epoch_num_list,test ,color='r',label='test') 152plt.plot(epoch_num_list,train_loss_list,color='b',label='train') 153plt.plot(epoch_num_list,test_loss_list ,color='r',label='test') 154plt.xlabel("epoch") 155plt.ylabel("loss") 156plt.legend() 157plt.show()

実行結果(一部切り抜き)
エポック数、訓練精度、テスト精度、損失関数の値
9980 0.33641746854182086 0.30564784053156147 1.1340349912643433
9981 0.33641746854182086 0.30564784053156147 1.1340349912643433
9982 0.33641746854182086 0.30564784053156147 1.1340349912643433
9983 0.33641746854182086 0.30564784053156147 1.1340349912643433
9984 0.33641746854182086 0.30564784053156147 1.1340349912643433
9985 0.33641746854182086 0.30564784053156147 1.1340349912643433
9986 0.33641746854182086 0.30564784053156147 1.1340349912643433
9987 0.33641746854182086 0.30564784053156147 1.1340349912643433
9988 0.33641746854182086 0.30564784053156147 1.1340349912643433
9989 0.33641746854182086 0.30564784053156147 1.1340349912643433
9990 0.33641746854182086 0.30564784053156147 1.1340349912643433
9991 0.33641746854182086 0.30564784053156147 1.1340349912643433
9992 0.33641746854182086 0.30564784053156147 1.1340349912643433
9993 0.33641746854182086 0.30564784053156147 1.1340349912643433
9994 0.33641746854182086 0.30564784053156147 1.1340349912643433
9995 0.33641746854182086 0.30564784053156147 1.1340349912643433
9996 0.33641746854182086 0.30564784053156147 1.1340349912643433
9997 0.33641746854182086 0.30564784053156147 1.1340349912643433
9998 0.33641746854182086 0.30564784053156147 1.1340349912643433
9999 0.33641746854182086 0.30564784053156147 1.1340349912643433
10000 0.33641746854182086 0.30564784053156147 1.1340349912643433

追加

Python

1train_x=np.array([]) 2for i in range(len(x_train)): 3 train_x = np.append(train_x,[ x_train[i] , y_train[i] ] ) 4 5train_x=train_x.reshape(len(x_train),2).astype(float) 6train_x = torch.tensor(train_x,dtype=float,requires_grad=True)#Tensor型に変換,微分可能にする 7train_x=train_x.to(torch.float) 8 9test_x=np.array([]) 10for i in range(len(x_test)): 11 test_x = np.append(test_x,[ x_test[i] , y_test[i] ] ) 12 13test_x=test_x.reshape(len(x_test),2).astype(float) 14test_x = torch.tensor(test_x,dtype=float,requires_grad=True)#Tensor型に変換,微分可能にする 15test_x=test_x.to(torch.float)

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

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

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

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

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

linkinpark

2022/05/10 15:47

x_batchが微分可能ではなかったので微分可能にするように修正しました。 しかしそれでも損失関数の値は全く変わっていませんでした。
jbpb0

2022/05/12 04:50 編集

「3class.txt」の内容が分からないので、データを x = np.random.rand(3003) y = np.random.rand(3003) t = (x * x + y * y) * 1.5 と適当にでっちあげて実行してみたところ、学習ループ内の scheduler.step()#学習率の更新 を削除したら、学習が進みました 0 1 0.5203552923760177 0.5348837209302325 0.9911680221557617 27 2 0.5203552923760177 0.5348837209302325 0.8898512721061707 54 3 0.5203552923760177 0.5348837209302325 0.8776270151138306  (中略) 269919 9998 0.9929681717246485 0.9933554817275747 0.026275327429175377 269946 9999 0.9925980754996299 0.9900332225913622 0.026202505454421043 269973 10000 0.9922279792746114 0.9933554817275747 0.02624298818409443 データに依存するかもしれないので、質問者さんがやってる条件で効果あるかは分かりませんが 【追記】 質問の「追加」に気付かず、上に書いた相違点以外は、質問の一番上に記載のコードで実行しました
linkinpark

2022/05/12 10:23

ありがとうございます!! 何度も申し訳ないのですが、スケジューラーを削除するとなぜ学習が進むのか教えてもらえませんか?
jbpb0

2022/05/12 11:01

> スケジューラーを削除するとなぜ学習が進むのか 「StepLR(optimizer, step_size=1,gamma=0.1)」だと、毎回学習率が1/10になるので、 0.1, 0.01, 0.001, 0.0001... と急速に学習率が小さくなりすぎてしまうからだと思います https://qiita.com/koshian2/items/4c27c887438a52062d97 の一番上のグラフを見てください 横軸が20000あたりからあまり下がらなくなっているのが、横軸32000のところでガクッと下がってますよね そこで学習率を1/10(0.1→0.01)に変えた効果です 学習率を変えるタイミングは、上記のように「loss」があまり下がらなくなってきた頃に行うのが効果的です まずは学習率一定で行ってみて、「loss」がどこまで下がるのかを確認して、もっと下げたければどのタイミングが効果的かを考えて、そこではじめて学習率を途中で変える設定を追加するのです
linkinpark

2022/05/12 11:33

とても参考になりました。今回の場合ですとロスが全然下がっていないのに学習率を低下させていたため 学習が進まなかったという認識でよろしいでしょうか?
jbpb0

2022/05/12 12:18

> ロスが全然下がっていないのに学習率を低下させていたため学習が進まなかった そうですね 付け加えると、毎回1/10は、lossがある程度下がった後だったとしても、急すぎると思います ところで、「3class.txt」のデータの場合も、「scheduler.step()」を削除したら、学習が進むのでしょうか?
linkinpark

2022/05/13 02:48

エポック数、訓練精度、テスト精度、損失関数の値 1 0.3316062176165803 0.3488372093023256 1.117761492729187 2 0.3804589193190229 0.34551495016611294 1.094038963317871 3 0.36935603256846783 0.3521594684385382 1.0900559425354004 4 0.3630643967431532 0.33222591362126247 1.0891376733779907 5 0.3549222797927461 0.33222591362126247 1.0914580821990967 6 0.35714285714285715 0.3222591362126246 1.0865081548690796 7 0.346039970392302 0.3588039867109635 1.0875911712646484 8 0.3545521835677276 0.3654485049833887 1.085936188697815 1993 0.9356032568467801 0.9269102990033222 0.20271606743335724 1994 0.9359733530717986 0.9302325581395349 0.20558935403823853 1995 0.9356032568467801 0.9335548172757475 0.20198504626750946 1996 0.9344929681717247 0.9302325581395349 0.20387524366378784 1997 0.9363434492968171 0.9401993355481728 0.2028283327817917 1998 0.9385640266469282 0.9401993355481728 0.20413526892662048 1999 0.9385640266469282 0.9368770764119602 0.20219630002975464 2000 0.9348630643967432 0.9302325581395349 0.20283257961273193 損失関数の値の収束が遅いので今回はoptimizerをアダムにしています。 スケジューラーを削除したところ無事学習が進みました!!(SGDでも進んでいました) 本当にありがとうございました!! また機会があればよろしくお願いします。
guest

回答1

0

ベストアンサー

python

1scheduler = StepLR(optimizer, step_size=1,gamma=0.1)#step_size:更新タイミングのエポック数,gamma:更新率

だと、毎回学習率が1/10になるので、
0.1, 0.01, 0.001, 0.0001...
と急速に学習率が小さくなりすぎてしまい、学習が進みません

 
学習ループ内の

python

1 scheduler.step()#学習率の更新

を削除してみてください

投稿2022/05/13 13:27

jbpb0

総合スコア7651

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

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

linkinpark

2022/05/13 14:06

改めてありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問