機械学習レシピ#6 Tensorflow for Poetsでイメージ分類器

https://www.youtube.com/watch?v=cSKfRcEDGUs&list=PLOU2XLYxmsIIuiBfYad6rFYQU_jL2ryal&index=2

画像分類器にどう学習させるかについて、TensorFlow for Poets使用して作業する。
TensorFlow for Poetsはハイレベルのコードで分類器に学習させるために基本的に２つのスクリプトを実行すればよいだけであり、そしてパワフルな分類器である。

TensorFlow for Poetsで画像分類器に学習させるためにすることは１つ、学習データを供給すればよいだけである。

**今回のゴールは5種の花を区別する分類器を作ること。**

##学習データの準備
既に花の学習画像データが用意されているのでダウンロードする。

```
% cd $HOME
% mkdir tf_files
% cd tf_files
% curl -O http://download.tensorflow.org/example_images/flower_photos.tgz
% tar xzf flower_photos.tgz
#時間を短縮するために、今回はカテゴリを間引く。
$ rm -rf dandelion sunflowers tulips
```
TensorFlowがセットアップされてたDockerを起動

```
docker run -it -v $HOME/tf_files:/tf_files  gcr.io/tensorflow/tensorflow:latest-devel
```

## 分類器を学習させる
分類器を学習させるためにTensorFlowを使用する。
TensorFlowは械学習ライブラリで、特に深層学習の作業に役立つ。

深層学習は特に画像分類器のような領域で大きな成果につながった。
画像に関して手作業で有用な特徴を抽出するコードを書くのは難しい。
これを避けるために深層学習を使う。画像を扱うときに手作業で特徴を抽出する必要がないという大きな利点がある。（画像の特徴の生ピクセルを使え、あとは分類器が行う）

学習データの様子の違いを見るためにIrisのデータセットと画像のディレクトリを比べてみる。

Irisで各欄(列)は花を描く特徴。例えば定規を測るなどの手作業でこういう特徴がでてきた。

| Sepal Length | Sepal Width | Petal Length | Petal Width | Species |
|:-:|:-:|:-:|:-:|:-:|
| 5.1  | 3.5  | 1.4  | 0.2  |  I. setosa |

一方、TensorFlow for Poetsでの学習データは単にラベル付きの名前。

| File Name | Label |
|:-:|:-:|
| rose1.png  | Rose  |
| tulipgarden.jpg  | Tulip  |

分類機はただの関数。f(x) = y
ここでxは画像のピクセルの２次元配列、yはバラのようなラベル。

深層学習では分類器のことをニューラルネットワークと呼ぶ。
ハイレベルではそれはただの分類器。
前回の最近接と似ているが、違いはもっと複雑な関数を覚えられること。

TensorFlow for Poetsは人の代わりに背後でニューラルネットワークを設定し学習させる仕事をする。

Josh Gordenの好きなTensorFlowプログラムの書き方はTF Learnを使うこと。
TF LearnはTensorFlow上部のハイレベルの機械学習ライブラリ。
構文はscikit-learnに似ている。

トレーニングコードを取得する。(以下のコマンドは先ほど起動したコンテナ上で実行)

```
# cd /tensorflow
# git pull
```

Interceptionを使用してリトレーニング

```
python tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=/tf_files/bottlenecks \
--how_many_training_steps 500 \
--model_dir=/tf_files/inception \
--output_graph=/tf_files/retrained_graph.pb \
--output_labels=/tf_files/retrained_labels.txt \
--image_dir /tf_files/flower_photos
・・・
Final test accuracy = 96.4%
Converted 2 variables to const ops.
```

裏でTensorFlow for Poetsは分類器を一から学習させてるいるのではなく、Inceptionという既存の分類器をベースに学習を始めている。
InceptionはGoogleの最良の画像分類器の一つ。1000の異なるカテゴリ、1200万の画像を学習している。
TensorFlow for Poetsでは、まずInceptionで始め、リトレーニング(Transfer Learningとして知られている)という技術を使い、Inceptionが前に学習したいくつかを再利用し、はるかに少ない学習データで新しい高精度の分類器を作れる。

#学習したモデルを使用して予測する

```
import tensorflow as tf

# change this as you see fit
image_path = sys.argv[1]

# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()

# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line 
                   in tf.gfile.GFile("/tf_files/retrained_labels.txt")]

# Unpersists graph from file
with tf.gfile.FastGFile("/tf_files/retrained_graph.pb", 'rb') as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
    _ = tf.import_graph_def(graph_def, name='')

with tf.Session() as sess:
    # Feed the image_data as input to the graph and get first prediction
    softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
    
    predictions = sess.run(softmax_tensor, \
             {'DecodeJpeg/contents:0': image_data})
    
    # Sort to show labels of first prediction in order of confidence
    top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
    
    for node_id in top_k:
        human_string = label_lines[node_id]
        score = predictions[0][node_id]
        print('%s (score = %.5f)' % (human_string, score))
```

wikipediaからバラの画像をダウンロードし、分類器を使って予測。

```
$ curl -L https://goo.gl/tx3dqg > $HOME/tf_files/label_image.py
$ docker run -it -v $HOME/tf_files:/tf_files  gcr.io/tensorflow/tensorflow:latest-devel 
```

```
# python /tf_files/label_image.py /tf_files/flower_photos/daisy/21652746_cc379e0eea_m.jpg
# python /tf_files/label_image.py /tf_files/flower_photos/roses/2414954629_3708a1a04d.jpg 
```

結果は以下のような感じになる

```
daisy (score = 0.99071)
sunflowers (score = 0.00595)
dandelion (score = 0.00252)
roses (score = 0.00049)
tulips (score = 0.00032)
```

分類器は学習データについて知ってるだけ。
良い画像分類器にするのに肝心な点は多様性と量。