Python で初めての単回帰分析

単回帰分析の意味は調べればいくらでも出てきますが、自分で実際にプログラムを書いてみることで、理解が深まればいいかなと思い、Python を使って試してみたいと思っています。

一応、単回帰分析に対する説明としては、以下のような例があります。
1. 1つの目的変数(y)を1つの説明変数(x)で予測するもの。
2. それらの関係性を y = ax ＋ b という一次方程式の形であらわす。
※ a は傾き、b は切片

テスト環境は、（いつインストールしたかも覚えていない） Jupyter Notebook を使います。
使用したバージョンは以下です。

```
The version of the notebook server is: 6.0.0
Python 3.7.3 (default, Mar 27 2019, 22:11:17) 
[GCC 7.3.0]
```

#### pandas
pandas（パンダス、パンダズまたはパンダ）はデータを変換したり解析したりするためのライブラリ。
これを使って、データを読み込んでいきます。
使用したバージョンは以下です。

```python
import pandas as pd
print(pd.__version__)
# 0.24.2
```

#### データ読み込み
今回は、48名分の身長(x)と体重(y)のデータ(sample.csv)を使用してみます。

```bash:sample.csv
x,y
152,57
173,78
172,83
178,58
166,63
175,66
158,66
163,74
157,64
165,68
176,68
165,60
147,63
153,63
146,47
156,49
145,59
181,66
160,74
140,55
152,55
165,56
170,65
159,51
151,52
167,51
177,82
155,63
159,45
170,66
154,56
163,60
161,70
165,70
150,57
158,53
163,67
186,69
168,68
170,74
155,60
159,49
170,87
163,50
166,58
161,69
159,60
171,71
```

sample.csv ファイルを読み込み、最初の3行を出力してみます。
以下のように読み込めているようです。

```python
df = pd.read_csv('sample.csv')
df.head(3)
 	x 	y
0 	152 	57
1 	173 	78
2 	172 	83
```

pandas.read_csv でデータを読み込むと、DataFrame という型でデータが作成されるようです。
[pandas.read_csv](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html)
[DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/frame.html)

それぞれの列データを変数x, y に格納しておきます。

```
x = df.x
y = df.y
```

#### matplotlib
matplotlib（マットプロットリブ）は、グラフ描画ライブラリ。
使用したバージョンは以下です。

```python
import matplotlib
matplotlib.__version__
# '3.1.0'
```

#### グラフ描画

```python
import matplotlib.pyplot as plt
plt.plot(x, y)
plt.show()
```
![matplotlib1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63951/942e9945-d509-ed31-a25e-3c8ddb574d70.png)

全ての点が線でつながれたグラフが表示されました。
期待していたのは点だけが表示されているグラフでしたので、以下のように修正します。

```python
import matplotlib.pyplot as plt
plt.plot(x, y, 'o')
plt.show()
```
![matplotlib2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63951/31c373aa-4c34-789d-9eb5-87325a38ef73.png)

#### scikit-learn
scikit-learn（サイキット・ラーン）は、科学技術計算を行うためのPythonパッケージ NumPy（ナンパイまたはナムパイ）と SciPy（サイパイ）の上で構築されている機械学習用ライブラリ。
使用したバージョンは以下です。

```python
import sklearn
print(sklearn.__version__)
# 0.21.2
```
scikit-learn を使うことでお手軽に単回帰分析することが出来そうです。
[LinearRegression](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression)

#### データの学習
線形回帰モデル（LinearRegression）のインスタンスを生成し、データを学習(fit)させます。

```python
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(x, y)
# ValueError: Expected 2D array, got 1D array instead:
```

と思ったら、エラーが出てしまいました。2次元配列が必要なところ、1次元配列を与えているようです。
x, y の格納の仕方を変更して、改めて学習してみます。

```python
x = df[['x']]
y = df[['y']]
```
```python
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(x, y)
# LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
```
今度は取り込んでくれたようです。
ここの部分は、元の x と y のままでも以下のように定義すれば動いてくれるはずです。

```python
# values で numpy.ndarray 型に変換し、np.reshape(-1, 1)でn行1列に変換する
model.fit(x.values.reshape(-1,1), y.values.reshape(-1,1))
```

#### データの予測
それでは予測(predict)させてみます。

```python
plt.plot(x, y, 'o')
plt.plot(x, model.predict(x), linestyle="solid")
plt.show()
```

![matplotlib3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63951/8aaa8c93-6b79-6c50-e0ce-926000314c14.png)
説明変数(x) から、目的変数(y) を予測した結果、右肩上がり（身長が増えるほど、体重が増える）の線が引かれました。

この直線の"傾き"と"切片"については、それぞれ coef_ と intercept_ 属性が保持しているようですので、それらを出力してみると、直線の方程式を得ることができます。

```python
print('y = %.2fx + %.2f' % (model.coef_ , model.intercept_))
# y = 0.52x + -20.94
```

以上のことから、a（傾き）と b（切片）が分かることで、x（身長）から y（体重）を予測することができる、即ち"単回帰分析"が実現出来たということになります。