TensorFlowでImageNetの学習データを使った画像認識をおこなうためのセットアップ手順　- Linux(Ubuntu) GPU版

[Googleの機械学習フレームワーク「TensorFlow」でImageNetの学習データを使った画像認識を試してみた](http://qiita.com/nkjm/items/a2dada74d48b29f0e5f4)の記事ではMacOS Xをベースにしたセットアップ方法を記載しました。今回はLinux(Ubuntu)で、GPUを利用する場合のセットアップ方法を記載しておきます。

全体を通して概ね公式ドキュメント通りでいけますが、ImageNetの学習データを利用するためにリリース7ac6fdfにおいてはprotobufのソースを一部修正する必要があります。

## 環境
- OS: Ubuntu Server 14.04 LTS
- Python: 2.7.6
- TensorFlow: 0.6.0 (2016/2/15時点で最新)
- GPU: 利用する

今回はOS側ではすでにGPUは認識しており、必要なツールはインストールされているという前提で進めます。したがってCUDA Toolkit、cudnnなどのライブラリのインストール手順は含まれていません。


## インストール手順

まずbazelをインストールします。

```Terminal
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ sudo apt-get install pkg-config zip g++ zlib1g-dev unzip
$ wget https://github.com/bazelbuild/bazel/releases/download/0.1.5/bazel-0.1.5-installer-linux-x86_64.sh
$ chmod +x bazel-0.1.5-installer-linux-x86_64.sh
$ ./bazel-0.1.5-installer-linux-x86_64.sh --user
$ export PATH="$PATH:$HOME/bin"
```

~/.bashrcを編集してPATHを設定しておきます。

```bash:~/.bashrc
#省略
export PATH="$HOME/bin:$PATH"
```

もし手元の環境にpipとその他依存関係にあるパッケージと、virtualenvをインストールしておきます。

```Terminal
$ sudo apt-get install python-pip python-numpy swig python-dev
$ sudo pip install --upgrade virtualenv
```

virtualenvでTensorFlow用の独立したpythonの実行空間を作成します。
下記ではユーザーのホームディレクトリ直下に作成していますが、適宜変更してください。

```Terminal
$ virtualenv --system-site-packages ~/tensorflow
```

作成した独立実行空間を現在のシェルで有効化するため、activateファイルを読み込みます。今回はbashを利用している前提です。成功するとプロンプトが変わります。

```Terminal
$ source ~/tensorflow/bin/activate
(tensorflow)$ 
```

ipythonをpipでインストールします。

```Terminal
(tensorflow)$ pip install ipython
```

TensorFlowのGithubレポジトリからソースをダウンロードします。
このレポジトリ外にあるsubmoduleを必要とするので--recurse-submodulesオプションを指定していることに注意してください。

```Terminal
(tensorflow)$ git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git
```

ダウンロードしたソース中のcoded_stream.hを編集してバッファの制限値を64MBから256MBに大きくします。この修正はおそらく近い将来不要になると思いますが、現時点ではImageNetの学習データを利用するのに必要です。

```c:tensorflow/google/protobuf/src/google/protobuf/io/coded_stream.h
  static const int kDefaultTotalBytesLimit = 256 << 20;  // 64MB
```



ダウンロードしたソース直下に移動し、configureスクリプトを実行します。

```Terminal
(tensorflow)$ cd tensorflow/
(tensorflow)$ TF_UNOFFICIAL_SETTING=1 ./configure
```

このconfigureスクリプトではいくつかの質問に答える必要があります。
ほぼすべてデフォルト値で問題ありませんが、AWS EC2のG2インスタンスを利用している場合は下記のcompute capabilityを変更して3.0とする必要があります。

```
Please specify a list of comma-separated Cuda compute capabilities you want to build with.
You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus.
Please note that each additional compute capability significantly increases your build time and binary size.
[Default is: "3.5,5.2"]: 3.0
```


ソースをビルドします。

```Terminal
(tensorflow)$ bazel build -c opt --config=cuda //tensorflow/cc:tutorials_example_trainer
(tensorflow)$ bazel-bin/tensorflow/cc/tutorials_example_trainer --use_gpu
```

pipパッケージ化します。

```Terminal
(tensorflow)$ bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
(tensorflow)$ bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg

```

作成したpipパッケージをインストールします。

```Terminal
(tensorflow)$ pip install /tmp/tensorflow_pkg/tensorflow-0.6.0-py2-none-any.whl
```

これでほぼインストールは完了なのですが、今回はImageNetのトレーニングデータを使った画像認識をおこないたいので、それを追加でインストールします。まずソースに含まれるimagenetディレクトリをvirtualenvで作成した独立実行空間配下にコピーします。

```Terminal
(tensorflow)$ cp -a tensorflow/models/image/imagenet ~/tensorflow/lib/python2.7/site-packages/tensorflow/models/image/
```

コピーしたディレクトリに移動し、classify_image.pyスクリプトを実行します。
初回実行時には必要なデータがダウンロードされ、最後にサンプルとして用意されているパンダの画像の解析が実行されます。

```Terminal
(tensorflow)$ cd ~/tensorflow/lib/python2.7/site-packages/tensorflow/models/image/imagenet/
(tensorflow)$ python classify_image.py

giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.89233)
indri, indris, Indri indri, Indri brevicaudatus (score = 0.00859)
lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00264)
custard apple (score = 0.00141)
earthstar (score = 0.00107)

(tensorflow)$
```

上記のような結果がでていれば成功です。結果はジャイアントパンダで信頼度は89%とのこと。

任意の画像を解析するには下記のように--image_fileオプションで画像ファイルを指定します。

```Terminal
(tensorflow)$ python classify_image.py --image_file [画像ファイル]
```


## 関連記事
- [Googleの機械学習フレームワーク「TensorFlow」でImageNetの学習データを使った画像認識を試してみた](http://qiita.com/nkjm/items/a2dada74d48b29f0e5f4)
- [error parsing inception v3 file: 64MB python protobuf parsing limit #582](https://github.com/tensorflow/tensorflow/issues/582)