ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

俺俺フレームワークでVGG16がちょっと動いた。

2月からこつこつとやっていた俺俺フレームワークで、VGG16のCソースが生成できるようになりました。学習済のKeras環境から、ポータブルなCソースコードを生成します。最終層の計算結果だけが少し違っていて、今後の課題となっています。出力されるCソースのこだわりは、mallocファイルシステムの存在を前提としない、C++の機能を一切使わない事です。

ソースはgithubに公開しています。
https://github.com/natsutan/cocytus

生成されたCソースはここから下です。

https://github.com/natsutan/cocytus/tree/master/example/vgg16/c

実行結果

同じデータを入れたKerasの出力と、俺俺フレームワークの出力を層単位で比較しています。最終層の入力までは一致していますが、最終層で計算が変になります。

犬画像を入れた結果、上がKeras、下が俺俺フレームワーク

('n02091467', 'Norwegian_elkhound', 0.6510464)
('n02105162', 'malinois', 0.20971657)
('n02106662', 'German_shepherd', 0.124572)
('n02105412', 'kelpie', 0.0050396309)
('n02093754', 'Border_terrier', 0.0034161564)
Norwegian_elkhound, rate = 0.982867
German_shepherd, rate = 0.004897
kelpie, rate = 0.003937
timber_wolf, rate = 0.003696
Siberian_husky, rate = 0.001548

猫を入れた結果。同じく上がKeras、下が俺俺フレームワーク

('n02091467', 'Norwegian_elkhound', 0.6510464)
('n02105162', 'malinois', 0.20971657)
('n02106662', 'German_shepherd', 0.124572)
('n02105412', 'kelpie', 0.0050396309)
('n02093754', 'Border_terrier', 0.0034161564)
Norwegian_elkhound, rate = 0.982867
German_shepherd, rate = 0.004897
kelpie, rate = 0.003937
timber_wolf, rate = 0.003696
Siberian_husky, rate = 0.001548

どちらも、なんとなくはあってるんですが、計算結果が違うのは気持ち悪いですね。

最終層の計算が合わない問題

いろいろ一日試行錯誤してみましたが全くわからず、作戦を変えようとしています。その中でわかったことメモ。

softmaxは無関係

Kerasの最終出力をsoftmaxからLinearに変更したが、Linearの出力で値が変わっている。

最終層のみおかしい

VGG16は最後に3つの全結合層(Dense)があり、前2つは完全に一致している。前のMNISTで俺俺フレームワークを試した時は処理結果が一致していたので、僕が根本的に勘違いしているというのは無さそう。VGG16の入力層では、知らない間に定数値を引かれていた。何かVGG16特有の最終層処理があるのではないかと疑っている。

Kerasの最終層にオール0を入力してみる。

重みデータはそのままで、kerasの最終層に全て0データを入力して、その出力(activation=Linear)を見てみた。僕の理解ではBias項のみが出てくるのだが、全く違う値が出てきている。重みデータはHDFViewで確認済。重みデータを書き換えて傾向を見ようとしたら、新しい重みデータをダウンロードして上書きされてしまったので心が折れました。

MNISTからVGG16へ

kerasの前のバージョンではMNIST互換のひらがな認識CNNが動いていました。そこからVGG16が動く状態に持って行くまでが、Keras2.0への移行部分と、上の最終層問題を除くと約2日程度でした。当初2週間くらいかかるかと思ったのですが、予想以上に早くできました。あと、最終層の問題だけです。2日の内訳は

  • VGG16は入力で固定値(103.939, 116.779, 123.68)を引いてるのがKerasのソースでは読み取れなかった。
  • CNNの境界処理がvalidからsameへ変更
  • 最大層が16固定値になっていて、MNISTは動いたがVGG16で実行時に即死していた。

程度がVGG16を動かす時の変更箇所でした。入出力のサイズ合わせや、重みの対応付けは俺俺フレームワークの方でやってくれるので便利でした。

今後の話

今回の俺俺フレームワーク実装の話を、次回TFUGハード部で発表します。おたのしみに。