ディープラーニングフレームワーク Caffe を Ubuntu 15.10 にインストールする【備忘録】

Caffe をインストールした際のコマンドをメモとして残します。
なお、私はディープラーニングについて完全に素人ですので、おかしなことを書いていたらご指摘いただけると幸いです :sweat_smile: 

まず、インストールしたコンピュータの諸元です。

    - ubuntu 15.10
    - プロセッサ AMD A8-7600 Radeon R7, 10 Compute Cores 4C+6G × 4
    - グラフィック Gallium 0.4 on AMD KAVERI (DRM 2.43.0, LLVM 3.6.2)
    - OS種別 64 ビット

NVIDIA の GPU は搭載していないはずなので、CUDA 無しです。
つまり、CPU 実行の Caffe をインストールしました。

まず、必要なライブラリをインストールします。
```
sudo apt-get install libatlas-base-dev libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev libgflags-dev libgoogle-glog-dev liblmdb-dev protobuf-compiler git
```

次に、GitHub から Caffe のソースコードを入手します。
GitHub のアカウントは既に持ってたので clone のみ実行。
```
git clone https://github.com/BVLC/Caffe.git
```

Caffe のコンパイルの前に `Makefile.config`, `Makefile` を編集します。
```
cd Caffe
cp Makefile.config.example Makefile.config
```

`Makefile.config`では `CPU_ONLY = 1` をコメントアウトから外します。つまり、活かします。
```
-# CPU_ONLY := 1
+CPU_ONLY := 1
```

Ubuntu 15.10 の場合、Makefile を変更する必要があります。
hdf5 (って何？ :sweat_smile: ) のパスが変更されたとのことで、詳細は下記サイトにあります。
[Fix hdf5 naming problem](https://gist.github.com/wangruohui/679b05fcd1466bb0937f#fix-hdf5-naming-problem)

`Makefile` の修正箇所は２つ。

- INCLUDE_DIRS に `/usr/include/hdf5/serial/` を追加

```
--- INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
+++ INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial/
```
- LIBRARIES に指定する `hdf5_hl, hdf5` を `hdf5_serial_hl hdf5_serial` に変更

```
--- LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_hl hdf5
+++ LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_serial_hl hdf5_serial
```

あとは、Caffe をコンパイルして、単体テストを実行します。
```
make
make test
make runtest
```
単体テストでは二千行以上のログが出力されます。
その末尾が下記のように `PASSED` になればOK（多分） :sweat_smile: 
```
[==========] 1090 tests from 150 test cases ran. (77712 ms total)
[  PASSED  ] 1090 tests.
```

次に、MNIST という手書き数字画像のデータベースで学習とテストを実行します。

まず、データを入手して、変換します。
```
cd data/mnist
./get_mnist.sh
cd ../..
./examples/mnist/create_mnist.sh
```

実行に先立ち、GPU モードを CPU モードに設定変更します。
`examples/mnist/lenet_solver.prototxt` を編集します。
```
-solver_mode: GPU
+solver_mode: CPU
```
学習を実行します。
```
./examples/mnist/train_lenet.sh
```
実行には20分以上かかりました。ログの末尾が下記のようになれば良さそう（多分） :sweat_smile: 
```
I0617 01:06:25.591403  3693 solver.cpp:317] Iteration 10000, loss = 0.00308486
I0617 01:06:25.591476  3693 solver.cpp:337] Iteration 10000, Testing net (#0)
I0617 01:06:32.654916  3693 solver.cpp:404]     Test net output #0: accuracy = 0.9907
I0617 01:06:32.654999  3693 solver.cpp:404]     Test net output #1: loss = 0.0286426 (* 1 = 0.0286426 loss)
I0617 01:06:32.655014  3693 solver.cpp:322] Optimization Done.
I0617 01:06:32.655027  3693 caffe.cpp:222] Optimization Done.
```

素人の憶測ですが、**accracy** が 1 に近ければ学習成功なのかと思われます。
なお、Caffe 関連の情報を検索すると **"Test score #0"** が正解率だとの記載が散見されたのですが、自分が実行した範囲では見当たりませんでした。上記の **"Test net output #0: accuracy"** がそれに代わるもののように見えました。

この学習の結果、
`./examples/mnist/lenet_iter_10000.caffemodel`
が生成されるので、テストではこれを参照します。

最後に、テストを実行します。
```
./build/tools/caffe test -model ./examples/mnist/lenet_train_test.prototxt -weights ./examples/mnist/lenet_iter_10000.caffemodel
```

テストは学習とは違ってわずか数秒で終わりました。
ログは四百行近く出力されましたが、末尾が下記のようになればOK（多分） :sweat_smile: 
```
I0617 01:24:38.824632  4486 caffe.cpp:292] accuracy = 0.9874
I0617 01:24:38.824659  4486 caffe.cpp:292] loss = 0.0422483 (* 1 = 0.0422483 loss)
```

この MNIST というサンプルを実行できたのはいいのですが、結果は各カテゴリに対する確率が表示されるだけなのだそうです。つまり、素人としては、サンプルを実行して無事に流れただけでは、何がどうなっているのかサッパリわかりません。

そこで、まずは、MNIST の手書き数字画像を見てみたくなります。
データは data/mnist に保存されている下記２つのファイルです。

    - t10k-images-idx3-ubyte
    - train-images-idx3-ubyte

これに含まれる画像を見る方法については [taitai0226](http://qiita.com/taitai0226)さんの下記の記事に紹介されています。
[MNISTの学習用画像を見てみよう！（２）](http://qiita.com/taitai0226/items/4116f5f64d0672c51e5a)

紹介されているとおり GNU Octave というアプリを使って手書き数字の画像を拝見できました。
[taitai0226](http://qiita.com/taitai0226)さん、ありがとうございました :pray: 



最後に、以上の内容は
[初めてのディープラーニング
──オープンソース"Caffe"による演習付き](http://www.ric.co.jp/book/contents/book_1022.html)
を参考にさせて頂いています。
ubuntu 15.10 に特有の設定変更などもあったので、手順をここでメモとしてまとめました。