TensorFlow - MNIST For ML Beginners

先月Googleが機械学習ライブラリであるTensorFlowを公開しました。Amazonも同様に公開していますが、書店にも機械学習の書籍がずらりと並ぶなど、今最も注目を集めている分野の１つです。機械学習はCGでも利用が研究されており、ロコモーションやフェイシャルアニメーションなどに活用したSiggraphの論文もよく見られます。ゲームへの活用事例はこれからとはいえ、マーケティングなども含めた幅広い利用も期待でき、TensorFlowがディファクトスタンダードがならずとも、今の機械学習の活用の流れにはとても興味深いものがあります。

#TensorFlowのインストール手順
TensorFlowは公式にはUbuntu/LinuxとMac OS Xをサポートしています。WindowsでもDockerで利用している人もいるようですが、今回はOS Xを使用します。Ubuntu/LinuxではGPUもサポートされていますが、OS XはCPUのみとなります。

TensorFlowはPythonとC++のAPIが提供されていますが、ここではPythonを使用します。Pythonは標準で使用することができ、OS X EI Captian(V10.11.2)ではPython 2.7.10になっています。（余談ですが、Windows10もぜひPythonが標準で搭載されて欲しかったですね。）

```lang:
$ python -V
Python 2.7.10
```

TensorFlowのインストールにはpipを使用します。OS X EI Captianでは、tensolrflowのインストールでsixのアンインストールが失敗することがあるようです。その場合は、--ignore-installed six のオプションを追加してみてください。

```lang:
$ sudo easy_install pip
$ sudo easy_install --upgrade six
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.6.0-py2-none-any.whl
```
TensorFlowは仮想的なPython環境を構築するvirtualenvを使用したセットアップを推奨しています。

```lang:
$ sudo pip install --upgrade virtualenv
$ virtualenv --system-site-packages ~/tensorflow
$ source ~/tensorflow/bin/activate
```

インストールが済んだら、下記のコードを実行してみます。「Hello, TensorFlow!」と42という数字が出力されれば、問題なくTensorFlowのインストールは完了しています。

```lang:
$ python
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
```

# MNIST
公式に公開されているチュートリアルは現在11個あり、その中の「MNIST For ML Beginners」は画像から文字を認識するビギナー向けのチュートリアルで、機械学習の分野ではHello World的な位置づけのようです。

実行に必要となるサンプルデータはYann LeCun氏のウェブサイトからダウンロードすることができ、このデータをローカルに保存するためのPythonのコードも下記サイトから取得することができます。
https://tensorflow.googlesource.com/tensorflow/+/master/tensorflow/examples/tutorials/mnist/input_data.py

このコードをインポートし、下記のようにデータの読み込みを行います。ダウンロードしたデータはトレーニング用の60000個のデータポイントとテスト用の10000用のデータポイントで構成されています。

```lang:py
import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
```
次に入力画像用のプレースホルダーを用意します。各画像は28x28=784ピクセルで構成されています。Noneを指定しているのは枚数の制限を行いわないためですが、前述したように60000個のトレーニング用のデータポイントを読み込みますので、[60000, 784]を格納することになります。つまり、1番目の次元は画像のインデックス、2番目の次元はピクセルのインデックスになります。なお、読み込まれたデータにはデータポイントと同数のラベルがあります。これは画像が0から9までのどの数字かを示します。つまりラベルは[60000, 10]の配列となります。

```lang:py
x = tf.placeholder("float", [None, 784])
```

## ソフトマックス回帰

このサンプルではソフトマックス回帰が使用されています。例えば、ある画像をみて80％の確率で9、5％の確率で8、それ以外の確率はわずか、といったように確率を与えます。ソフトマックス回帰は2つのステップが存在し、入力のあった特定のクラスに含まれる証拠を足し合わせ、この証拠を確率に変換します。この証拠を合計するために、各ピクセルごとに重みを持たせます。この重みは正と負を持っています。また、入力にかかわらず、確率を高くするためのバイアスを設定できるようにしています。このモデルの重みとバイアスの変数を下記に用意します。これらの変数は計算に使用されるとともに、変更することもできます。重みはピクセルごとに持っているので2次元で表現されています。初期値はゼロです。

```lang:py
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
```

ソフトマックス回帰のモデルは下記のようになります。

```lang:py
y = tf.nn.softmax(tf.matmul(x,W) + b)
```

## トレーニング
次にモデルのトレーニングを行います。このトレーニングには悪いモデル定義し、最小限に抑えるようにします。ここで使用されるのはクロスエントロピーです。チュートリアルではギャンブルでも使用されているというコスト関数ですが、まず、最初に正解を入力するための新しいプレースホルダーを用意します。

```lang:py
y_ = tf.placeholder("float", [None,10])
```

コスト関数の実装は下記のとおりです。クロスエントロピーの定義をそのまま実装しているので、とくに複雑なところはないかと思います。

```lang:py
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
```

最適化手法と最小化したい値を設定します。ここでは勾配降下法アルゴリズムとステップサイズに0.01を指定しています。

```lang:py
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
```
ここで、トレーニングするためのモデルを行いますが、セクションで実行が行われています。セクションについては、このチュートリアルには説明がなかったので、どこかで見かけ次第補足したいと思います。

```lang:py
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
```

最後にトレーニングを1000回実行します。ここでxとy_に値が入ります。

```lang:py
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
```

## モデルの評価

最後にモデルの評価を行います。実際に実行しているのは最後の3行目です。結果として、91％前後の値が得られるかと思います。

```lang:py
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
```

# 所感
機械学習を効率よく利用していくには、機械学習に必要な基礎を身につけておかないと理解がはかどらない印象でした。TensorFlowやTheanoなどを触る前に、基本部分を理解しておくほうが効率的かと思います。

TensorFlowはパフォーマンスや実装のしやすさなどで否定的な声もありますが、今回の公開を機にユーザーが一気に広がる期待感があります。以前は敷居が高い機械学習でしたが、このように利用しやすくなったことは歓迎すべきことと思います。また、ゲームでの利用では、AIはもちろんですが、好みに合わせた他のユーザークリエティブコンテンツを提案するなどのサービスを提供することもできるかもしれません。