TensorFlowを試す（線形回帰）


機械学習の勉強を始めてみようと、とりあえずメジャーな[TensorFlow](https://www.tensorflow.org/)から試してみることに。

まずはイントロダクションのコードを読んでいきます。
<https://www.tensorflow.org/versions/r0.7/get_started/index.html#introduction>

## 環境

- ArchLinux
- Python 3.5.1
- TensorFlow 0.7
- on VMware

## インストール

AURにパッケージがあるのでそこからインストールします。

```bash
$ pacaur -S python-tensorflow
```

途中2回くらい入力を求められますが、そのままEnterで続行。GPUは使わない（使えない）

## コード

Python3仕様に微修正。あと、最後の`print`の位置はおかしいじゃないかと。

```python:intro.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 range(201):
    if step % 20 == 0:
        print((step, sess.run(W), sess.run(b)))
    sess.run(train)

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

## コード内容

`y = 0.1x + 0.3`上のランダムな100個の`(x, y)`の組み合わせを機械学習に渡して、一次関数`y = Wx + b`に線形回帰させます。

```python:intro.py#L4-L6
# 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
```

まずNumPyでランダムに100個の点を生成しています。

```python:intro.py#L8-L13
# 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
```

回帰先の変数`w`と`b`を用意します。
変数は`tf.Variable`で作ります。コンストラクタは以下

```python
# Create a variable.
w = tf.Variable(<initial-value>, name=<optional-name>)
```

`W`は`-1.0`から`1.0`の間のランダムな値から始めます。
`b`は`0`から始めます。
TensorFlowにおける値は[テンソル](https://ja.wikipedia.org/wiki/%E3%83%86%E3%83%B3%E3%82%BD%E3%83%AB)です。`tf.random_uniform`や`tf.zeros`の第1引数はテンソルのシェイプを渡します。今回の`W`や`b`はスカラー値なので`[1]`になります。
初期値は他に以下が利用できます。

```python
# Creates a tensor with all elements set to 1.
tf.ones(shape, dtype=tf.float32, name=None)

# Creates a constant tensor.
tf.constant(value, dtype=None, shape=None, name='Const')
```

```python:intro.py#L15-L18
# Minimize the mean squared errors.
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
```

回帰方法を指定します。最小二乗法になります。
誤差`loss`を残差の二乗の平均と定義し、[再急降下法](https://ja.wikipedia.org/wiki/%E6%9C%80%E6%80%A5%E9%99%8D%E4%B8%8B%E6%B3%95)で誤差が最小になるように最適化していきます。
最適化方法は他に[確率的勾配降下法](https://ja.wikipedia.org/wiki/%E7%A2%BA%E7%8E%87%E7%9A%84%E5%8B%BE%E9%85%8D%E9%99%8D%E4%B8%8B%E6%B3%95)の各アルゴリズムを用いる`tf.train.AdagradOptimizer`や`tf.train.MomentumOptimizer`などなどがあります。

```python:intro.py#L20-L25
# Before starting, initialize the variables.  We will 'run' this first.
init = tf.initialize_all_variables()

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

初期化処理。
以降、ステップを進めるには`sess.run(train)`を実行、変数の値を取り出すのは`sess.run(W)`や`sess.run(b)`で行います。


## 実行結果

出力は左から`(ステップ数, W, b)`となります。
`W`が`0.1`に、`b`が`0.3`に収束していくのがわかります。

```bash
$ python intro.py
(0, array([-0.93135095], dtype=float32), array([ 0.], dtype=float32))
(20, array([-0.08106428], dtype=float32), array([ 0.4020806], dtype=float32))
(40, array([ 0.04989112], dtype=float32), array([ 0.32825044], dtype=float32))
(60, array([ 0.08613255], dtype=float32), array([ 0.3078182], dtype=float32))
(80, array([ 0.09616224], dtype=float32), array([ 0.30216366], dtype=float32))
(100, array([ 0.09893791], dtype=float32), array([ 0.3005988], dtype=float32))
(120, array([ 0.09970608], dtype=float32), array([ 0.30016571], dtype=float32))
(140, array([ 0.09991866], dtype=float32), array([ 0.30004588], dtype=float32))
(160, array([ 0.0999775], dtype=float32), array([ 0.30001271], dtype=float32))
(180, array([ 0.09999377], dtype=float32), array([ 0.30000353], dtype=float32))
(200, array([ 0.09999827], dtype=float32), array([ 0.300001], dtype=float32))
```

## Next

今回試したのが回帰分析だったので、次はクラスタ分析を試してみたい。