PFN発のディープラーニングフレームワークchainerで画像分類をするよ(chainerでニューラルネット1)

1日ちょっと前に、PFNから新しいディープラーニングフレームワーク"chainer"が公開されました[1]。触ってみた感じの特徴は、pythonのコードで完結するので、システムに組込みしやすそうで、処理の内容も読みやすい。同時に、処理の内容に興味を持たずに使うには難しいという思いでした。ベースにしてあたらしいツールを作るには最適に感じるので、これから、chainerをベースにした様々な用途のツールができるのが期待されます。

CPU用インストール ~ MNISTのトレーニング

ここでは、chainerのチュートリアル[1]に書いてあるとおりにインストールと初期タスクをおこなうだけです。

インストールは、githubからソースを落としてきてpython setup.py installでも、pipで入れてもいいと思います。とりあえずここではpip

pip install chainer

これでchainerが動くんですが(シンプル!)、とりあえず何かしらの学習をしたいので、チュートリアル通りにMNIST(手書き数字データベース)のトレーニングをします。これはCPUでも一瞬で行けます。

git clone https://github.com/pfnet/chainer.git
python chainer/examples/mnist/train_mnist.py

環境次第では、ダウンロード先ディレクトリの用意ができないことがあるので

スクリプト(chainer/examples/mnist/train_mnist.py)のこの行を
mnist = fetch_mldata('MNIST original')

こう変える(好きなディレクトリのパスでいいです)
mnist = fetch_mldata('MNIST original', data_home='/tmp')

あとはerrorが下がっていくのを眺めましょう(^^)

画像分類問題を解く

まぁMNISTが解けるのはいいです、でもcaffeとかをすでに触ってるみなさんは、画像分類問題とかを簡単に解きたいですよね。幸いchainerのexamplesにはimagenet[2]の分類問題を解くために先人たちが作ったネットワークがexampleとして付属してます(python ~/chainer/examples/imagenet/)。ただし、caffeの用にトレーニング済みのものがダウンロードして来られるわけではないので自分でデータを集めてトレーニングする必要があります。

データセット作る

本来なら、面白いデータ(アニメキャラの分類[3]とかAKBの分類[4]とか)で作りたいんですが、ファインチューニングならまだしも、1からトレーニングをするとなるとそれなりの量のデータが必要で正直面倒です。今回は、caffeにお手軽ダウンロードスクリプトがついてる[5]、flickr sytle datasetを使いましょう。

caffeの付属スクリプトを使って以下のように集めます。とりあえず80000サンプル使います

git clone https://github.com/BVLC/caffe.git
python caffe/examples/finetune_flickr_style/assemble_data.py --workers=-1 --images=80000 --seed 831486

これで

  • caffe/data/flickr_style/images
  • caffe/data/flickr_style/train.txt
  • caffe/data/flickr_style/test.txt

の3点セットが揃いました。なお、train.txtやtest.txtは画像ファイルパス、クラス名をスペースで区切ったファイルなので、これを人力で頑張って用意すれば、以下の手順で他の問題も解けます。

さて、chainerのexampleで用意されているスクリプトを動かすためには、まだ少し準備が必要です。まず、このデータはサイズが正規化されていないので、256x256の画像にする必要があります。どのようなやり方でやってもいいんですが、僕は、拡大縮小なしで、複製して連結+256切り取りでやりました(https://gist.github.com/Hi-king/1c7f86e0fa628c41eb3c)。

mv caffe/data/flickr_style/images caffe/data/flickr_style/images_raw
python crop.py caffe/data/flickr_style/images_raw caffe/data/flickr_style/images
# train.txtには、絶対パスが書かれているので、必ずcrop後の出力をimagesディレクトリに入れる必要がある

さらに、用意したデータセットの平均画像を作っておく必要があります。これはchainerのスクリプトが用意されてます。

cd caffe/data/flickr_style
python ${your_path}/chainer/examples/imagenet/compute_mean.py train.txt
# mean.npyというファイルが生成されます

GPUを有効化する

全ての用意が出来ました。これでトレーニングが始められます!が、規模の大きい学習をCPUだけでやるのは心もとないです。せっかくなのでGPUでやりましょう。検証してないですが、たぶん10~20倍の時間かければCPUでもできると思うので、お試しだけならそちらでもいいかもしれません。

依存するライブラリ(pycuda, scikit.cudaなど)がインストールされてればすぐに使い始められます。僕は用意してなかったので、ここでインストールします。また、setup.py install でchainerをインストールしていれば一緒に入るのかもしれません。

[追記] chainer-cuda-depsがリリースされたので、今後はそちらを使いましょう

pip install chainer-cuda-deps
# こちらは古い方法
pip install -r chainer/chainer/requirements/cuda-requirements.txt

これで、chainerが必要とするcuda関連pythonライブラリが入ります

学習!

cd caffe/data/flickr_style
python ${your_path}/chainer/examples/imagenet/train_imagenet.py -g 0 train.txt test.txt 2>&1 | tee log
# CPUでやる場合は-g -1
# ネットワーク構造も複数選べる(GoogLeNetとか)けれど、デフォルトのNINをつかってる

これで学習できるんですが、このスクリプト、デフォルトではかなり大規模な学習用に作られてるので、学習の進捗が全然出てこなくて寂しいです。もっとおしゃべりなスクリプトに修正しましょう。

# chainer/examples/imagenet/train_imagenet.py
            train_cur_loss += loss
            train_cur_accuracy += accuracy
            if train_count % 10 == 0: # ここ修正
                mean_loss  = train_cur_loss / 10 # ここ修正
                mean_error = 1 - train_cur_accuracy / 10 # ここ修正
                print >> sys.stderr, ''
                print json.dumps({'type': 'train', 'iteration': train_count,
                                  'error': mean_error, 'loss': mean_loss})

ログを吐く周期を上のよう短くすることで楽しく進捗が見られます。

さて、あとはログをグラフにして、進捗を見ましょう。とりあえずpythonスクリプト作りました(https://gist.github.com/Hi-king/1c7f86e0fa628c41eb3c)

less log|grep iteration > log_pretty
python plot.py log_pretty

結果は以下

f:id:Hi_king:20150611035412p:plain

この問題は、20クラス識別なので、チャンスレート(当てずっぽう)はだいたい95%のエラー。 "キュビズム"、"ロマンティック"、"バロック"という、人間でもよくわかんない抽象的なクラスを当てる問題なので[6]、これでもなかなか学習進んでる方かと思われます。論文中でも3割強の正解率(7割弱のerror)となっているので妥当かと思います。 まぁこれはクローズドテスト(学習に使ってるデータでのエラー)なので、ちゃんとした評価としては全然不足です。

ちなみに、5000イテレーションで、amazonEC2のg2.2xlargeで50分程度でした。CPUでも2,3日頑張れば行けそうですね。

chainerはcaffeよりも回帰とかRNNとかがやりやすいのが利点なので、次は識別じゃない問題を解いてみたいものです。