Gunosyデータ分析ブログ

Gunosyで働くデータエンジニアが知見を共有するブログです。

Chainer 1.11.0 で畳み込みニューラルネットワークを試してみる

はじめまして,Gunosyデータ分析部の@hmjです. 2016年の2月からGunosyのデータマイニングエンジニアとして働いていて,今はデータ分析や記事配信アルゴリズム改善を行っています.

今回は,GunosyでのDeep Learningの利用例と, 先日リリースされたChainer 1.11.0*1 を使った簡単なCNNの実行例のご紹介をします.

Deep Learning の Gunosy での利用例

背景

Deep Learning は,2012年に物体の認識率を競うILSVRCにて従来手法よりも高い精度をだし,機械学習の研究者らに衝撃を与えたといわれています*2. 最近では「人工知能」と同じレイヤーで語られるほど「Deep Learning」は未だに注目を集めています.

そんな中で,弊社データ分析部でも Deep Learning の手法をいくつか試しています. 用いているタスクの内容としては,主にユーザのデモグラフィック(性別や年齢など)の分類となります. ユーザのデモグラフィックを活用することで,例えば,性別や年齢ごとに適したニュース記事を配信することが可能となります.

フレームワークと手法

Deep Learning のフレームワークは, Caffe,Theano,Chainer,TensorFlow などいくつかありますが, 私は実験的に使いやすい理由で Chainer を利用しています.

ユーザのデモグラフィックを予測する手法ですが, ユーザの行動履歴データを加工して,畳み込みニューラルネットワーク(Convolutional Neural Network,以下 CNN)の手法を応用することで従来手法よりも高い精度をだすことができています.

Chainer 1.11.0 にて MNISTサンプルを例にしてCNNを試してみる

今回は日々お世話になっているChainerのv1.11.0 の新しい書き方で, 日々利用しているCNNのexampleを簡単にご紹介します*3

Chainer 1.11.0 の変更点については,下記ブログに解説がありましたので,こちらが参考になると思います. www.monthly-hack.com

MNISTサンプルを例にしたCNNのコード

実行した環境とライブラリのバージョンは,

- AWS の g2.2xlarge
- Python 2.7
- Chainer 1.11.0
- CNNの構成 : 2つの畳込み層,2つのプーリング層

となります。

ほとんどexamples と同じ内容となりますが,

train, test = chainer.datasets.get_mnist(ndim=3)

get_mnist の引数が異なっています.ndim3 を与えると,shape が (1, 28, 28) の形式で取得できます*4. これによって,CNNにデータを渡すことができます.

学習結果の可視化

CNNにすることが,MLPで行うよりも高い精度を確認することができます. 下記はepoch を20回まわして,5回まで表示したものです.

$ python train_mnist_cnn.py

epoch       main/loss   validation/main/loss  main/accuracy  validation/main/accuracy

1           0.175833    0.0593624             0.949533       0.9803                    

2           0.0526729   0.0435978             0.983915       0.9855                    

3           0.0370761   0.0386008             0.988848       0.9874                    

4           0.0280716   0.0352529             0.991548       0.9891                    

5           0.0214525   0.0304704             0.993649       0.9907

...

テスト精度は最大で99.3%となりました.

訓練時の誤差とテスト精度を描画すると下記のようになりました(青: loss,緑: accuracy).

f:id:gunosy_data:20160725142017p:plain

また,テスト用のデータについて予測を行い,混同行列 (confusion matrix)をグラフ化すると,下記のようになり高い精度となっていることがわかります. 「0」を「6」と間違っているのは,0と6が似ているからでしょうか...

f:id:gunosy_data:20160725142202p:plain

余談

最後に,余談となりますが,自分で書いた文字を分類させてみる,というのをやってみました.

下の画像は筆者が「1」を書いたものです.

f:id:gunosy_data:20160725162918p:plain

これを読み込んで,numpy.array に変換して,学習済みのmodel*5に食べさせて分類させたところ

img = np.array(Image.open('./data/my_1.png').convert('L'), 'f')
img -= img.mean()
y= model.predictor(img.reshape(-1, 1, 28, 28))
F.softmax(y).data.argmax(axis=1)

array([1])

と「1」と正しく分類することができました*6

最後に

Chainerを利用してMNISTをサンプルにしてCNNの紹介をさせて頂きました. 1.11.0 は以前のバージョンのものとは書き方が異なり慣れが必要だと思います. ですが,慣れると以前より使いやすくなるので, examples をもとに試行錯誤するのがおすすめです.

*1:https://github.com/pfnet/chainer/releases

*2:https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0#.E6.AD.B4.E5.8F.B2

*3:既にあったらごめんなさい

*4:https://github.com/pfnet/chainer/blob/master/chainer/datasets/mnist.py#L33

*5:ここではcpu上でpredictさせるために model.to_cpu() を事前にしています

*6:画像について平均除去の前処理を行っています