scikit-learn、Spark.ml、TensorFlow で線形回帰〜（４）TensorFlow

TensorFlow はニューラルネットの構築フレームワークというイメージが強いですが、[tf.contrib.learn](https://www.tensorflow.org/api_docs/python/tf/contrib/learn)の下に KMeansClustering や SVMなど、一般的な機械学習ライブラリも入っており、[LinearRegression](https://www.tensorflow.org/api_docs/python/tf/contrib/learn/LinearRegressor) のライブラリも存在します。
Tutorial にも２つ記事があります。

- [Large-scale Linear Models with TensorFlow](https://www.tensorflow.org/tutorials/linear)
- [TensorFlow Linear Model Tutorial](https://www.tensorflow.org/tutorials/wide)

基本的な使い方は以下に書かれているので、これに沿ってやってみましょう。

- [Getting Started With TensorFlow](https://www.tensorflow.org/get_started/get_started)

# 4.1 学習データの準備
先のページの最後の部分にあるbasic usageのコードからコメントを入れ替えると以下になります。
入力データをファイルから読み込んで入れ替えれば良さそうです。

```
import tensorflow as tf
import numpy as np

# xは一次元
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]

# モデル作成
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)

# 学習データ
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4,
                                              num_epochs=1000)
# 学習
estimator.fit(input_fn=input_fn, steps=1000)

# 評価
print(estimator.evaluate(input_fn=input_fn))
```

input_fn で tf.contrib.learn.io.numpy_input_fn を使っていますが、input_fn の作り方が [Building Input Functions with tf.contrib.learn](https://www.tensorflow.org/get_started/input_fn) に書かれているので、これを参考に作ってみましょう。

```python:tfLR.py
import tensorflow as tf
import numpy as np

# scikit-learn と同じ
import csv
def readArrayWithCSV(dataFile):
    x = []
    y = []
    f = open(dataFile, 'r')
    reader = csv.reader(f)
    for row in reader:
        x.append([float(row[0])])  # リストにする
        y.append(float(row[1]))
    return x,y

# read data                                                                          
dataFile = 'sampleLR.csv'
x0,y0 = readArrayWithCSV(dataFile)

# input_fn
def input_data():
    # カラム名をキーとし、N次元の学習データを収めた tf.constantを値とする辞書を作成
    feature_cols = {'x': tf.constant(x0)}
    # ラベルの値を tf.contant に設定
    labels = tf.constant(y0)
    # feature_cols と labels を返す
    return feature_cols, labels
```

# 4.2 モデルの作成
元ソースとほぼ同じです。
結果の a1, a2 ... 及び b は、get_variable_value() で取得できます。

```python:tfLR.py
# define features                                                                    
features = [tf.contrib.layers.real_valued_column('x', dimension=1)]

# build model                                                                        
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)

# training                                                                           
steps = 1000
estimator.fit(input_fn=input_data, steps=steps)

# model parameters
a = estimator.get_variable_value('linear/x/weight')
b = estimator.get_variable_value('linear/bias_weight')
```

# 4.3 モデルを用いた予測
モデルの予測には predict_scores() または predict() を使います。リターン値は predict値の generator になるので、list() でリストとして取得しておきます。

```python:tfLR.py
# prediction                                                                         
def predict_data():
    feature_cols = {'x': tf.constant(x0)}
    labels = tf.zeros(len(y0))
    return feature_cols, labels

p0 = list(estimator.predict_scores(input_fn=predict_data))

# output                                                                             
x = np.array(x0)
y = np.array(y0)
p = np.array(p0)

from plotLR import plotLR
title = "predLR_with_tensorflow"
plotLR(title, x, y, p, 0.4, 0.8, a[0][0], b[0], steps)
```

plotLR は scikit-learn編参照。
steps=1000 だと、scikit-learn、spark.ml と同じ値でしたが、100だとちょっとずれた値になりました。 
![predLR_with_tensorflow_1000.png](https://qiita-image-store.s3.amazonaws.com/0/175988/7c1d83f9-8eb0-bbdc-2e4b-9a9e997e9f1f.png)
![predLR_with_tensorflow_100.png](https://qiita-image-store.s3.amazonaws.com/0/175988/a03de5b7-91da-fb80-5700-ac1d31833396.png)