Tensorflow MNIST For ML Beginners

#はじめに
メモ用、各関数がなにしてるか分かる範囲で記してます。
詳しい人は間違ってるとこを指摘してもらえると助かります。

参考サイト：
[MNIST For ML Beginners](https://www.tensorflow.org/versions/0.6.0/tutorials/mnist/beginners/index.html)
[Variables: Creation, Initialization, Saving, and Loading](https://www.tensorflow.org/versions/master/how_tos/variables/index.html)
#TensorFlow
Googleが作った機械学習ライブラリです。
https://www.tensorflow.org/

#インストール
とりあえず、pyenvで環境構築します。
環境：MacOSX, Python3.5.0

```pyenv.
pyenv install 3.5.0
pyenv virtualenv 3.5.0 tf35
pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.7.1-cp35-none-any.whl
```

#MNIST For ML Beginners
MNISTは画像のデータセット(手書きの数字画像がたくさんあるやつ)です。
各画像に各数字のラベルが振られてます。

タスクとしては、手書き画像が0~9どの数字なのかあてることです(10クラス分類)。
ここでは簡単な、ソフトマックス回帰で分類します。

#The MNIST Data
```read_data.py
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
```

`input_data.read_data_sets`は
第一引数にMNISTデータの保存先("MNIST_data/")を設定。ココは任意なので好きな名前で良い。
キーワード引数の`one_hot`は、`False`にするとラベルが実数(0~9)に、`True`にすると`one_hot`(今回の場合、10クラス分類なので要素数10のベクトル,ex: 4 = [0,0,0,0,1,0,0,0,0,0])になる。

ココで、獲得できるのは、 trainデータ55k, testデータ10k。
一枚の画像は要素数784のベクトル(実際は28*28の画像)で各要素[0, 1]の範囲(色の濃さ)で表されている、各画像にone_hotでラベル(0~9)がついている。


#Softmax Regressions
ソフトマックス回帰は、シグモイド関数を多変量にしたもの


#コード
##準備
```
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

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

placeholderは型(float32)と大きさ(784)を定義して、計算する際にココに入れる形になります。

`Variable`には`zeros`で0のベクトルが作られています。
文字通りvariableなので、中身は更新する事に変わっていきます。
10個のクラスに対してのバイアス(b)、重み(W)になります。

`softmax`は、ソフトマックス関数を行ってくれる関数です。
`matmul`はおそらく、matrix multipleなので行列の掛け算してます。

##training
```
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) 

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict = {x: batch_xs, y_: ys})
```
最初の行では、`placeholder`でラベルを入れる場所を作ります。
ココに入るのは正解データです。
`cross_entropy`は学習時に最小化したい関数になります。
`GradientDescentOptimizer`(最急降下法)は与えられた関数の最小値を探索するアルゴリズムです。引数の`0.01`は更新するときの重みみたいなものです。

ここまでで、変数の宣言や式の組み立てができました。
次に、学習をしていきます。

`initialize_all_variables`で今まで宣言した変数等をどっかのクラスかなにかにのせていくのかな。
次に、`Session`でクラス定義、で`sess.run(init)`でさっきの`init`をこん中に入れて、準備完了。

あとはfor文で学習させていくだけ。
ここでは、100個のデータをランダムに毎回渡しています。
こういうのをstochastic gradient descent(確率的勾配降下法)というそうです。
メモリ効率が良さそうな感じしますね。

##モデルの保存
いちいち学習し直すのもめんどくさいのでとりあえず、モデル保存したいと思います。

```
init = ~~~~
saver = tf.train.Saver()

sess = ~~~~~
for i in range ~~~~~~:
    ~~~~~~~
    ~~~~~~~
saver.save(sess, "tmp/model.ckpt")
```
とりあえず、これで任意のファイルに保存できます

##モデル評価
```
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}))
```
correct_predictionは評価する関数の定義です。
argmax(y, 1)とargmax(y_, 1)つまり、予測と正解が一緒であればTrue, 間違ってればFalseを出力する関数です。

`accuracy`では、`correct_prediction`の出力のベクトル(True or False)を`cast`で`float`に直してから、`mean`で平均をとる関数の宣言をしています

最後に、`sess.run`でテストデータ全体で走らせています。


##出力
```
0.9082
```
とりあえず、サイトに載ってる数値通りの値がでました。

#まとめ
今回はtensorflowを使って、softmax回帰で10クラスの分類を行った。

簡単な流れとしては、
variable, placeholderの宣言。
softmax等の学習の際に用いる関数の定義
最適化関数の定義(Gradient Descent Optimizer)
stochastic trainingをする(少しずつランダムサンプリングして学習していく)
最後に予測して答え合わせ