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

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

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

Chainerは、国産の深層学習フレームワークです。あらゆるニューラルネットワークをPythonで柔軟に書くことができ、学習させることが可能。GPUをサポートしており、複数のGPUを用いた学習も直感的に記述できます。

機械学習

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

Q&A

解決済

Chainerの学習がうまくいかない

shinww
shinww

総合スコア4

Chainer

Chainerは、国産の深層学習フレームワークです。あらゆるニューラルネットワークをPythonで柔軟に書くことができ、学習させることが可能。GPUをサポートしており、複数のGPUを用いた学習も直感的に記述できます。

機械学習

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

1回答

0グッド

0クリップ

457閲覧

投稿2022/10/10 07:33

編集2022/10/10 16:01

前提

chainerで画像分類の実験を行っています。学習させたモデルでテストを行うと0.1%しか出ないという状態です。
画像のデータセットについては特に問題ないと考えています。

実現したいこと

  • 問題の解決

該当のソースコード

python

1テスト用のコード 2 3#!/usr/bin/env python 4"""Example code of learning a large scale convnet from ILSVRC2012 dataset. 5 6Prerequisite: To run this example, crop the center of ILSVRC2012 training and 7validation images and scale them to 256x256, and make two lists of space- 8separated CSV whose first column is full path to image and second column is 9zero-origin label (this format is same as that used by Caffe's ImageDataLayer). 10 11""" 12from __future__ import print_function 13import argparse 14import datetime 15import json 16import multiprocessing 17import random 18import sys 19import threading 20import time 21 22import numpy as np 23from PIL import Image 24 25 26import six 27import six.moves.cPickle as pickle 28import _pickle as cPickle #変更 29from six.moves import queue 30 31import chainer 32import matplotlib.pyplot as plt 33import numpy as np 34import math 35import chainer.functions as F 36import chainer.links as L 37from chainer.links import caffe 38from matplotlib.ticker import * 39from chainer import serializers 40 41from functools import cmp_to_key #追加 42 43 44 45parser = argparse.ArgumentParser( 46 description='Image inspection using chainer') 47parser.add_argument('image', help='Path to inspection image file') 48parser.add_argument('--model','-m',default='model', help='Path to model file') 49parser.add_argument('--mean', default='mean.npy', 50 help='Path to the mean file (computed by compute_mean.py)') 51parser.add_argument('--out', '-o') 52args = parser.parse_args() 53 54 55def read_image(path, center=False, flip=False): 56 image = np.asarray(Image.open(path)).transpose(2, 0, 1) 57 if center: 58 top = left = cropwidth // 2 59 else: 60 top = random.randint(0, cropwidth - 1) 61 left = random.randint(0, cropwidth - 1) 62 bottom = model.insize + top 63 right = model.insize + left 64 image = image[:, top:bottom, left:right].astype(np.float32) 65 image -= mean_image[:, top:bottom, left:right] 66 image /= 255 67 if flip and random.randint(0, 1) == 0: 68 return image[:, :, ::-1] 69 else: 70 return image 71 72import nin 73 74mean_image = cPickle.load(open(args.mean, 'rb')) 75 76model = cPickle.load(open(args.model,'rb')) 77 78#mean_image = cPickle.load(open(args.mean, 'rb')) 79#model = cPickle.load(open(args.model,'rb',)) 80 81#serializers.load_hdf5("gpu1out.h5", model) 82cropwidth = 256 - model.insize 83model.to_cpu() 84 85 86def predict(net, x): 87 h = F.max_pooling_2d(F.relu(net.mlpconv1(x)), 3, stride=2) 88 h = F.max_pooling_2d(F.relu(net.mlpconv2(h)), 3, stride=2) 89 h = F.max_pooling_2d(F.relu(net.mlpconv3(h)), 3, stride=2) 90 #h = net.mlpconv4(F.dropout(h, train=net.train)) 91 h = net.mlpconv4(F.dropout(h)) 92 h = F.reshape(F.average_pooling_2d(h, 6), (x.data.shape[0], 1000)) 93 return F.softmax(h) 94 95#setattr(model, 'predict', predict) 96 97img = read_image(args.image) 98x = np.ndarray( 99 (1, 3, model.insize, model.insize), dtype=np.float32) 100x[0]=img 101#x = chainer.Variable(np.asarray(x), volatile='on') 102x= chainer.Variable(np.asarray(x)) 103with chainer.no_backprop_mode(): 104 105 score = predict(model,x) 106#score=cuda.to_cpu(score.data) 107 108categories = np.loadtxt("labels.txt", str, delimiter="\t") 109 110top_k = 20 111#↓list()を追加 112prediction = list(zip(score.data[0].tolist(), categories)) 113#prediction.sort(cmp=lambda x, y: cmp(x[0], y[0]), reverse=True) 114prediction.sort (key=lambda x: x[0],reverse=True) 115 116for rank, (score, name) in enumerate(prediction[:top_k], start=1): 117 print('#%d | %s | %4.1f%%' % (rank, name, score * 100)) 118 119 120今回使用した nin.py 121import math 122import chainer 123import chainer.functions as F 124import chainer.links as L 125 126 127class NIN(chainer.Chain): 128 129 """Network-in-Network example model.""" 130 131 insize = 227 132 133 def __init__(self): 134 w = math.sqrt(2) # MSRA scaling 135 super(NIN, self).__init__( 136 mlpconv1=L.MLPConvolution2D( 137 3, (96, 96, 96), 11, stride=4), 138 mlpconv2=L.MLPConvolution2D( 139 96, (256, 256, 256), 5, pad=2), #wscale=w削除 140 mlpconv3=L.MLPConvolution2D( 141 256, (384, 384, 384), 3, pad=1), 142 mlpconv4=L.MLPConvolution2D( 143 384, (1024, 1024, 1000), 3, pad=2), 144 ) 145 self.train = True 146 147 def clear(self): 148 self.loss = None 149 self.accuracy = None 150 151 def __call__(self, x, t): 152 self.clear() 153 h = F.max_pooling_2d(F.relu(self.mlpconv1(x)), 3, stride=2) 154 h = F.max_pooling_2d(F.relu(self.mlpconv2(h)), 3, stride=2) 155 h = F.max_pooling_2d(F.relu(self.mlpconv3(h)), 3, stride=2) 156 h = self.mlpconv4(F.dropout(h)) #変更 157 h = F.reshape(F.average_pooling_2d(h, 6), (x.data.shape[0], 1000)) 158 159 self.loss = F.softmax_cross_entropy(h, t) 160 self.accuracy = F.accuracy(h, t) 161 return self.loss 162 163 def predict(self, x_data, train=False): 164 x = chainer.Variable(x_data, volatile=True) 165 166 h = F.relu(self.conv1(x)) 167 h = F.relu(self.conv1a(h)) 168 h = F.relu(self.conv1b(h)) 169 h = F.max_pooling_2d(h, 3, stride=2) 170 h = F.relu(self.conv2(h)) 171 h = F.relu(self.conv2a(h)) 172 h = F.relu(self.conv2b(h)) 173 h = F.max_pooling_2d(h, 3, stride=2) 174 h = F.relu(self.conv3(h)) 175 h = F.relu(self.conv3a(h)) 176 h = F.relu(self.conv3b(h)) 177 h = F.max_pooling_2d(h, 3, stride=2) 178 h = F.dropout(h, train=train) 179 h = F.relu(self.conv4(h)) 180 h = F.relu(self.conv4a(h)) 181 h = F.relu(self.conv4b(h)) 182 h = F.reshape(F.average_pooling_2d(h, 6), (x_data.shape[0], 1000)) 183 return F.softmax(h) 184 185学習用のコード 186def train_loop(): 187 # Trainer 188 graph_generated = False 189 while True: 190 while data_q.empty(): 191 time.sleep(0.1) 192 inp = data_q.get() 193 if inp == 'end': # quit 194 res_q.put('end') 195 break 196 elif inp == 'train': # restart training 197 res_q.put('train') 198 model.train = True 199 continue 200 elif inp == 'val': # start validation 201 res_q.put('val') 202 #serializers.save_npz(args.out, model) 203 #model.to_cpu() 204 pickle.dump(model, open(args.out, 'wb'), -1) 205 serializers.save_npz(args.outstate, optimizer) 206 model.train = False 207 continue 208 209 volatile = 'off'if model.train else 'on' 210 #x = chainer.Variable(xp.asarray(inp[0]), volatile=volatile) 211 x = chainer.Variable(xp.asarray(inp[0])) 212 with chainer.no_backprop_mode(): 213 #t = chainer.Variable(xp.asarray(inp[1]),volatile=volatile) 214 t = chainer.Variable(xp.asarray(inp[1])) 215 with chainer.no_backprop_mode(): 216    #if model train: 217 if model: 218 optimizer.update(model, x, t) 219 if not graph_generated: 220 with open('graph.dot', 'w') as o: 221 o.write(computational_graph.build_computational_graph( 222 (model.loss,)).dump()) 223 print('generated graph', file=sys.stderr) 224 graph_generated = True 225 else: 226 model(x, t) 227 res_q.put((float(model.loss.data), float(model.accuracy.data))) 228 del x, t 229 230data_qにデータを入れる 231 232 def feed_data(): 233 # Data feeder 234 i = 0 235 count = 0 236 237 x_batch = np.ndarray( 238 (args.batchsize, 3, model.insize, model.insize), dtype=np.float32) 239 y_batch = np.ndarray((args.batchsize,), dtype=np.int32) 240 val_x_batch = np.ndarray( 241 (args.val_batchsize, 3, model.insize, model.insize), dtype=np.float32) 242 val_y_batch = np.ndarray((args.val_batchsize,), dtype=np.int32) 243 244 batch_pool = [None] * args.batchsize 245 val_batch_pool = [None] * args.val_batchsize 246 pool = multiprocessing.Pool(args.loaderjob) 247 data_q.put('train') 248 for epoch in six.moves.range(1, 1 + args.epoch): 249 print('epoch', epoch, file=sys.stderr) 250 print('learning rate', optimizer.lr, file=sys.stderr) 251 perm = np.random.permutation(len(train_list)) 252 for idx in perm: 253 path, label = train_list[idx] 254 batch_pool[i] = pool.apply_async(read_image, (path, False, True)) 255 y_batch[i] = label 256 i += 1 257 258 if i == args.batchsize: 259 for j, x in enumerate(batch_pool): 260 x_batch[j] = x.get() 261 data_q.put((x_batch.copy(), y_batch.copy())) 262 i = 0 263 264 count += 1 265 if count % denominator == 0: 266 data_q.put('val') 267 j = 0 268 for path, label in val_list: 269 val_batch_pool[j] = pool.apply_async( 270 read_image, (path, True, False)) 271 val_y_batch[j] = label 272 j += 1 273 274 if j == args.val_batchsize: 275 for k, x in enumerate(val_batch_pool): 276 val_x_batch[k] = x.get() 277 data_q.put((val_x_batch.copy(), val_y_batch.copy())) 278 j = 0 279 data_q.put('train') 280 281 optimizer.lr *= 0.97 282 pool.close() 283 pool.join() 284 data_q.put('end') 285### 試したこと 286学習させる画像の枚数や学習回数を変更した。

以下のような質問にはグッドを送りましょう

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

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

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

PondVillege

2022/10/10 07:57

画像サイズとConfusion Matrixを示していただけると原因究明に役立ちそうです
shinww

2022/10/10 09:37

画像サイズは256×256です。 confusion matrixを追加していませんが他の関数を使っているということでしょうか。 勉強不足で申し訳ないです。
PondVillege

2022/10/10 13:16 編集

Confusion Matrixとは,分類問題において精度や再現率などを評価するための表です.日本語では混同行列とも呼ばれます. https://www.google.com/search?q=confusion+matrix 今回使われたデータセットILSVRC2012では1000カテゴリあるとのことで,かつモデルの精度が0.1%なんですよね,この0.1%というのは,ある入力画像に対して1000カテゴリからランダムに何か1つ選ぶときの精度と同じです.つまるところ,このモデルは何も学習していない可能性があります. ただ,精度だけでは評価しづらいものがあるので,Confusion Matrixによる評価を経て,モデルが完全にRandom Choiceを行うものになっていることを証明した上で,コードやモデルに問題が無いか探そう.というものです. ちなみにモデルもnet.mlpconv1() -> ReLU() -> MaxPooling2d()の繰り返しであることはわかるのですが,これら畳み込み層のカーネル数などのハイパーパラメータがモデルの性能に影響するので,明示していただきたいところです.
shinww

2022/10/10 14:00 編集

色々とご説明ありがとうございます。今回学習のために使用したコードを↑に追加しました。 学習させるためのコードです。↓ よろしくお願いします。
PondVillege

2022/10/10 13:55

この欄では文頭の半角スペースが消されるので,こちらのコードも質問を編集して書き込んでいただけるとありがたいです.
PondVillege

2022/10/10 15:15 編集

optimizer.update(model, x, t) の直下に print(f"acc: {model.accuracy.data}, loss: {model.loss.data}") として表示させみてください.各epochでの数値の遷移を見てみたいです.微塵も動かなければ学習時のコードがおかしいです. 多分,with chainer.no_backprop_mode():の中でoptimizer.update()しているのがダメだと思います.
shinww

2022/10/10 15:39

実行してみたところ、lossの数値に変化はあったのですが、accの方が0.0のままでした。 train_roopのコードを変える必要があるということでしょうか。
PondVillege

2022/10/10 16:00 編集

> 実行してみたところ、lossの数値に変化はあったのですが、accの方が0.0のままでした。 dropoutがあるので,そのレイヤでの重みの組み合わせで,当然lossの数値に変化が出ます. 私が見たい遷移は,中長期的にどのような増減をしたか,というものになります. 横ばいである場合,学習が進んでいませんし,少しずつ減少するなら少なくとも学習は進んでいる証拠になります. > train_roopのコードを変える必要があるということでしょうか。 多分そうです,学習時のコードの全体像がまだわからなくて,具体的にどこに原因があるかわからないといった状態です.並列処理でdata_qにクエリを投げている.という理解でよろしいですか?どのようにクエリを投げていますか?
shinww

2022/10/10 16:14

>私が見たい遷移は,中長期的にどのような増減をしたか,というものになります. lossのはずっと6.9辺りを動いている感じです。 >どのようにクエリを投げていますか? data_qに関するコードを一応↑に追加しました。train_listからnp.random.permutation()を用いてデータをシャッフルして渡しています。
shinww

2022/10/10 16:38

上の場合はできませんでした。 また、volatileが削除されてしまったためwith chainer.no_backprop_mode()を追加したのですが、そういった場合どうすればよいでしょうか。
PondVillege

2022/10/10 16:50 編集

速度に差があるだけなので,とりあえずvolatileなしにするだけで実行してみましょうか with chainer.no_backprop_mode()を追加されていますが,このなかでVariableを実行すると必ずvolatile=Trueにしたことと同じようになってしまうので,chainer.using_config()で代用してvolatile=Falseの場合の処理も書かなくてはなりません.
jbpb0

2022/10/11 00:40

https://docs.chainer.org/en/latest/upgrade_v2.html#volatile-flag-is-removed の「Volatile flag is removed」の「Example」を見ると、Chainer v1用のコードで「volatile=True」だった場合は、Chainer v2では「with chainer.no_backprop_mode():」を使うように書いてあります この質問のコードでは、 > volatile = 'off'if model.train else 'on' から、「model.trainではない」場合が「volatile=on」(=True)になるので、ps_aux_grepさんの回答のように、「model.trainではない」場合のみ「with chainer.no_backprop_mode():」を使います
shinww

2022/10/12 03:50

お二方多くの解決方法を提示してくださってありがとうございました。

回答1

0

ベストアンサー

やはり,optimizer.update()with chainer.no_backprop_mode():の中にあるのは望ましくないと思われます.

Python

1if model.train: 2 x = chainer.Variable(np.asarray(inp[0])) 3 t = chainer.Variable(np.asarray(inp[1])) 4 optimizer.update(model, x, t) 5 if not graph_generated: 6 with open('graph.dot', 'w') as o: 7 o.write(computational_graph.build_computational_graph( 8 (model.loss,)).dump()) 9 print('generated graph', file=sys.stderr) 10 graph_generated = True 11else: 12 with chainer.no_backprop_mode(): 13 x = chainer.Variable(np.asarray(inp[0])) 14 t = chainer.Variable(np.asarray(inp[1])) 15 model(x, t) 16res_q.put((float(model.loss.data), float(model.accuracy.data))) 17del x, t

投稿2022/10/10 16:19

編集2022/10/12 04:32
PondVillege

総合スコア1066

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

jbpb0

2022/10/10 23:51

https://qiita.com/mitmul/items/1e35fba085eb07a92560 の「5.1 ValidationやTestを行う際の注意点」に書かれてるようなことをして、 model(x, t) の際に「F.dropout(h)」が無効になるようにしなくても大丈夫でしょうか?
jbpb0

2022/10/11 00:51

同様な理由で、 x= chainer.Variable(np.asarray(x)) with chainer.no_backprop_mode(): score = predict(model,x) を、下記のように変更しなくても大丈夫でしょうか? with chainer.using_config('train', False), chainer.using_config('enable_backprop', False): x= chainer.Variable(np.asarray(x)) score = predict(model,x)
PondVillege

2022/10/11 00:57

コメント補足ありがとうございます 今回は学習出来ない件なので学習時以外のパラメータ設定は無視して進めてましたが,たしかにそこらへんも気を配る必要がありますね まだ原因があるとすれば,lossのbackwardを明記してないとことか,でしょうか
jbpb0

2022/10/11 02:20

> lossのbackwardを明記してない それは要らないのではないですかね https://qiita.com/icoxfog417/items/96ecaff323434c8d677b の「学習」に、 「中核となるのは更新を行っているoptimizer.updateです。1.5からはlossfunを引数に渡すことで自動的に渡されたlossfunによる誤差計算、伝播(backward)を行ってくれるようになりました。もちろん、今まで通りmodel.zerograds()で勾配を初期化してから自前で誤差の計算・伝播を行い(loss.backward)、optimizer.updateを呼ぶことも可能です。」 と書かれてます
jbpb0

2022/10/11 02:35

> 学習出来ない件 が解決して、 > 学習させたモデルでテストを行うと0.1%しか出ない がだいぶマシになっても、「F.dropout(h)」の「ratio」のデフォルト値は「0.5」 https://docs.chainer.org/en/stable/reference/generated/chainer.functions.dropout.html と結構大きいため、テスト時にも有効なままだとテスト結果が思ったほど良くならない、となるかも、と思いまして
PondVillege

2022/10/11 05:06

> 「F.dropout(h)」の「ratio」のデフォルト値は「0.5」 https://docs.chainer.org/en/stable/reference/generated/chainer.functions.dropout.html と結構大きいため、テスト時にも有効なままだとテスト結果が思ったほど良くならない、となるかも、と思いまして そうですね,テスト時にも有効だとテストの結果は良くならなさそうです.ですが,学習データに対してフィッティングされていれば学習時の損失は下がるはずですが,上のコメントで申し出ていたように停滞していたとのことなので不活性化率に関しては一旦忘れていました.
shinww

2022/10/12 03:51

↑のコードの修正したところ学習がうまくいくようになりました。ありがとうございました。
PondVillege

2022/10/12 05:04

おめでとうございます.もしまた精度の議論があるときは,Confusion Matrixと学習曲線の提示をお願いします.コードの誤りもここから推測できます

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

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

Chainer

Chainerは、国産の深層学習フレームワークです。あらゆるニューラルネットワークをPythonで柔軟に書くことができ、学習させることが可能。GPUをサポートしており、複数のGPUを用いた学習も直感的に記述できます。

機械学習

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