Facebookが論文を書いている、C3Dというモデルがあります。これは、動画の分類器です。通常、写真の分類器ですと、2次元のConvolutionを使いますが、C3Dでは時間方向に次元を拡張し、3次元のConvolutionをしています。
これの、Tensorflow版、Keras版、PyTorch版そしてオリジナルのCaffe版(但しConvolution3Dに対応するためCaffeを改造)はあるのですが、Chainer版が見当たらなかったので、移植してみました。
- c3d-chainer: https://github.com/ikeyasu/c3d-chainer
※ 一応動いていますが、元のものと同じ精度が出ているかは確認していません。
Chainer用に変換した学習済みモデルもこちらで配布しています。
Pretrained モデルを使ってみる
README.mdのとおり、モデルをダウンロードして、必要なものをインストールすれば以下のように実行できます。
以下、 https://www.youtube.com/watch?v=dM06AMFLsrc のバスケットボールの動画を予測をしています。
$ python predict.py -a c3d --model caffe_model/conv3d_deepnetA_sport1m_iter_1900000_chainer.model --mean caffe_model/train01_16_128_171_mean.npy --video dM06AMFLsrc.mp4 --labels caffe_model/labels.txt
Loaded 487 labels.
Loaded caffe_model/conv3d_deepnetA_sport1m_iter_1900000_chainer.model.
/home/ikeyasu/anaconda3/envs/chainer3/lib/python3.6/site-packages/chainer/utils/experimental.py:104: FutureWarning: chainer.functions.pooling.MaxPoolingND is experimental. The interface can change in the future.
FutureWarning)
Position of maximum probability: 367
Maximum probability: 10.43649
Corresponding label: basketball
Top 5 probabilities and labels:
10.43649 basketball
8.61597 volleyball
8.46861 streetball
7.04241 roller derby
6.63952 freestyle wrestling
コンバート
本来、Chainerでしたら、CaffeFunction
を使って、Caffeモデルのインポートができます。が、C3Dは、Caffe自体を改造して作られているのでインポートができません。
そのため、重みのコピーを行いました。これは、C3D Model for Kerasを参考にしています。
を見てもらえると分かりますが、各レイヤーの重みをコピーしているだけです。
スクラッチからTraining
また、元論文は、Sports-1Mを使っているのですが、スクラッチから学習を試すには規模が大きかったので、UCF-11という小ぶりなデータセットを使っています。(個人的には、Video classificationのCIFAR-10の位置づけと認識しています)
これで学習すると、以下のように、8割ちょっとの結果がでました。学習時間は、GTX 1080 搭載の手元のPCで、3時間ぐらいです。
実行の仕方は、こちらのREADME.mdを見てもらえれば分かるので、ここでは実装時に工夫した点を書きたいと思います。
データの用意
試行錯誤の時間を早めるため、ffmpeg で静止画に展開して、それを動画として読み込むためのDatasetクラスを作りました。https://github.com/ikeyasu/c3d-chainer/blob/master/datasets/UCF11.py
また、最初は、CIFAR-10と合わせて、32px の大きさで試していました。が、イマイチ結果が出ず。これは、人間の目で見ても、解像度が低すぎて何か分からないので、仕方ないかなと思います。
Data augumentation
その他パラメータを論文に合わせて実行すると、すぐに main/accuracy が1になって、validation/accuracy が良くならない、そして学習が進むとvalidation/lossが増えるという、過学習の状態になりました。当初は、さぼって Data augumentation をしてなかったので、それが悪かったんだろうという事で、以下3つのaugumentationをしてみました。
- Random Fliping (水平方向反転)
- Random Crop (少し大きめの画像から領域をランダムにトリミング)
- Random Erase (一部をマスク)
比較のため、全てのData augmentationをOffにしたグラフを以下に掲載します。
過学習しているグラフ(Data augmentationなし):
先ほどのグラフと比べて、完全に過学習していて、精度が上がっていない事が分かります。もっとも、単純にaccuracy(Classificationなので、softmax_cross_entropy)を比較しても、Data augmentationをしていないときと、そんなに変わらないようです。ただ、Lossの方は、向上しており、過学習がある程度解消している事は見て取れます。