素人がCaffeを使ってDeepLearningしてみた(実践編)

#はじめに
この記事は
1. Deep Learningって何？を説明する [概要編](http://qiita.com/yuishihara/items/abb59555dca9b34a59f0)
2. Deep Learningライブラリの一つであるCaffeのインストールする [導入編](http://qiita.com/yuishihara/items/1dfa2eed5261104381a7)
3. Caffeを使って簡単な学習をさせてみる 実践編(この投稿)
の三本構成になっています

タイトルにもありますが、Deep Learningの研究者でもなんでもない素人が残した記録程度の投稿なので、間違った記述があるかもしれない点はご容赦いただき、読んでいただくようお願いします
(もしおかしい点があればコメントで指摘していただけると嬉しいです)
あと、思いのほかわからないことが多いため、実践編は少しずつ更新の予定です・・・

#MNISTのデータベース(手書き文字)を認識させる
まず第一歩として、
1)公式の情報をベースにMNISTの学習をさせる（ここまではチュートリアルに書いてある）
2)学習したネットワークを使って、MNISTの28*28pixelのJPEG画像を認識させる（何故かチュートリアルに書いてない）
をやることにします

##MNISTの学習をさせる
[公式](http://caffe.berkeleyvision.org/gathered/examples/mnist.html)に書いてあることなぞります

###MNISTのデータベースを作成する
gitからcloneしてきた素の状態では、学習の対象となる手書き文字のデータがないので下記で落とします
環境変数としてCAFFE_ROOTが設定されている前提で（設定していない場合はcaffeのリポジトリのルートがCAFFE_ROOTになるよう設定してください）、

```console:
cd $CAFFE_ROOT
./data/mnist/get_mnist.sh
./examples/mnist/create_mnist.sh
```

これで、うまく行けばexamples/mnist以下にmnist_test_lmdbとmnist_train_lmdbの2つのフォルダが生成され、中にデータベースができているはずです

###データベースを使って学習させる
データベースを作成したら、付属しているネットワークとソルバーを使って特に何もすることなく、手書き文字を学習させることができます
具体的には、下記1行で終わりです。時間は環境によって変わりますが、10分もあれば終わると思います


```console:
cd $CAFFE_ROOT
./examples/mnist/train_lenet.sh
```

これで、学習がきちんとされれば、examples/mnist以下に、lenet_iter_10000.caffemodelとlenet_iter_5000.caffemodelが作成されます。10000と5000の違いは、学習のイテレーションが10000回目のときのネットワークか5000回めのネットワークかというだけです

##学習されたMNISTのネットワークで実際にどう認識されるか確かめてみる
チュートリアルに沿ってデータベースから学習させると、なんとなくネットワークがなにかしら学習したのはわかるんですが、実際にネットワークを使ってみないと、うまく出来たのかイマイチ自身がわきません
そこで、10000文字が格納されている上のデータベースを、それぞれ1文字ずつJPEGにして、それをネットワークに与えて、どんな出力になるかみてみます
この章で使ったスクリプトは[GitHub](https://github.com/yuishihara/CaffePythonUtils)においたので、もしよければ使ってください

###データベースをJPEGにして認識対象をわかりやすくする
データベースを見ても、何番目が何の文字かわかりにくいので、データベース内に格納されているデータをJPEGにします
今回は、自前でスクリプトを作ってJPEGにしました
こんな感じ（python）

```py
import scipy
import numpy as np
import lmdb
import sys
from caffe.io import caffe_pb2

def convert_to_jpeg(db_dir):
    env = lmdb.open(db_dir)
    datum = caffe_pb2.Datum()
    with env.begin() as txn:
        cursor = txn.cursor()
        for key_val,ser_str in cursor:
            datum.ParseFromString(ser_str)
            print "\nKey val: ", key_val
            print "\nLabel: ", datum.label
            rows = datum.height;
            cols = datum.width;
            img_pre = np.fromstring(datum.data,dtype=np.uint8)
            img = img_pre.reshape(rows, cols)
            file_name = str(key_val) + "_" + str(datum.label) + ".jpg"
            scipy.misc.toimage(img, cmin=0.0, cmax=255.0).save("data/mnist/jpg/" + file_name)

```

mnist_test_lmdb内にあるデータベースであれば、下記のようにすると10000個のjpg画像が生成されます

```console:
cd $CAFFE_ROOT
python mnist_jpg_converter.py examples/mnist/mnist_test_lmdb/
```

###画像をネットワークに与えて、結果を見てみる
まずネットワークを読み込むために、caffe付属のpython/classify.pyを書き換えます
こんな感じ。

```py
def main(argv):
    # --略--

    # Make classifier.
    classifier = caffe.Classifier(args.model_def, args.pretrained_model)

    # Load numpy array (.npy), directory glob (*.jpg), or image file.
    args.input_file = os.path.expanduser(args.input_file)
    print("Loading file: %s" % args.input_file)
    grayimg = caffe.io.load_image(args.input_file, color=False)[:,:,0]
    inputs = [np.reshape(grayimg, (28, 28, 1))]

    print("Classifying %d inputs." % len(inputs))

    # Classify.
    start = time.time()
    predictions = classifier.predict(inputs)
    print("Done in %.2f s." % (time.time() - start))

    # --略--

```

あとは、このスクリプトを使って

```console:
cd $CAFFE_ROOT
python lenet_classify.py data/mnist/jpg/00000007_9.jpg result.npy
```

のようにすれば、分類結果がresult.npyに出力されます

```console:
python my/show_mnist_result.py result.npy 
[[  6.68664742e-03   2.82594631e-03   8.81279539e-03   1.06628540e-05
    4.27712619e-01   1.90626510e-04   1.27627791e-04   9.20879841e-03
    4.14795056e-02   5.02944708e-01]]
```

列の項目は0,1,2,...,9の順番で並んでいるので、9に対する確率が約50％で他のどの分類結果よりも高いので、ネットワークがきちんと学習していることが確認できます
（次に確率が高いのは4ですが、9と4は見た目が近いので、納得できる結果かと思います）

お疲れ様でした

#参考文献
[CaffeでDeep Learning つまずきやすいところを中心に](http://qiita.com/uchihashi_k/items/8333f80529bb3498e32f)
[Caffeで手軽に画像分類](http://techblog.yahoo.co.jp/programming/caffe-intro/)