2019年5月29日水曜日

KerasチュートリアルのCNNがうまくいかない

(2019/05/31:末尾に追記しました)
 深層学習を勉強する機運が高まったので「PythonとKerasによるディープラーニング」を読んでいる。第5章ではまずMNIST数字分類にCNNを使うのだが、サンプルコードを写経したプログラムがうまくいかないので困っている。誰か教えてください。
 こちらがそのノートブック。MNISTデータ読み込みなどが終わった後、前半ではサンプルコード通りのネットワークを持つ分類器を使っている。

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 3, 3, 64)          36928     
_________________________________________________________________
flatten_1 (Flatten)          (None, 576)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                36928     
_________________________________________________________________
dense_2 (Dense)              (None, 10)                650       
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0

その結果がこれである。

Epoch 1/5
60000/60000 [==============================] - 97s 2ms/step - loss: 14.0193 - acc: 0.1115
Epoch 2/5
60000/60000 [==============================] - 88s 1ms/step - loss: 14.4351 - acc: 0.1044
Epoch 3/5
60000/60000 [==============================] - 86s 1ms/step - loss: 14.4351 - acc: 0.1044
Epoch 4/5
60000/60000 [==============================] - 91s 2ms/step - loss: 14.4351 - acc: 0.1044
Epoch 5/5
60000/60000 [==============================] - 88s 1ms/step - loss: 14.4351 - acc: 0.1044

 テストデータでの正答率も0.1028と何も学んでいない。どこかでコードミスっているか?と思い、サンプルコードをgit cloneしてそのまま実行してもやはり同じようになった。
 次に上のモデルのConv2D_3が妙に気になったので消してみたのが後半。

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_4 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_3 (Dense)              (None, 64)                102464    
_________________________________________________________________
dense_4 (Dense)              (None, 10)                650       
=================================================================
Total params: 121,930
Trainable params: 121,930
Non-trainable params: 0

 その結果がこれである。

Epoch 1/5
60000/60000 [==============================] - 85s 1ms/step - loss: 0.1748 - acc: 0.9473
Epoch 2/5
60000/60000 [==============================] - 87s 1ms/step - loss: 0.0534 - acc: 0.9835
Epoch 3/5
60000/60000 [==============================] - 85s 1ms/step - loss: 0.0391 - acc: 0.9881
Epoch 4/5
60000/60000 [==============================] - 84s 1ms/step - loss: 0.0309 - acc: 0.9911
Epoch 5/5
60000/60000 [==============================] - 84s 1ms/step - loss: 0.0259 - acc: 0.9922

 テストデータでの正答率も0.9899と高い。この結果からはこのConv2D_3が悪かったんかなぁという推測を生む以上の何かは得られなかった。
 その次に、イヌとネコの分類器を作るパートでも同様にサンプルコード通りに試してみた。そのノートブックがこちら
 モデルのサマリはこんな感じ。

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 148, 148, 32)      896       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 74, 74, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 72, 72, 64)        18496     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 36, 36, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 34, 34, 128)       73856     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 17, 17, 128)       0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 15, 15, 128)       147584    
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 7, 7, 128)         0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 6272)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               3211776   
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 513       
=================================================================
Total params: 3,453,121
Trainable params: 3,453,121
Non-trainable params: 0

 実行結果はこんな感じ。

Epoch 1/30
100/100 [==============================] - 199s 2s/step - loss: 3.9247 - acc: 0.4875 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 2/30
100/100 [==============================] - 190s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 3/30
100/100 [==============================] - 197s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 4/30
100/100 [==============================] - 193s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 5/30
100/100 [==============================] - 191s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 6/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 7/30
100/100 [==============================] - 191s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 8/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 9/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 10/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 11/30
100/100 [==============================] - 191s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 12/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 13/30
100/100 [==============================] - 194s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 14/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 15/30
100/100 [==============================] - 191s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 16/30
100/100 [==============================] - 195s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 17/30
100/100 [==============================] - 193s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 18/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 19/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 20/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 21/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 22/30
100/100 [==============================] - 195s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 23/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 24/30
100/100 [==============================] - 193s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 25/30
100/100 [==============================] - 193s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 26/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 27/30
100/100 [==============================] - 193s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 28/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 29/30
100/100 [==============================] - 192s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000
Epoch 30/30
100/100 [==============================] - 193s 2s/step - loss: 7.9712 - acc: 0.5000 - val_loss: 7.9712 - val_acc: 0.5000

 2つの分類で正答率0.5なのでやはりダメダメである。何故サンプルコード通りでうまくいかないのかが全くわからない。それとlossが全く動いていないのが気になる。この手の「同じ値を出力し続ける」ようなことって、記憶が曖昧だがメモリ足りない時とかに起きるようなことがあった気がするなぁなんて思いながら結果を眺めていた。
 おそらくMNISTでConv2D_3が入るとうまくいかない理由と、イヌネコ分類器がうまくいかない理由は一緒なんだろうという気がしている。ただその原因が全く分からない。ググっても同じような人は見当たらない。どこかでタイポしているのだろうか。なんなのか。今日はずっとこれの原因を探していたがもう限界である。

(追記)
 ノートブック
 やはりオーバーフローの類が原因として濃厚だったためバッチサイズを10にしたところ、たまに学習がうまくいくようになった。ただやはりうまく学習するモデルとそうでないモデルの違いがよくわからず模索した跡が、ノートブックのmodel1~3の部分。
 そんな時に、学習と関係ないコマンドを追加しただけなのにうまく学習が進んでいたモデルがうまく学習しなかったところでハッと気づいた。そこで上のmodel2を10回繰り返したのが、ノートブック後半部。
 結果としてうまくいったりうまくいかなかったりするものとが出てきたので、なるほどなと。こういうこともあるのだな。

 しかし、「局所解にハマってlossがなかなか下がらない」ならともかく、「lossがドカンと上がってしまう」というのは、一体何が起きているのか直感的によくわからないですね。やっぱり詳しい人教えてください。

0 件のコメント:

コメントを投稿