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ハード部で発表します。おたのしみに。