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

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

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

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

Python 3.x

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

解決済

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

linkinpark
linkinpark

総合スコア31

PyTorch

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

Python 3.x

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

1回答

0評価

0クリップ

237閲覧

投稿2022/05/10 02:57

編集2022/05/13 23:06

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

Python

from __future__ import print_function from statistics import mode #from math import gamma #コマンドライン引数を受け取る処理をするモジュール import torch # ライブラリ「PyTorch」のtorchパッケージをインポート import torch.nn as nn # 「ニューラルネットワーク」モジュールの別名定義 import torch.nn.functional as F #様々な関数を持つクラス import torch.optim as optim#adam,SGDなどの最適化手法をもつモジュール from torchvision import datasets,transforms#データの前処理に必要なモジュール from torch.optim.lr_scheduler import StepLR#学習率の更新を行う関数 import pandas as pd from sklearn.model_selection import train_test_split import numpy as np import matplotlib.pyplot as plt import time class Net(nn.Module): def __init__(self): super(Net, self).__init__() input_size=torch.tensor([2]) #入力層 hidden_size=torch.tensor([20]) #中間層 output_size=torch.tensor([3]) #出力層 self.fc1 = nn.Linear(input_size,hidden_size) # Linearは「全結合層」を指す(入力層、出力層) self.fc2 = nn.Linear(hidden_size,output_size) # Linearは「全結合層」を指す(入力層、出力層) def forward(self, x): x = self.fc1(x) x = torch.sigmoid(x) x = self.fc2(x) output =torch.log_softmax(x, dim=1) return output #予測の精度を求める関数 def accuracy(self,x,t): y = self.forward(x) y=y.cpu().data.numpy() y = np.argmax(y, axis=1)#axis=列方向に見ていく(横) t=t.cpu().data.numpy() accuracy = np.sum(y == t) / float(x.shape[0]) return accuracy #データ分割 data = pd.read_table("3class.txt", sep=" ", header=None) x = data[0].values y = data[1].values t = data[2].values x_train, x_test,y_train,y_test,t_train, t_test = train_test_split(x,y,t,train_size=0.9) train_x=np.array([]) for i in range(len(x_train)): train_x = np.append(train_x,[ x_train[i] , y_train[i] ] ) train_x=train_x.reshape(len(x_train),2).astype(float) train_x = torch.FloatTensor(train_x)#Tensor型に変換 test_x=np.array([]) for i in range(len(x_test)): test_x = np.append(test_x,[ x_test[i] , y_test[i] ] ) test_x=test_x.reshape(len(x_test),2).astype(float) test_x = torch.FloatTensor(test_x)#Tensor型に変換 t_train = torch.LongTensor(t_train)#Tensor型に変換 t_test = torch.LongTensor(t_test)#Tensor型に変換 num=int(27*1e+4) batch_size=100 train_size=train_x.shape[0]#2702 epoch=int(max(int(train_size / batch_size), 1))#27 lr=0.1 seed=0 epoch_num=1 use_cuda =torch.cuda.is_available()#cudaを使えと指定されcudaが使える場合にcudaを使用 torch.manual_seed(seed)#疑似乱数を作る時に使う、元となる数字。 シード値が同じなら常に同じ乱数が作られる。(再現性がある) device = torch.device("cuda" if use_cuda else "cpu")#GPUを指定なければCPU device=torch.device("cpu") #GPUに送る train_x=train_x.to(device) train_t=t_train.to(device)#修正 test_x=test_x.to(device) test_t=t_test.to(device)#修正 train_loss_list = [] test_loss_list = [] train = [] test = [] epoch_num_list=[] model = Net().to(device)#netインスタンス生成。modelはレイヤーの構成親クラスを継承 optimizer = optim.SGD(model.parameters(),lr=0.1)#最適化手法,model.parameters():自動で重みとバイアスを設定してくれる scheduler = StepLR(optimizer, step_size=1,gamma=0.1)#step_size:更新タイミングのエポック数,gamma:更新率 #print(list(model.parameters())) # 開始 start_time = time.perf_counter() # ダミー処理 time.sleep(1) for i in range(num): #バッチ処理 batch_mask = np.random.choice(train_size, batch_size) x_batch = train_x[batch_mask] t_batch = train_t[batch_mask] model.train() output = model.forward(x_batch)#推論の結果をoutputに出力 loss = F.nll_loss(output,t_batch)#損失関数の関数 optimizer.zero_grad()#保持しているデータを初期化(勾配が累積されるため) loss.backward()#誤差逆伝搬法;勾配を求めている optimizer.step()#重みとバイアスをoptimizerを使って更新 scheduler.step()#学習率の更新 if i % (epoch) == 0: model.eval() train_acc = model.accuracy(train_x,train_t) test_acc = model.accuracy(test_x, test_t) train.append(train_acc) test.append(test_acc) output = model.forward(train_x) train_loss_list.append(F.nll_loss(output,train_t)) print(i,epoch_num, train_acc, test_acc,F.nll_loss(output,train_t).item()) output = model.forward(test_x) test_loss_list.append(F.nll_loss(output,test_t)) epoch_num_list.append(epoch_num) epoch_num=epoch_num+1 # 修了 end_time = time.perf_counter() # 経過時間を出力(秒) elapsed_time = end_time - start_time print(elapsed_time) #print(list(model.parameters())) train=torch.tensor(train) test=torch.tensor(test) train_loss_list=torch.tensor(train_loss_list) test_loss_list=torch.tensor(test_loss_list) train =train.cpu().data.numpy() test = test.cpu().data.numpy() train_loss_list = train_loss_list.cpu().data.numpy() test_loss_list = test_loss_list.cpu().data.numpy() plt.ylim([0,1.2]) #plt.plot(epoch_num_list,train,color='b',label='train') #plt.plot(epoch_num_list,test ,color='r',label='test') plt.plot(epoch_num_list,train_loss_list,color='b',label='train') plt.plot(epoch_num_list,test_loss_list ,color='r',label='test') plt.xlabel("epoch") plt.ylabel("loss") plt.legend() plt.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

train_x=np.array([]) for i in range(len(x_train)): train_x = np.append(train_x,[ x_train[i] , y_train[i] ] ) train_x=train_x.reshape(len(x_train),2).astype(float) train_x = torch.tensor(train_x,dtype=float,requires_grad=True)#Tensor型に変換,微分可能にする train_x=train_x.to(torch.float) test_x=np.array([]) for i in range(len(x_test)): test_x = np.append(test_x,[ x_test[i] , y_test[i] ] ) test_x=test_x.reshape(len(x_test),2).astype(float) test_x = torch.tensor(test_x,dtype=float,requires_grad=True)#Tensor型に変換,微分可能にする test_x=test_x.to(torch.float)

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

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でも進んでいました) 本当にありがとうございました!! また機会があればよろしくお願いします。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

PyTorch

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

Python 3.x

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