Caffe, Pylearn2をまとめて試す


##環境
Dockerで新しく作成したUbuntuコンテナ

- CentOS release 6.6
	- Docker version 1.3.2, build 39fa2fa/1.3.2
		- Ubuntu 14.04

- Caffe 3e12d49324793d4798ee10bb6ef6a1c1b7633baf (`git log | head -n 1`)
- Pylearn2 9870dec593c71c194ebc2044973f65acc32c8675

##Docker Hub

とりあえずお試しで使ってみたいという方に向けて、Caffe(python wrapper含む), Pylearn2のそれぞれの環境構築を行ったDockerコンテナを[Docker Hub](https://hub.docker.com/u/cordea/)に公開しました。
詳細はリポジトリのInformationをご参照下さい。

### Caffe

```haskell:bash
# docker pull cordea/pycaffe
```

この記事で言うと"make"まで終了している状態のコンテナです。

### Pylearn2

```haskell:bash
# docker pull cordea/pylearn2
```

"path"まで終了している状態のコンテナです。

#共通

## Create user

rootでもいいって人は飛ばして下さい。

```haskell:bash
# username="your user name"
# adduser --disabled-password --gecos '' $username
# adduser $username sudo
# echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
# su $username
```

基本だけとりあえずinstall
他にも共通のパッケージはありますが...

```bash
$ sudo apt-get update
$ sudo apt-get install python vim git wget
```

#Caffe

今回は **CPUモード** で動作させるため、NVIDIA Graphics Driverはインストールしません。

## Installation
```bash
$ sudo apt-get install make bc libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev libblas-dev libatlas-base-dev libgflags-dev libgoogle-glog-dev liblmdb-dev protobuf-compiler libsvm-dev libsvm3 libsvm-tools
```

### PyCaffe
[Anaconda Python](https://store.continuum.io/cshop/anaconda/)が推奨されていますがLinuxだと面倒なのはどちらでも変わらないので今回は使いません。

公式の通り`pip`で入れるなら (おそらく追加で`gfortran`のinstallが必要です)

```bash
$ sudo apt-get install python-pip
$ cd ~/caffe/python/
$ for req in $(cat requirements.txt); do sudo pip install $req; done
```

出来るだけ`apt-get`で管理したいなら

```bash
$ sudo apt-get install python-pip python-scipy python-matplotlib python-scikits-learn ipython python-h5py python-leveldb python-networkx python-nose python-pandas python-dateutil python-protobuf python-yaml python-gflags python-skimage cython
```

### CUDA

```bash
$ cd ~
$ cd 
$ chmod u+x cuda_6.5.14_linux_64.run 
$ ./cuda_6.5.14_linux_64.run 
Do you accept the previously read EULA? (accept/decline/quit): accept
Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 340.29? ((y)es/(n)o/(q)uit): n
Install the CUDA 6.5 Toolkit? ((y)es/(n)o/(q)uit): y
Enter Toolkit Location [ default is /usr/local/cuda-6.5 ]: 
/usr/local/cuda-6.5 is not writable.
Do you wish to run the installation with 'sudo'? ((y)es/(n)o): y
Do you want to install a symbolic link at /usr/local/cuda? ((y)es/(n)o/(q)uit): y
Install the CUDA 6.5 Samples? ((y)es/(n)o/(q)uit): n
Installing the CUDA Toolkit in /usr/local/cuda-6.5 ...

===========
= Summary =
===========

Driver:   Not Selected
Toolkit:  Installed in /usr/local/cuda-6.5
Samples:  Not Selected

$ sudo ldconfig /usr/local/cuda-6.5/lib64/
$ rm cuda_6.5.14_linux_64.run
```

###make


```bash
$ git clone https://github.com/BVLC/caffe
$ cd caffe/
$ cp Makefile.config.example Makefile.config  
$ echo "CPU_ONLY := 1" >> Makefile.config # 1/26 追記   
$ make all
$ make test
$ make runtest

...

[----------] Global test environment tear-down
[==========] 457 tests from 98 test cases ran. (14811 ms total)
[  PASSED  ] 457 tests.
```

##Tutorial

```bash
$ vim examples/mnist/lenet_solver.prototxt
```

```bash
$ ./data/mnist/get_mnist.sh 
$ ./examples/mnist/create_mnist.sh
$ ./examples/mnist/train_lenet.sh 
```

##PyCaffe Tutorials

[Caffeで手軽に画像分類](http://techblog.yahoo.co.jp/programming/caffe-intro/)に従ってTutorialを行います。


```bash
$ cd ~/caffe/examples/imagenet/
$ wget https://raw.githubusercontent.com/sguada/caffe-public/master/models/get_caffe_reference_imagenet_model.sh
$ chmod u+x get_caffe_reference_imagenet_model.sh
$ ./get_caffe_reference_imagenet_model.sh
$ cd ~/caffe/data/ilsvrc12/
$ ./get_ilsvrc_aux.sh
$ cd ~/caffe/
$ wget http://www.vision.caltech.edu/Image_Datasets/Caltech101/101_ObjectCategories.tar.gz
$ tar xzvf 101_ObjectCategories.tar.gz
```

```bash
$ echo "export PYTHONPATH=$HOME/caffe/python:$PYTHONPATH" >> ~/.bashrc
$ source ~/.bashrc
```

###実行

####リファレンスモデルでの分類

```bash
$ cd ~/caffe/python/
$ python classify.py --raw_scale 255 ../101_ObjectCategories/airplanes/image_0001.jpg ../result.npy
```
上のリンクに従って`show_result.py`を作成し、実行します。

```bash
$ cd ~/caffe/
$ python show_result.py data/ilsvrc12/synset
synset_words.txt  synsets.txt       
$ python show_result.py data/ilsvrc12/synset_words.txt result.npy 
#1 | n04552348 warplane, military plane | 84.8%
#2 | n04008634 projectile, missile |  5.5%
#3 | n02690373 airliner |  5.1%
```

#####classify.pyでエラーが出た場合

numpyのioとPyCaffeのio.pyが競合するようです。([Strange Issue using Python #782](https://github.com/BVLC/caffe/issues/782))

```bash
$ python classify.py --raw_scale 255 ~/caffe/101_ObjectCategories/airplanes/image_0001.jpg ../result.npy
Traceback (most recent call last):
  File "classify.py", line 7, in <module>
    import numpy as np

...


  File "/usr/local/lib/python2.7/dist-packages/skimage/util/dtype.py", line 8, in <module>
    dtype_range = {np.bool_: (False, True),
AttributeError: 'module' object has no attribute 'bool_'
```

無理やりな方法ですが`io.py`を`caffe_io.py`にrenameします。
ここでrenameした場合には、次の"Caffeを特徴抽出器として使った分類"に作成する`feature.py`でもrenameする必要があります。

```bash
$ cd ~/caffe/python/
$ aftfile="caffe_io"
$ for file in `find . -name "*.py"`; do; cat $file | sed -e "s/import [\w\.]*io/import $aftfile/g" | sed -e "s/caffe\.io/caffe\.$aftfile/g" > $file".tmp";mv $file".tmp" $file; done
$ mv "caffe/io.py" "caffe/"$aftfile".py"
```


　

####Caffeを特徴抽出器として使った分類
前のブランチに切り替えたまま戻すのをすっかり忘れていたので、もしかしたら少し違う部分があるかもしれません。

```bash
$ cd ~/caffe
$ cp examples/imagenet/imagenet_deploy.prototxt examples/imagenet/imagenet_feature.prototxt
$ vim examples/imagenet/imagenet_feature.prototxt
```

次のように`imagenet_feature.prototxt`を変更して下さい。

```vim:imagenet_feature.prototxt
...

154   top: "fc6wi"

...

162   bottom: "fc6wi"

...
```

　deeplearning-tutorials
libsvm formatで特徴量を並べたファイルを作成します。

```bash
$ cd ~/caffe/
$ git clone https://github.com/CORDEA/deeplearning-tutorials
$ mv ~/caffe/deeplearning-tutorials/caffe/feature.py ~/caffe/
$ python feature.py
```

もしくは

```bash
$ cd ~/caffe/
$ wget https://raw.githubusercontent.com/CORDEA/deeplearning-tutorials/master/caffe/feature.py
$ python feature.py
```

`train`commandは`svm-train`に
`predict`commandは`svm-predict`に
それぞれ名前が変わっていますので注意して下さい。

```bash
$ svm-scale -s scale.txt train.txt > train_scaled.txt
$ svm-scale -r scale.txt test.txt > test_scaled.txt
$ svm-train -c 0.03 train_scaled.txt caltech101.model
```


####Fine tuning

必要なファイルを用意します。

"Caffeを特徴抽出器として使った分類"で`git clone`した場合

```bash
$ cd ~/caffe/
$ mv ~/caffe/deeplearning-tutorials/caffe/fine_tuning.py ~/caffe/
$ python fine_tuning.py
```

wgetする場合

```bash
$ cd ~/caffe/
$ wget https://raw.githubusercontent.com/CORDEA/deeplearning-tutorials/master/caffe/fine_tuning.py
$ python fine_tuning.py
```

`convert_imageset.bin`の仕様が変わっているので参考記事の通りでは動作しません。
参考記事で指定されているflagの`1`が現在のどれに当たるかわかりませんが、おそらく`-gray`だろうと判断して進めています。

```bash
$ build/tools/convert_imageset.bin -gray -resize_width 256 -resize_height 256 101_ObjectCategories/ train.txt caltech101_train_leveldb
$ build/tools/convert_imageset.bin -gray -resize_width 256 -resize_height 256 101_ObjectCategories/ val.txt caltech101_val_leveldb
$ build/tools/compute_image_mean.bin caltech101_train_leveldb caltech101_mean.binaryproto
```

参考記事から参照先が変わっていますので気をつけて下さい。

```bash
$ cp ~/caffe/models/bvlc_reference_caffenet/*.prototxt ~/caffe/
$ cd ~/caffe/
$ sed -i -e 's/fc8/fc8ft/g' train_val.prototxt deploy.prototxt
```

以下の部分をエディタ(viとか)で変更して下さい。

```vim:solver.prototxt
1 net: "train_val.prototxt"

...

4 base_lr: 0.001

...

14 solver_mode: CPU
```

```vim:train_val.prototxt
8     source: "caltech101_train_leveldb"
9     backend: LEVELDB

...

14     mean_file: "caltech101_mean.binaryproto"

...

25     source: "caltech101_val_leveldb"
26     backend: LEVELDB

...

31     mean_file: "caltech101_mean.binaryproto"

...

321     num_output: 102
```

```vim:deploy.prototxt
5 input_dim: 256
6 input_dim: 256

...

204     num_output: 102
```

```bash
$ build/tools/caffe train -solver solver.prototxt
```


　

　


#Pylearn2

## Installation
```bash
$ sudo apt-get install python-setuptools python-pip python-dev python-numpy python-scipy python-yaml python-matplotlib liblapack-dev python-nose2 cython
```

```bash
$ sudo pip install theano
```


```bash
$ cd ~
$ git clone https://github.com/lisa-lab/pylearn2.git
$ cd pylearn2
$ sudo python setup.py develop
```


### path

```vim
$ echo "export PATH=$HOME/pylearn2/pylearn2/scripts/:$PATH" >> ~/.bashrc
$ echo "export PYLEARN2_DATA_PATH=$HOME/.data/lisa/data" >> ~/.bashrc
$ source ~/.bashrc
```

##Tutorials

### Gaussian-Bernoulli RBM examples using CIFAR10

```bash
$ cd ~/pylearn2/pylearn2/scripts/datasets/
$ ./download_cifar10.sh
$ cd ~/pylearn2/pylearn2/scripts/tutorials/grbm_smd/
$ python make_dataset.py
$ train.py cifar_grbm_smd.yaml
$ show_weights.py cifar_grbm_smd.pkl --out weights_result.png # GUIがある場合は --out は無くても良い
$ plot_monitor.py cifar_grbm_smd.pkl --out monitor_result.png
Put e, b, s or h in the list somewhere to plot epochs, batches, seconds, or hours, respectively.
Enter a list of channels to plot (example: A, C,F-G, h, <test_err>) or q to quit or o for options: b,L,M
set x_axis to example
A. bias_hid_max:cifar_grbm
B. bias_hid_mean:cifar_grbm
C. bias_hid_min:cifar_grbm
D. bias_vis_max:cifar_grbm
E. bias_vis_mean:cifar_grbm
F. bias_vis_min:cifar_grbm
G. h_max:cifar_grbm
H. h_mean:cifar_grbm
I. h_min:cifar_grbm
J. learning_rate:cifar_grbm
K. objective:cifar_grbm
L. reconstruction_error:cifar_grbm
M. total_seconds_last_epoch:cifar_grbm
N. training_seconds_this_epoch:cifar_grbm

Put e, b, s or h in the list somewhere to plot epochs, batches, seconds, or hours, respectively.
Enter a list of channels to plot (example: A, C,F-G, h, <test_err>) or q to quit or o for options: q
```

####imageの確認
dockerで動作させている場合

`docker cp`でlocalにcopyしてるだけ

```bash
% container="pylearn2" # Enter the container ID or name
% for file in `echo weights_result.png monitor_result.png`;do;docker cp $container:/home/cordea/pylearn2/pylearn2/scripts/tutorials/grbm_smd/$file /host/path/to/dir/;done
% open *.png # for Mac
```


### SdA examples using MNIST

```bash
$ cd ~/pylearn2/pylearn2/scripts/datasets/
$ python download_mnist.py
$ cd ~/pylearn2/pylearn2/scripts/tutorials/stacked_autoencoders/tests
$ python test_dae.py
```

## 自分の用意したデータを使う

**csvをそのまま使用するなら[こちら](http://fastml.com/pylearn2-in-practice/)が参考になります。**

今回はcsvからpklを作成する方法を紹介します。

画像をresize, gray-scale化した上でcsvに変換します。

```bash
$ cd ~
$ git clone https://github.com/CORDEA/deeplearning-tutorials.git
$ cd deeplearning-tutorials/pylearn2
$ mkdir in
```
`convertImage.py`は以下の様なディレクトリ構造を想定して作成しています。
ディレクトリ名をラベル情報として下さい。

```
.
├── convertImage.py
    ├── in
        ├── hoge # label name
        |   ├── hogehoge.png
        |   ...
        |
        ├── huge
        |   ├── hugehuge.png
        |   ...
        ...
```

```bash
$ python convertImage.py
```

作成した`train.csv`をpklファイルにします。

```bash
$ python createpkl.py
```

`train.pkl`を`~/pylearn2/pylearn2/scripts/tutorials/`のサンプルを参考にして使用すれば使えるかと思います。

###例

クラス数は10として例示します。

```bash
$ cd ~/pylearn2/pylearn2/scripts/tutorials/dbm_demo/
$ cp ~/deeplearning-tutorials/pylearn2/train.pkl ./
```

```bash:rbm.yaml
13,21c13
<     dataset: &data !obj:pylearn2.datasets.binarizer.Binarizer {
<         # We use the "raw" tag to specify the underlying dataset defining
<         # the sampling probabilities should be MNIST.
<         raw: &raw_train !obj:pylearn2.datasets.mnist.MNIST {
<             which_set: "train",
<             start: 0,
<             stop: %(train_stop)i
<         }
<     },
---
>     dataset: !pkl: "train.pkl",
```

```vim:train_dbm.py
22     hyper_params = {'detector_layer_dim': 10,
```

```bash
$ python train_dbm.py rbm.yaml
$ show_weights.py dbm.pkl --out figure.png
```


####エラー

```python:pylearn2/pylearn2/space/__init__.py
794                 raise TypeError(Cannot safely cast batch dtype %s to space's dtype %s. % (batch.dtype, self.dtype))
```

ここでエラーが出たのですが、データの方を弄ってもいまいち上手く行かなかったので

```python:pylearn2/pylearn2/space/__init__.py
794                 # raise TypeError("Cannot safely cast batch dtype %s to "
795                 print "Might not be safely cast batch dtype %s to space's dtype %s." \
796                         % (batch.dtype, self.dtype)
```

```python:pylearn2/pylearn2/format/target_format.py
 98             try:
 99                 print "Run the conversion to int64 from %s" % (targets.dtype)
100                 targets = np.array([[int(r) for r in label] for label in targets])
101             except:
102                 raise TypeError("need an integer array for targets, %s" % (targets.dtype))
```

今のところこんなかんじで無理やり動かしています...


お疲れ様でした。

# 参考
## Caffe
- [Caffe](http://caffe.berkeleyvision.org/)
	- [Installation](http://caffe.berkeleyvision.org/installation.html)
	- [Training LeNet on MNIST with Caffe](http://caffe.berkeleyvision.org/gathered/examples/mnist.html)
- [Caffeで手軽に画像分類 - Yahoo! デベロッパーネットワーク](http://techblog.yahoo.co.jp/programming/caffe-intro/)
- [はじめるDeep learning](http://qiita.com/icoxfog417/items/65e800c3a2094457c3a0)

## Pylearn2

- [Pylearn2 dev documentation](http://deeplearning.net/software/pylearn2/)
	- [Download and installation](http://deeplearning.net/software/pylearn2/index.html#download-and-installation)
	- [Library Documentation](http://deeplearning.net/software/pylearn2/library/datasets.html#module-pylearn2.datasets.csv_dataset)
	- [Quick-start example](http://deeplearning.net/software/pylearn2/tutorial/index.html#tutorial)

- [FastML](http://fastml.com/)
	- [Pylearn2 in practice](http://fastml.com/pylearn2-in-practice/)
	- [How to get predictions from Pylearn2](http://fastml.com/how-to-get-predictions-from-pylearn2/)

- [JSAI's AI Tool Introduction - Deep Learning and Pylearn2](http://www.slideshare.net/ktrnkym/ai-tool-introduction-20140710b)

- [pylearn2 入門したい編 - laughingのブログ](http://laughing.hatenablog.com/entry/2013/11/30/pylearn2_%E5%85%A5%E9%96%80%E3%81%97%E3%81%9F%E3%81%84%E7%B7%A8)

- [CaffeでDeep Learning つまずきやすいところを中心に](http://qiita.com/uchihashi_k/items/8333f80529bb3498e32f)

- [Pylearn2を使って手書き文字認識を行う](http://qiita.com/dsanno/items/a1d805a89e192c44730d)

- [今ナウいディープラーニングのライブラリ「Pylearn2」のインストールとチュートリアル](http://qiita.com/mizuki0420@github/items/3f9c97b32e8d6e37abad)

- [男のための機械学習〜RBMでA◯女優さんの共通特徴量を得よう〜 - 新kensuke-miの日記](http://kensuke-mi.xyz/kensuke-mi_diary/2014/11/rbma.html)

- [Python/PILによる画像のグレイスケール化とアスキーアート化 - Soleil cou coupé](http://d.hatena.ne.jp/xef/20120920/p1)