単回帰分析での機械学習入門 (Python)

<h2>はじめに</h2>
単回帰分析の理論とPythonでの実装について簡単な解説によって、説明していく。
(※あくまで個人の見解であるため、内容に不備がある可能性もございます。)
<h2>目次</h2>
1. 単回帰分析とは?
2. 説明変数に最も当てはまりの良い1次関数を見つける
3. Pythonでの実装
4. まとめ
<h2>1. 単回帰分析とは？</h2>
単回帰分析とは、1種類のデータから最も当てはまりの良い関数を見つけ、その関数に未知データを適用することで予測を行う手法である。
では、単回帰分析の「回帰」とは何を示しているだろうか。
　　＜回帰＞
　　　回帰とは、未知データからある数値を予測することを指す。
　　　(例：身長、体重)
ここで、機械学習では「回帰」という問題のほかに、「分類」という問題もある。
　　＜分類＞
　　　分類とは、未知データからあるクラスに分類すること指す。
　　　主に、0か1の分類は2値分類と呼び、複数のクラスに分類することを多クラス分類と呼ぶ。
　　（例 : 花の種類、商品を買うか買わないか）
今回は単回帰分析であるため、回帰問題である。よって、ある数値を予測することを目的とする。
<h2>2. 説明変数に最も当てはまりの良い1次関数を見つける</h2>そもそも説明変数とは、予測したい値(目的変数)を求めるためのデータのことである。
単回帰分析を行うにあたって、説明変数に最も当てはまりの良い１次関数を見つけることで、最適な予測値を導き出したい。ではどうやってその関数を見つけ出すのだろうか。
<h4>最小二乗法</h4>
　最小二乗法とは、1次関数をf(x)とした時、
$$ 
\sum^{n}_{i=1}\lbrace y_i-f(x) \rbrace^{2} 
$$
　が最小となるようなf(x)の値を求める方法である。(n : データの数, $y_i$ : 実際のデータ)
　それではどのようにして最小二乗法を行うのだろうか。
　今回求めたい関数は1次関数であるから、
$$
f(x)=ax+b
$$
　としておく。(a：傾き, b：切片)<br>
　[手順]
　① xとyの平均値を求める。
　　平均値の求め方としては、
$$ 
\bar{x}=\frac{\sum^{n}_ix_i}{N}
$$

　　である。 ( $x_i$：xのデータ, $\bar{x}$：xの平均値 , N：データの個数)
　　yの平均値も同じようにして求める。
　② xの分散を求める。
　　分散とは、データのばらつき具合を示す数値である。式は以下である。
　　$$ 
V_x=\frac{1}{N}\sum^{n}_{i=1}(x_i-\bar{x})^{2} 
$$
　③ xとyの共分散を求める。
$$
V_x {}_y = \frac{1}{N}\sum^{n}_i(x_i-\bar{x})(y_i-\bar{y})
$$
　④ 共分散をxの分散で割って、f(x)の傾きaを得る。
$$
a=\frac{V_x {}_y}{V_x}
$$
　⑤ 切片bの値を求める。
　　 $y=ax+b$より、
　　　　　$b=y-ax$
　　であるから、切片bは、xとyのデータと、傾きaの値を用いて求めることができる。<br>
　こうして得られた傾きaとbを$y=ax+b$の式に適用することで、最適な関数f(x)を求めることができる。
<h2>3. Pythonでの実装</h2>
ここまでで学習した単回帰分析を実際にPythonで実装してみる。

```python
# 今回使うライブラリの読み込み
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
```

今回は、説明変数を数学の点数、目的変数を理科の点数として予測を行なっていく。

訓練用データ↓        

|math|science|
|:-:|:-:|
|6|13	
|15|22	
|19|30	
|20|32	
|34|40	
|42|40	
|46|52	
|59|64	
|62|64	
|78|72	
|79|80	
|81|87	
|95|98	

テスト用データ↓

|math|science|
|:-:|:-:|
|5|	14|
|10|	17|
|22|	30|
|36|	44|
|48|	55|
|64|	64|
|67|	65|
|72|	78|
|77|	80|
|86|	88|
|97|	96|

```python
# データの読み込み
train_df = pd.read_csv('train_data.csv')
test_df = pd.read_csv('test_data.csv')

# 説明変数と目的変数に分ける
train_x = train_df['math']
train_x = np.array(train_x).reshape(-1, 1)
train_y = train_df['science']
test_x = test_df['math']
test_x = np.array(test_x).reshape(-1, 1)
test_y = test_df['science']

# 訓練用データの形状
print("説明変数： ", train_x.shape)
print("目的変数： ", train_y.shape)

'''
実行結果
    説明変数：  (13, 1)
    目的変数：  (13,)
'''
```

実際に予測を行なっていく。scikit-learnのLinearRegressionを使って、モデルを構築する。

```python
# モデルの構築
reg = LinearRegression()

# 学習
reg.fit(train_x, train_y)

'''
実行結果
    LinearRegression()
'''
```

reg.coef_で1次関数の傾き、reg.intercept_で1次関数の切片を出力する。

```python
print("傾き：a={}".format(reg.coef_))
print("切片：b={}".format(reg.intercept_))

'''
実行結果
    傾き：a=[0.89738222]
    切片：b=9.481915874431337
'''
```

上のコードで得られた傾きと切片の値を使って、$y=ax+b$のグラフを描画する。

```python
# グラフを描画するための関数を定義する
def simple_linear_regression(x):
    y = []
    for i in x:
        y.append(reg.coef_*i + reg.intercept_)
    fig, ax1 = plt.subplots(1,1,figsize=(10,8))
    ax2 = ax1.twinx()
    ax1.plot(x, y, color='orange')
    ax2.scatter(train_x, train_y)
    ax1.set_xlabel("score of math", fontsize=18)
    ax1.set_ylabel("score of science", fontsize=18)
    plt.show()

# グラフの描画
x = range(0, 100)
simple_linear_regression(x)
```

実行結果は以下のようになる。![reg_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966248/f7a9b2be-1d96-89b8-0f2a-8aeddc247cf7.png)
それでは、このモデルの評価を行なっていく。reg.score(x, y)とすることで、データの決定係数$R^{2}$を出力することができる。
決定係数とは、最大値が1であり、値が1に近いほどモデルが与えられたデータに当てはまっていることを示す。
式は以下のようになる。($\widehat{y_i}$：予測値)
$$
 R^2=1-\frac{\sum_{i=1}^{n}(y_i-\widehat{y_i})^2}{\sum_{i=1}^{n}(y_i-\bar{y_i})^2}
$$
実際にreg.scoreを使って出力してみる。

```python
# 訓練用データの評価
print("訓練用データに対する決定係数: {:.3f}".format(reg.score(train_x, train_y)))

# テスト用データの評価
print("テスト用データに対する決定係数: {:.3f}".format(reg.score(test_x, test_y)))

'''
実行結果
    訓練用データに対する決定係数: 0.978
    テスト用データに対する決定係数: 0.992
'''
```

どちらのデータに対しても決定係数が1に近いため、精度の高いモデルであることが分かる。
<h2>4. まとめ</h2>
ここまで、単回帰分析の理論の解説とPythonでの実装を行なってきた。単回帰分析は機械学習の基礎の基礎であり、統計学の手法の1つでもある。
単回帰分析のモデルは単体ではあまり使われないが、これをベースにさまざまな機械学習の手法へとつなげていくことのできるため、これを理解しておくことは非常に大事である。
次回からは、複数の説明変数から目的変数を予測することで、実際の現象に非常に近い分析を行うことのできる手法について解説していく。

<h2>参考</h2>
[scikit-learn API Regerence](https://scikit-learn.org/stable/modules/classes.html)