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

# 2. scikit-learn: LinearRegression
機械学習のライブラリの使用方法は、

1. 学習データを準備する
2. 学習モデルをパラメータを決めて作成する
3. 学習モデルに学習データを与えて学習させる
4. 学習させたモデルを評価する、または、予測を行う

というプロセスになります。
scikit-learn の線形回帰は [LinearRegression](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression) を使います。コードは非常に簡単です。

```python:skLR.py
import numpy as np
from sklearn import linear_model

# 学習データの読み込み
（略）

# モデル作成
model = linear_model.LinearRegression()

# 学習（x = 独立変数・説明変数、y = 従属変数・目的変数）
model.fit(x, y)

# 学習したモデルを使って予測
p = model.predict(x)
```

## 2.1 学習データの準備
[線形回帰(wikipedia)](https://ja.wikipedia.org/wiki/線形回帰) は、複数の x (独立変数・説明変数）を扱えるので、linear_model は ([x1, x2...], y) と、x が配列のデータを学習データとします。
例えば、医療費を推定するのに、年齢、性別、職業、BMI、喫煙... といったデータを独立変数とし、y=医療費、[x1=年齢、x2=性別、x3=職業...] というデータで線形回帰を行えます。
今回は、独立変数が一つなので、([x], y) というデータの組みを与えます。

```python:skLR.py
import numpy as np
from sklearn import linear_model

# csvファイルからリストに読み込む                                                                         
import csv
def readArrayWithCSV(dataFile):
    x = []
    y = []
    f = open(dataFile, 'r')
    reader = csv.reader(f) # csvデータは '1.0, 2.0' という形式
    for row in reader:
	x.append([float(row[0])])  # x はリストにする
	y.append(float(row[1]))
    # x=[[1.0], [1.1] ...], y=[2.0, 2.1 ...] の形式
    return x,y

# 学習データの準備                                                                          
dataFile = "sampleLR.csv"
x0,y0 = readArrayWithCSV(dataFile)
# LinearRegression の学習データは numpy.arrayなので変換する
x = np.array(x0)
y = np.array(y0)
```

## 2.2 モデルの作成
LinearRegression に学習データを fit() させると、線形回帰は y = a1*x1 + a2*x2 + ... b の a1, a2 ... と b を算出します。これらは

- model.coef_ = a1, a2 ... の値
- model.intercept_ = b の値

で取得できます。

```python:skLR.py
# モデルの作成                                                                       
model = linear_model.LinearRegression()

# 学習                                                                               
model.fit(x, y)

# model parameters                                                                   
a = model.coef_[0]
b = model.intercept_
```

## 2.3 モデルを用いた予測
学習させたモデルに対して predict(x) を行うと、予測値=p を出力します。学習データの x の予測値と理論値のグラフを作って比較してみました。

```python:plotLR.py
import numpy as np
import matplotlib.pyplot as plt

def plotLR(title, x, y, p, at, bt, ap, bp, steps=0):
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    # 青い点が学習データ
    ax.scatter(x, y, color='blue')
    # 赤い線が学習した線形関数
    textP = 'P:x=' + str(round(ap, 4)) + ', y=' + str(round(bp, 4))
    ax.plot(x, p, color='red', label=textP)
    # 緑の点線が学習データ生成に使った理論値
    textT = 'T:x=' + str(at) + ', y=' + str(bt)
    lx = np.array([0,10])
    ly = at * lx + bt
    ax.plot(lx, ly, color='green', linestyle='dashed', label=textT)

    ax.set_title(title)
    ax.legend(loc=2)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    if steps > 0:
        text = 'steps=' + str(steps)
        ax.text(8.5, 0.6, text)
        title = title + '_' + str(steps)
    #fig.show()                                                                      
    imageFile = title + '.png'
    fig.savefig(imageFile)
```
```python:skLR.py
# model parameters                                                                   
a = model.coef_[0]
b = model.intercept_

# 予測                                                                         
p = model.predict(x)

# 出力                                                                             
from plotLR import plotLR
title = "predLR_with_sklearn"
plotLR(title, x, y, p, 0.4, 0.8, a, b)
```
結果は以下の通り。
![predLR_with_sklearn.png](https://qiita-image-store.s3.amazonaws.com/0/175988/6a9add73-735f-15ee-211c-9d76a2450cba.png)