飽きるまでやります。

私の私による私のためのメモ。内容に一切の責任を負えません。

Kerasのバックエンドでハマった話

概要

深層学習の練習しました。悪い意味でハマりました。

やったこと

続・深層学習でアニメ顔を分類する with Keras - Qiita
参考1

Kerasでアニメキャラの顔認識 - Qiita
参考2

ここを参考にしながらアニメの顔分類をとりあえずしてみました。

 

NNの構成を読む

model.add(Convolution2D(96, 3, 3, border_mode='same', input_shape=(3, 32, 32)))

畳み込み層 Keras2.0からConv2D() でもどっちでも動く
3*3の96種のカーネルをかける、入力と出力の縦横は同じ(ゼロパディング)、入力画像は3CHの32*32、即ち出力は96CHの32*32の特徴マップ

Convolution2D(128, 3, 3)

引数なしならborder_mode='valid'、即ち128CHの30*30の特徴マップが出力される

model.add(MaxPooling2D(pool_size=(2,2)))

プーリング層
pool_size=(2,2)は画像を半分にする、即ち出力は15*15の特徴マップ

Dropout(0.5)

入力の50%がドロップする、過学習防止になる

Flatten()

全結合層への入力データは一次元である必要があるため、Flatten()で一次元化する

Dense(1024)

全結合層
1024次元(32*32)の出力。最後のDenseでクラス分類。

ハマりどころ+見解

真実がわからないから妄言です。
参考2のコードは動いたけど参考1のコードはエラーを吐きました。

ValueError: ('The specified size contains a dimension with value <= 0', (-1536, 1024))
とか
ValueError: The shape of the input to "Flatten" is not fully defined (got (0, 15, 128). Make sure to pass a complete "input_shape" or "batch_input_shape" argument to the first layer in your model.
とかです。

from keras import backend as K
K.set_image_dim_ordering('th')

これでエラーは出なくなりました。ではtf状態で出された精度は一体なんなのか…。

見解として、

  • 多分3*32の32ch画像として入力されていた? 参考2にはプーリング層がないので正常(?)に動いた。
  • 2回目の畳み込み層はゼロパディングがないので1*30の特徴マップになった。
  • 次にプーリング層で特徴マップの大きさを半分にするがここで仕組みは分からないけど1を半分にすることで負の数が出てきてエラーになった。

原因と対処

anaconda下で仮想環境作ってやってるんですがkeras.jsonが仮想環境の外に作られるせいかKerasのバージョン違いの間でデフォルトのバックエンドが変わったりとかなんとかで色々ややこしいことになっていたようです。
Keras2.1のデフォルトのバックエンドはTensorFlowでchannels_lastです。困ったんでとりあえず.keras/keras.jsonを消しました。
.keras/keras.jsonとkeras/backend/__init__.pyあたりにバックエンドの設定が書いてあるようです。

感想

道理でマッハで学習が終わると思った!