BVLC/caffeのwindowsブランチを使ってインストールからcifar10の動作確認まで（CPU版）

# 更新履歴

- 2016/04 初投稿。動作確認。
- 2017/04/02 タグを修正。動作確認はしていない。

# はじめに
BVLC/caffeのwindowsブランチのソースコードを使って、caffeのインストールからcifar10の学習と分類まで試してみました。環境構築するにあたって、「なぜその作業が必要なのか」わからない点が多くあり、そのような点は適当にスルーしています（つまり、本当に正しく動いているかは保証できないYO）。

# 参考にしたページ
+ [【Caffe】Windows7にCaffeをインストール　（いつもの作業備忘録）](http://punyo-er-met.hateblo.jp/entry/2016/03/27/110656)
+ [CaffeでDeep Learning (2)　（桜遡）](http://www.hsakurai.com/entry/2015/08/17/235834)
+ [[deep learning] caffeとCIFAR-10を使って画像判別テスト(詳細)　（脳汁portal）](http://portaltan.hatenablog.com/entry/2016/02/26/182545)

# 環境
+ windows8(64bit)
+ Visual Studio Express 2013 for Windows Desktop
+ cygwin(シェルスクリプトを実行するため)

# やったこと

1. githubのコードをダウンロードしてビルド
2. サンプルデータ(cifar10)を使って学習
3. 学習結果を用いて画像のクラス分類

※やったことは、上記の「参考にしたページ」やソースのREADMEに書かれていることとほぼ同じです。

## githubのコードをダウンロードしてビルド

ソースは以下です。
[https://github.com/BVLC/caffe/tree/windows](https://github.com/BVLC/caffe/tree/windows)

### ビルド前準備

ビルド自体は、caffe/windows/Caffe.slnを開いてVisual Studio上でビルドを実行するだけですが、そのままではエラーが出てしまったので、以下のような変更をしました。

#### CommonSettings.props.exampleの変更

caffe/windowsフォルダにあるCommonSettings.props.exampleを
CommonSettings.propsに改名(語尾の.exmapleを削除)します。
そして、中身の以下のタグを改変しました。

変更前
```
<CpuOnlyBuild>false</CpuOnlyBuild>
<UseCuDNN>true</UseCuDNN>
<PythonSupport>true</PythonSupport>
<PythonDir>C:\Miniconda2\</PythonDir>
```

変更後
```
<CpuOnlyBuild>true</CpuOnlyBuild>
<UseCuDNN>false</UseCuDNN>
<PythonSupport>true</PythonSupport>
<PythonDir>～略～\Anaconda2\</PythonDir>
```

↑は、GPUを使わない設定です。GPUを使いたい場合は、公式のREADMEを参考に改変してください。
　また、公式のREADMEではpython環境としてMinicondaが挙げられていましたが、自分のPCに既にAnacondaが入っていたのでAnacondaを使うことにしました。Anacondaのパスの”～略～”の部分は環境依存なので自分の環境に合わせて修正してください。


#### ソースの改変

##### src/caffe/util/db_lmdb.cppの改変

以下のように書き換えないと実行時エラーが出てしまいました。そこで、[Problems with MDB in the mnist example #1298](https://github.com/BVLC/caffe/issues/1298) を参考に以下のように改変しました。

変更前
```
const size_t LMDB_MAP_SIZE = 104857600;    // 100 MB
```

変更後
```
const size_t LMDB_MAP_SIZE = 1073741824;
```

変更した値の意味はよく分かりません。ちなみに、mnistのデータセットを試す場合、convert_mnist_data.cppに対して同様の改変をする必要がありました。

##### プロジェクトのプロパティの変更(GPUの場合)

今回はGPUで動作確認しないので必須ではありませんが、GPUで実行したい場合は、プロジェクトのプロパティを変更する必要がありそうです。デフォルトではwarningをエラーと見なす設定になっているので、その設定を変更する必要があります。これに関しては、以下のページが参考になりました。
[【Caffe】Windows7にCaffeをインストール　（いつもの作業備忘録）](http://punyo-er-met.hateblo.jp/entry/2016/03/27/110656)


以上によって、ビルドできるはずです。初めてビルドする時はNuGetが必要なライブラリをダウンロードしてくれるので、その分、時間がかかるかもしれません。


## サンプルデータ(cifar10)を使って学習

### 学習用データの用意

#### データのダウンロード

caffe/data/cifar10フォルダをカレントディレクトリとして、get_cifar10.shを実行します。すると、data_batch_1.bin～data_batch_5.binとtest_batch.binがダウンロードされます。

#### caffeで読み込める形式にデータを変換

ダウンロードしたデータをcaffeで読み込める形式に変換する必要があるようです。そのために、caffeフォルダをカレントディレクトリとして、./examples/cifar10/create_cifar10.shを実行します。なお、スクリプトを少し改変しました（ビルドしたバイナリのパスを修正しました）。

```create_cifar10.sh
#!/usr/bin/env sh
# This script converts the cifar data into leveldb format.

EXAMPLE=examples/cifar10
DATA=data/cifar10
DBTYPE=lmdb

echo "Creating $DBTYPE..."

rm -rf $EXAMPLE/cifar10_train_$DBTYPE $EXAMPLE/cifar10_test_$DBTYPE

./Build/x64/Release/convert_cifar_data.exe $DATA $EXAMPLE $DBTYPE

echo "Computing image mean..."

./Build/x64/Release/compute_image_mean.exe -backend=$DBTYPE \
  $EXAMPLE/cifar10_train_$DBTYPE $EXAMPLE/mean.binaryproto

echo "Done."

```

↑によって、caffe/examples/cifar10にcifar10_test_lmdbとcifar10_train_lmdbというフォルダが生成されるはずです。


### 学習

以下のページを参考にしました。むしろ、やったこともこのページと同じです。
[CaffeでDeep Learning (2)　（桜遡）](http://www.hsakurai.com/entry/2015/08/17/235834)

まず、学習する前にcaffe/examples/cifar10フォルダにある、cifar10_quick_solver.prototxtとcifar10_quick_solver_lr1.prototxtの最後の行を書き換えてCPUで学習するように変更します。

変更前
```
solver_mode: GPU
```

変更後
```
solver_mode: CPU
```

そして、学習用スクリプト(examples/cifar10/train_quick.sh)を実行します。なお、スクリプトを少し改変しました（ビルドしたバイナリのパスを修正しました）。

```train_quick.sh
#!/usr/bin/env sh

TOOLS=./Build/x64/Release

$TOOLS/caffe train \
  --solver=examples/cifar10/cifar10_quick_solver.prototxt

# reduce learning rate by factor of 10 after 8 epochs
$TOOLS/caffe train \
  --solver=examples/cifar10/cifar10_quick_solver_lr1.prototxt \
  --snapshot=examples/cifar10/cifar10_quick_iter_4000.solverstate.h5
```

実行時のカレントディレクトリはcaffeフォルダです。
```
$ ./examples/cifar10/train_quick.sh
```

### 学習結果の確認

pythonで画像の分類をしてみます。

まず、python上でpycaffeを呼べるようにするために、caffe/Build/x64/Release/pycaffeにあるcaffeフォルダをcaffeフォルダごと"～略～/Anaconda2/Lib/site-packages"にコピーします（site-packagesフォルダの中にcaffeフォルダがある状態にします）。
　あるいは、caffe/Build/x64/Release/pycaffe/caffeまでのパスを通す方法でもよいかもしれませんが、試していないのでよくわかりません。

次にクラス判定用プログラムを作成します。判定プログラムは以下のウェブページを参考にしました。（ほぼパクったに等しいので恐縮ですが、）平均画像を読み込む部分を少し変えました。
[[deep learning] caffeとCIFAR-10を使って画像判別テスト(詳細)　（脳汁portal）](http://portaltan.hatenablog.com/entry/2016/02/26/182545)

```cifar_test.py

import sys
import caffe
from caffe.proto import caffe_pb2
import numpy as np

net_path = 'cifar10_quick.prototxt'
model_path = 'cifar10_quick_iter_4000.caffemodel.h5'
mean_path = 'mean.binaryproto'

cifar_map = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]


mean_blob = caffe_pb2.BlobProto()
mean_data = open( mean_path , 'rb' ).read()
mean_blob.ParseFromString(mean_data)
mean_arr = np.array( caffe.io.blobproto_to_array(mean_blob) )

classifier = caffe.Classifier(
    net_path,
    model_path,
    mean=mean_arr[0],
    image_dims=(32, 32),
    raw_scale=255)


image = caffe.io.load_image(sys.argv[1])

predictions = classifier.predict([image],oversample=False)
answer = np.argmax(predictions) 

print 'Answer: {0}({1:.0f}%)'.format(cifar_map[answer], predictions[0][answer]*100)

```

これで準備完了です。
caffe/examples/cifar10フォルダでcifar_test.pyを実行します。
第1引数に判定したい画像ファイル名を指定します。


```
cifar_test.py neko.jpg
```

入力画像neko.jpgは↓です。（[K-DON! ANIMALSのネコ](http://www.takaratomy-arts.co.jp/items/item.html?n=Y828928)）

![neko.jpg](https://qiita-image-store.s3.amazonaws.com/0/122887/e32d72cc-d7a4-ee82-dab6-432f0cea5673.jpeg)


判定結果は、
dog(64%)と出ました…。まぁ、ドヤ顏がたくましいので犬っぽいかもしれません。