Googleの機械学習フレームワーク「TensorFlow」でImageNetの学習データを使った画像認識を試してみた - TensorFlowのインストールから画像認識まで


この記事はGoogleが公開した機械学習フレームワークのTensorFlowを使って画像認識を試してみたときのセットアップ手順と画像認識結果について記載しています。公式ドキュメントのチュートリアルではいくつかハマりどころがあったのでそこの解決策も折り込んでいます。

画像認識はあくまでもTensorFlowの用途の一つであり、この記事はTesnorFlowの本質や機械学習というテーマを深堀するというより、現在の画像認識のレベルとそのテクノロジーが身近になっているというところをお伝えすることに重きを置いています。


## TensorFlowとは？

TensorFlowはいわゆる機械学習のフレームワークです。
特にニューラルネットワークの敷居を下げるフレームワークとして注目されているようです。

とはいってもここではDeep Learning/深層学習、ニューラルネットワークといった機械学習の仕組みには深入りせず、このTensorFlowというフレームワークを使って何ができるのか、そしてそのセットアップ手順を簡単にまとめたいと思います。


## TensorFlowでできること

ニューラルネットワークでできることは多岐にわたると思いますが、一般的にインパクトが強いものの一つが画像認識だと思います。

- 手書き文字認識
- 写真から写っているものを認識

顔認識についてはすでにMacOS XのPhotoやFacebookといった普及しているソフトウェア・サービスで実装されていることから馴染み深いものになっています。

しかし現代のニューラルネットワークの技術では人間が写真をみて「何が写っている」と判断するのとかなり近しいレベルで被写体を認識することができるようになっています。

これは昨年のTEDでのフェイ・フェイ・リーさんのプレゼンテーションで多くの人に認知されるようになったように思います。
[コンピューターが写真を理解するようになるまで](https://www.ted.com/talks/fei_fei_li_how_we_re_teaching_computers_to_understand_pictures?language=ja)

TensorFlowではまさに上記のImageNetという学習データを使った画像認識が可能です。
しかも、通常ニューラルネットワークの環境は依存関係が複雑でセットアップにかなり苦労するものが多いように思いますが、TensorFlowのセットアップが比較的容易です。

ほぼ公式ドキュメントに従うことでセットアップできますが、ちょっとしたコツが必要な部分もあったのでそこも含めてまとめておきたいと思います。


## 環境
- OS: MacOS X El Capitan
- Python: 2.7
- TensorFlow: 0.6.0 (2016/2/12時点で最新)
- GPU: 利用しない


## インストール手順

TensorFlowはpipを使ったインストールが超簡単、というもっぱらの噂でしたが、実際にはpipパッケージは更新が遅れており、Tutorialを進めると不具合がでてきます。なので今回はbazelを使ってソースからビルドします。

> bazelはGoogleが提供しているビルドツールです。

まずビルドに必要になるbazelとswigをhomebrewでインストールします。

```Terminal
$ brew install bazel swig
```

もし手元の環境にpipとvirtualenvがインストールされていなければ、インストールしておきます。

```Terminal
$ sudo easy_install pip
$ sudo pip install --upgrade virtualenv
```

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

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

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

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

いくつかの依存関係をpipでインストールします。

```Terminal
(tensorflow)$ pip install six
(tensorflow)$ pip install numpy
(tensorflow)$ pip install wheel
(tensorflow)$ pip install ipython
```

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

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

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

```Terminal
(tensorflow)$ cd tensorflow/
(tensorflow)$ ./configure
```

ソースをビルドします。

```Terminal
(tensorflow)$ bazel build -c opt //tensorflow/tools/pip_package:build_pip_package
```

一旦pipパッケージ化します。

```Terminal
(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 [画像ファイル]
```

ではいくつかのチャレンジをおこなってみましょう。
まず、蒔ストーブ。
![IMG_4401.jpg](https://qiita-image-store.s3.amazonaws.com/0/26079/ef75a5b4-8ddd-0015-9b3d-194b55a6b88e.jpeg "IMG_4401.jpg")

```Terminal
(tensorflow) $ python classify_image.py --image_file IMG_4401.jpg
stove (score = 0.99893)
fire screen, fireguard (score = 0.00040)
space heater (score = 0.00016)
rotisserie (score = 0.00003)
table lamp (score = 0.00002)

(tensorflow) $
```

99%でストーブである、ということでバッチリ正解です。

次にウィスキーの白州を。
![IMG_4403.jpg](https://qiita-image-store.s3.amazonaws.com/0/26079/73e12514-7a93-16f0-ef41-4d8ac0cecf68.jpeg "IMG_4403.jpg")

```Terminal
(tensorflow) $ python classify_image.py --image_file IMG_4403.jpg
beer bottle (score = 0.51731)
wine bottle (score = 0.44079)
red wine (score = 0.01136)
pop bottle, soda bottle (score = 0.00297)
corkscrew, bottle screw (score = 0.00082)

(tensorflow) $
```

結果は51%でビールのボトルとのこと。惜しい！が、ちゃんと信頼度51%としているところが謙虚です。

最後にテラスで犬を。
![IMG_4406.JPG](https://qiita-image-store.s3.amazonaws.com/0/26079/5e4eefa7-ce08-a29d-798e-d04e1feb2d5b.jpeg "IMG_4406.JPG")

```Terminal
(tensorflow) $ python classify_image.py --image_file IMG_4406.jpg
golden retriever (score = 0.23980)
Irish setter, red setter (score = 0.12932)
cocker spaniel, English cocker spaniel, cocker (score = 0.11191)
rocking chair, rocker (score = 0.03784)
folding chair (score = 0.03034)

(tensorflow) $ 
```

ゴールデンレトリバーではないですが、確かに人間がみてもダックスとゴールデンレトリバーは似ている。しかも椅子まで認識してくれており、その中で中心となる被写体が犬だとわかっているところがすごい。


## まとめ

TensorFlowはGPUが搭載されていないマシンでも動作し、かつセットアップも難しくありません。それでいてImageNetのような学習データを利用して最先端の画像認識システムを手元で構築できます。

他にもChainerなどいくつかのフレームワークがありますが、Googleが提供しているということもあり、2016/2/12現在、最も注目のフレームワークの一つだと思います。

[Google Cloud Vision API](https://cloud.google.com/vision/)はおそらくこの仕組みをコアに利用していると思うので、APIベースで画像認識機能を試してみたい人はこちらの限定プレビュープログラムにサインアップしてみるのもナイスアイデアでしょう。



## 参考サイト
- 公式ドキュメントのソースからインストールする方法 - [TensorFlow - Installing from sources](https://www.tensorflow.org/versions/v0.6.0/get_started/os_setup.html#source)
- もしprotobufのバージョンでエラーがでたら - [MacでTensorFlowのTypeError: __init__() got an unexpected keyword argument 'syntax'を解決する](http://qiita.com/light14/items/31ee6ff5f7823bab917f)