自分用TensorFlowメモ

今さらながら、TensorFlowの勉強をしています。
自分用にメモをしていたのですが、「しょぼくても公開したほうがイイヨ」とアドバイスを貰ったのでそうします。

書いてる内容は、全部どこかの他の記事の内容ですが、なるべくそれに自分の理解を追加して書いていきたいです(マサカリ投げてもらうため)。
間違ってる内容があれば指摘してもらえると喜びます。

以下メモをコピペ。

----------------------------------------------

TensorFlowを試す＆勉強するために読んだ記事やそこで得た知見を簡単にまとめる。
新しい知識を得るたび追記する。


## チュートリアルを動かすまでに試した手順
### 導入
pipで問題なく導入できる。
ただし、導入時にTensorFlowのバージョン、python2か3か、CPU版かGPU版か、LinuxかMax OSかを指定してインストールをする必要があり、いずれかによってpipのコマンドが変わる。
詳細は[ここ](https://www.tensorflow.org/versions/master/get_started/os_setup.html#pip-installation)  を参照。下記は実際に使ったコマンド。

```bash:
# Ubuntu/Linux 64-bit, GPU enabled:
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl
```

どこか詰まったら、大抵[公式ページのIssue](https://www.tensorflow.org/versions/master/get_started/os_setup.html#common-problems)に解決方法が乗ってる。必ず確認。
GPUを使う場合は、CUDAへのPATH、LD_LIBRALY_PATHを通しておく必要がある(他のライブラリ、例えばChainerなどで必要になるものと同様)。

```bash:
# こんな感じの内容を.bashrcとかに書いておく
$ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64"
$ export CUDA_HOME=/usr/local/cuda
```
### 動作確認
Ipythonを起動して下記のコードを１行ずつ確認。
これは[公式のイントロダクション](https://www.tensorflow.org/versions/r0.8/get_started/index.html#introduction)にあったコード。
コードを読むに、線形変換のパラメータを目的関数(二乗平均誤差)にしたがって最適化する処理っぽい。

```py:test.py
import tensorflow as tf
import numpy as np

# Create 100 phony x, y data points in NumPy, y = x * 0.1 + 0.3
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data * 0.1 + 0.3

# Try to find values for W and b that compute y_data = W * x_data + b
# (We know that W should be 0.1 and b 0.3, but Tensorflow will
# figure that out for us.)
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b

# Minimize the mean squared errors.
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# Before starting, initialize the variables.  We will 'run' this first.
init = tf.initialize_all_variables()

# Launch the graph.
sess = tf.Session()
sess.run(init)

# Fit the line.
for step in xrange(201):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(W), sess.run(b))

# Learns best fit is W: [0.1], b: [0.3]
```

TensorFlowでは、numpy形式のデータを基にしたVariableというクラスで変数を管理する。
この変数の演算で、最適化したい式を表現する(上記コードのy)。  
誤差関数はreduce_meanのようである。
二乗誤差を引数として与えて、それをlossにすると定義している。
他にも誤差関数のためのメソッドは用意されていそう。  
最適化のためのアルゴリズムもたくさん実装サれているようで、ここでは最もよく使われるGradient Descent(SGDではない？後で調べる)が使われている。
0.5は恐らくlearning rate。
これをoptimizerとして定義し、このminimizeメソッドに先ほどのlossを与えている。  
恐らく最も大事なのはsessionの概念。
TensorFlowでは事前に行いたい計算をまとめておき、それをセッションに投げることで処理を行う。
今回はtrainやinitがそれ。それぞれ、パラメータチューニングを行いたい計算、パラメータの初期化。

VariableやSessionといった概念は[ここ](http://qiita.com/tawago/items/c977c79b76c5979874e8)や[ここ](http://qiita.com/icoxfog417/items/fb5c24e35a849f8e2c5d)の記事を読んで勉強する。

### MNISTを試す
[公式のgit](https://github.com/tensorflow/tensorflow)をcloneしてその中(tensorflow/examples/tutorials/mnist)にあるチュートリアルを試す。
チュートリアルのコードを一部変更

```py:fully_connected_feed.py(一部抜粋)
# これを
#from tensorflow.examples.tutorials.mnist import input_data
#from tensorflow.examples.tutorials.mnist import mnist

# こうじゃ
import input_data
import mnist
```

どうやら、プロジェクトのルートから実行する前提のコードらしい。チュートリアルのディレクトリまで移動してから実行する場合は上のように変更が必要。  
それでは、mnistディレクトリまで移動して以下のコマンドを実行。

```bash:
$ python fully_connected_feed.py 
```

MNISTの学習が始まるはず。しばらく待つと終わって最終的な精度が表示される。
このチュートリアルはMLPを用いたもの。[CNNを用いたもの](https://www.tensorflow.org/versions/master/tutorials/mnist/pros/index.html)もある。

## TensorFlowのキホン, データ構造・メソッド
最低限知っておくべき機能やデータ構造、メソッドについて書く。
内容はほぼ公式ページのHow toなどを読んで自分が解釈した内容。
間違いに気づく度に更新する。

### VariableとPlaceholderの違い
TensorFlowで扱う変数にはVariableとPlaceholderの二つがある。  
Variableは、ニューラルネットが持っている(入力層、隠れ層の重み等)パラメータを定義・保持しておくためのデータ構造。
誤差関数を最適化するようにチューニングしたいパラメータはVariableで定義するイメージ。

Placeholderは、ニューラルネットの入力として与えるデータの形を定義しておくためのデータ構造。
ネットワークを定義するときに、どのような入力がどのような形式で来るのかをPlaceholderを使って宣言しておき、実際の訓練や動作時に対応するデータを流し込むイメージ。

### 使用するデバイスの設定
どのデバイス(どのCPU?どのGPU?)を使うかは tf.deviceッメソッドで設定する。

```bash:
# Pin a variable to CPU.
with tf.device("/cpu:0"):
  v = tf.Variable(...)

# Pin a variable to GPU.
with tf.device("/gpu:0"):
  v = tf.Variable(...)

# Pin a variable to a particular parameter server task.
with tf.device("/job:ps/task:7"):
  v = tf.Variable(...)
```

### モデルのセーブ&ロード
モデルのセーブ&ロードのためのクラスとして、tf.train.Saverというものがある。
pickleを使っても保存できるとは思うが、特に事情がない限り用意されてるものを使うのが一番だと思う。

#### モデルのセーブ
Saverを定義してsaveメソッドを呼べば良い。
引数はセッションと保存先のディレクトリ+ファイル名の文字列。

```py:example_save
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add an op to initialize the variables.
init_op = tf.initialize_all_variables()

# Add ops to save and restore all the variables.
saver = tf.train.Saver()

# Later, launch the model, initialize the variables, do some work, save the
# variables to disk.
with tf.Session() as sess:
  sess.run(init_op)
  # Do some work with the model.
  ..
  # Save the variables to disk.
  save_path = saver.save(sess, "/tmp/model.ckpt")
  print("Model saved in file: %s" % save_path)
```

モデルを保存する場合、必ず各変数に名前をつけておく。
名前は、nameプロパティで付けられる。


#### モデルのロード
Saverを定義してrestoreメソッドを呼べば良い。
引数はセッションと保存先のディレクトリ+ファイル名の文字列。

```py:example_load
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore all the variables.
saver = tf.train.Saver()

# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:
  # Restore variables from disk.
  saver.restore(sess, "/tmp/model.ckpt")
  print("Model restored.")
  # Do some work with the model
  ...
```

#### 一部のパラメータのみ保存
変数に名前を付けておくと、一部の変数のみ保存、ということが出来る。
コレを利用すると"モデルのサブセットのパラメータを保存して、別のモデルに転用する"という事ができる(?)。
Fine Tuningしたい場合は使うことになりそう。

```py:example_save_subset
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore only 'v2' using the name "my_v2"
saver = tf.train.Saver({"my_v2": v2})
# Use the saver object normally after that.
...
```


## 参考資料
* [TensorFlowの公式github](https://github.com/tensorflow/tensorflow)  
　・かなり詳しいチュートリアルがまとまってる  
　・とりあえずpullしておく
* [公式ページ(リンク先は導入のページ)](https://www.tensorflow.org/versions/master/get_started/os_setup.html)  
　・インストール方法、チュートリアルに関する情報がまとまっている  
　・かなり勉強になるのでここもマスト
* [特にプログラマーでもデータサイエンティストでもないけど、Tensorflowを1ヶ月触ったので超分かりやすく解説](http://qiita.com/tawago/items/c977c79b76c5979874e8)  
　・TensorFlowで扱うデータ構造などをまとめている  
　・入門者が最初に読むべき記事  
* [TensorFlowを算数で理解する](http://qiita.com/icoxfog417/items/fb5c24e35a849f8e2c5d)  
　・TensorFlowは独自の計算の扱い方があり、それが図でわかりやすくまとまっている  
　・TensorFlowの概念を理解するために最初に読んでおいた方が良いかもしれない  
* [ディープラーニングの有名ライブラリ5種を最短距離で試す半日コース（TensorFlow, Chainer, Caffe, DeepDream, 画風変換）](http://qiita.com/shu223/items/a4fc17eb3356a6068553)  
　・本当にサックリとMNISTのチュートリアルを動かす手順がまとまっている  
　・つまりやすい部分の補足があるのが良い