TSUBAME2.5でのCaffeによる3D-CNNの利用方法


# はじめに
TSUBAME2.5では、[Gsicの実験的サービスのページ](http://tsubame.gsic.titech.ac.jp/labs)に従って以下のようにコマンドを入力すると、Caffeを利用する準備が整います。

```shell-session
~> source /usr/apps.sp3/nosupport/gsic/env/caffe-0.13.sh
```

しかしこのバージョンのCaffe(ver0.13)に実装されていない3D-CNN(3D Convolutional Neural Network)の機能を利用する場合は別バージョンのCaffeの導入を行う必要があります。そこで本記事では、TSUBAME2.5において3D-CNNの機能を利用したい場合のCaffeの機能を記します。


# 環境
TSUBAME2.5を前提にしています。


# 3D-CNN用のCaffeの導入
## 必要環境の準備
まずCaffeのコンパイルに必要なOpenBLASのインストールを行います。シェルにおいてインストールしたいディレクトリで以下のように入力します。
(参考：[Linux で OpenBLAS と ATLAS を使って行列積の計算をしてみた - Unity 勉強メモ](http://unity-memo.hatenablog.com/entry/2015/03/03/104238))

```shell-session
~> git clone https://github.com/xianyi/OpenBLAS.git
~> cd OpenBLAS
~> make
~> make install
```

また、[Caffe公式](http://caffe.berkeleyvision.org/installation.html
)によれば、PythonからCaffeの機能を利用する場合、[Anaconda](https://www.continuum.io/downloads)のインストールが推奨されています。Pythonのバージョンマネージャにpyenvを用いている場合は、以下のコマンドで Anacondaのインストールと、グローバル環境にAnacondaを利用する設定ができます(Anacondaのバージョンは適宜変更する必要があります)。

```shell-session
~> pyenv install anaconda-2.3.0
~> pyenv global anaconda-2.3.0
```


## Caffeのダウンロード
[GitHub](https://github.com/jmerkow/caffe/tree/nd-pooling-public)からCaffeをダウンロードします。以下、`(ダウンロードしたディレクトリ)/caffe`を`$CAFFE ROOT`と表します。

```shell-session
~> git clone https://github.com/jmerkow/caffe.git
```

## Makefileの設定
つぎにMakefileの設定を行います。`$CAFFE ROOT/Makefile.config.example`を`$CAFFE ROOT/Makefile.config`にコピーします。

```shell-session
~> cd $CAFFE_ROOT
~> cp Makefile.config.example Makefile.config
```

`$CAFFE ROOT/Makefile.config`の一部を以下のように修正します。`BLAS INCLUDE`と`BLAS LIB`のパスは適宜変更します。

（修正前）

```mf
# USE_CUDNN := 1

# CUDA_DIR := /ust/local/cuda

BLAS := atlas
```

（修正後）

```mf
USE_CUDNN := 1

CUDA_DIR := /usr/apps.sp3/cuda/7.0

BLAS := open
BLAS_INCLUDE := (自分のホームディレクトリ)/.local/OpenBLAS/include
BLAS_LIB := (自分のホームディレクトリ)/.local/OpenBLAS/lib
```

## Caffeのコンパイル
`$CAFFE ROOT/Makefile.config`の編集が終わったら、コンパイル作業を行います。`make`コマンドの`-j`オプションは並列処理を行うことを表しています。

```shell-session
~> make all -j
~> make test -j
~> make runtest
```

全てエラーなく終了すればCaffeの導入は終了となります。`caffe`コマンドを実行して、以下のような表示がされれば準備が完了しています。

```shell-session
~> caffe
  caffe: command line brew
  usage: caffe <command> <args>
  commands:
    train           train or finetune a model
    test            score a model
    device_query    show GPU diagnostic information
    time            benchmark model execution time
    Flags from tools/caffe.cpp:
      -gpu (Run in GPU mode on given device ID (Legacy switch, use -gpus).)
        type: int32 default: -1
      -gpus (Run in GPU mode on given device IDs separated by ’,’.Use ’-gpus all’
        to run on all available GPUs.) type: string default: ""
      -iterations (The number of iterations to run.) type: int32 default: 50
      -model (The model definition protocol buffer text file..) type: string
        default: ""
      -snapshot (Optional; the snapshot solver state to resume training.)
        type: string default: ""
      -solver (The solver definition protocol buffer text file.) type: string
        default: ""
      -weights (Optional; the pretrained weights to initialize finetuning,
        separated by ’,’. Cannot be set simultaneously with snapshot.)
        type: string default: ""
```

# 学習方法
基本的に通常のCaffeと変わりませんが、3D-CNNのためのデータを扱う際はlmdb形式やLEVELDB形式は使えず、HDF5形式のみ利用可能なようです(参考：[ND convolution with im2col #2049 by jeffdonahue](https://github.com/BVLC/caffe/pull/2049
))。
またprototxtファイルに構造を記述する際も、3D-CNN以外の記述方法は[Caffe公式ドキュメント](http://caffe.berkeleyvision.org/tutorial/layers.html)に書かれている通りで問題ありません。3D-Convolution層、3D-Pooling層は、例えば以下のように`kernel_size`を3回書くことでカーネルのサイズを指定し、利用することができます。

（3D-Convolution層）

```yaml
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    engine: CAFFE
    num_output: 96
    kernel_size: 3
    kernel_size: 3
    kernel_size: 3
    stride: 1
    pad: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
```

（3D-Pooling層）

```yaml
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "relu1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3 
    kernel_size: 3 
    kernel_size: 3 
    stride: 1      
  }
}
```

3D-Convolution層を利用する場合、上記のように`convolution_param`以下に`engine: CAFFE`の記述が必要です。