話題のTensorFlowをTheanoと比べてみる（個人的メモ）

一晩で界隈の話題をかっさらっていった [TensorFlow](http://tensorflow.org/) ですが、[Theano](http://deeplearning.net/software/theano/index.html) などとの違いってなんだろう？というのがよく分からなかったので、~~（どこかで誰かが書いていそうだなと思いつつ）~~自分用にまとめてみました。
おそらくTheanoを恒常的に使われている方々にとっては不要なメモかと思いますが、Theano自体ほとんど触ってないので勉強を兼ねて…
（まずは基本的な演算からまとめていますが、順次追記していきます）

あくまで個人的メモですので、誤り・不正確な記述等々が含まれることご容赦ください。

なおこのメモの観点としては大きく以下の3点です。

* 依存ライブラリなど
* 書き方まわり
* その他気になった点

# 依存ライブラリなど

2015/11/11時点の情報です。
最低限必要なものを記載しているつもりですが、抜け漏れ等あるかもしれません。

* Theano(http://deeplearning.net/software/theano/install.html#install)
    * Python 2.6+ or 3.3+
    * NumPy 1.7.1+
    * SciPy 0.11+
    * six 1.9.0+
    * GPU利用時
        * NVIDIA CUDA drivers and SDK
        * libgpuarray
    * ソースからビルドする場合？
        * g++
        * python-dev
        * BLAS
* TensorFlow(http://tensorflow.org/get_started/os_setup.md)
    * Python 2.7（！）
    * Numpy 1.9.2+
    * six 1.10.0+
    * GPU利用時
        * Cuda Toolkit 7.0
        * CUDNN 6.5 V2
    * ソースからビルドする場合
        * Bazel
        * swig
        * python-dev

こうしてみると、ソースビルドしなければどちらも大きな差はなさそうです。

# 書き方まわり

Theano/TensorFlowとも公式のチュートリアル等から多数引用しています。

* Theano
    * http://deeplearning.net/software/theano/tutorial/index.html#tutorial
* TensorFlow
    * http://tensorflow.org/get_started/basic_usage.md
    * http://tensorflow.org/tutorials

## 四則演算

加算だけ取り上げます。

```py:Theano
import theano.tensor as T
from theano import function
x = T.dscalar('x')
y = T.dscalar('y')
z = x + y
f = function([x, y], z)
f(2.3, 3.1)

# output: 
# array(5.4)
```

```py:TensorFlow（constantで）
import tensorflow as tf
x = tf.constant(2.3)
y = tf.constant(3.1)
z = x + y

with tf.Session() as sess:
    result = sess.run(z)

# output: 
# result = 5.3999996
```

```py:TensorFlow（Variableで）
import tensorflow as tf
x = tf.Variable(2.3)
y = tf.Variable(3.1)
z = tf.add(x, y)
init_op=tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init_op)
    result = sess.run(z)

# output: 
# result = 5.3999996
```

```py:TensorFlow（placeholderで）
import tensorflow as tf
x = tf.placeholder(tf.float32, shape=(1,))
y = tf.placeholder(tf.float32, shape=(1,))
z = x + y

with tf.Session() as sess:
    result = sess.run(z, feed_dict={x: (2.3,), y: (3.1,)})

# output: 
# result = array([ 5.39999962], dtype=float32)
```

http://tensorflow.org/api_docs/python/io_ops.md#placeholder のサンプルコードだと、`tf.placeholder(float, shape=(1024, 1024))`となっていましたが、`tf.float32`にしないとエラーになりました。
型の渡し方とかが何かおかしかったのでしょうか…

## 基本的な演算（累乗）

```py:Theano
import theano.tensor as T
from theano import function
x = T.dscalar('x')
y = T.dscalar('y')
z = (x + y)**3
f = function([x, y], z)
f(2.3, 8.0)

# output: 
# array(1092.7270000000003)
```

```py:TensorFlow
import tensorflow as tf
x = tf.placeholder(tf.float32, shape=(1, ))
y = tf.placeholder(tf.float32, shape=(1, ))
z = tf.pow((x + y), 3)

with tf.Session() as sess:
    result = sess.run(z, feed_dict={x: (2.3, ), y: (8.0, )})

# output: 
# result = array([ 1092.72705078], dtype=float32)
```

TensorFlowは、一部の演算が http://www.tensorflow.org/api_docs/python/math_ops.md に記載の関数を介して行うようになっているようです。

## 微分

```py:Theano
import theano.tensor as T
from theano import function
x = T.dscalar('x')
z = x**2
gz = T.grad(z, x)
f = function([x], gz)
f(12.2)

# output: 
# array(24.4)
```

```py:TensorFlow
import tensorflow as tf
x = tf.placeholder(tf.float32, shape=(1, ))
z = tf.pow(x, 2)
gz = tf.gradients(z, x)

with tf.Session() as sess:
    result = sess.run(gz, feed_dict={x: (12.2, )})

# output: 
# result = [array([ 24.39999962], dtype=float32)]
```

特に意味はありませんが、あえて http://www.tensorflow.org/api_docs/python/train.md#AUTOGENERATED-gradient-computation に書かれている低レベル関数を使ってみました。
実利用の際は勾配自体が欲しいことは（最適化手法自体を実装する場合などを除き）少ないと思われますので、http://www.tensorflow.org/api_docs/python/train.md#optimizers の各種Optimizerを使うことになるのでしょうか。

## 以下順次追記します。たぶん。

# その他

## 計算モデル

（まだあまり把握してません…）

# 所感

* あまりTheanoを触っていない人間の感覚として、Theanoは`dscalar`や`dmatrix`など型がいろいろあって面倒そうな印象
    * その辺りはTensorFlowの方が使いやすい？
* まだちゃんと試してませんが、TensorFlowは以下の点でも優位でしょうか
    * 実装済みのOptimizerが使える
    * 可視化ツールが充実している？

あとチュートリアルが充実しているのは大変ありがたいのですが、サンプルコードがところどころ誤っているのかなんなのか上手く動かないケースがあるので、ドキュメントも信用し過ぎないように注意したほうが良いかもしれません。
（おそらくすぐ修正されるでしょうけど）