【多項式回帰分析】機械学習特訓 ver.2（予習）

<b> 【特訓 ver.2】 多項式回帰スタート！！

・単回帰分析の場合は、1次関数のような関係の場合に利用。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/07dc9418-49f7-819a-2387-1e620c0d38b1.png)

ただし、いつも上記のように、シンプルに比例するような関係でない場合もある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/881ec1b7-a5e9-efcd-7bfa-3f39edc2771a.png)

<br>

・その場合に多項式回帰で考える。2次以上の関数に適用する（2次関数など）
　※とはいえ、事前に多項式回帰とわかるケースは少ないらしい...。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/918dbc35-dacc-29d8-bb32-ef2d565ee785.png)


## それではスタート！！
##### 大まかな流れ
以下、2ステップで実践。

<b>その１：</b>まずは、前回学習した【単回帰分析】で実装。
<b>その２：</b>その後、【多項式回帰】で実装し、精度の違いを見てみる。

##### 使用データ
Position_Salaries.csv
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/c830aae2-4687-cdb8-7523-89f073d2158a.png)

## その1：単回帰分析
・データの確認
・データの分割→線形回帰モデルの作成
・結果の可視化、および評価

復習なのでサクッと！

```python
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# データの読み込み
df = pd.read_csv("/content/Position_Salaries.csv")
print(df.head())
print()

# 相関の確認
print(df[["Level", "Salary"]].corr())

# 散布図の描画
plt.scatter(df["Level"], df["Salary"])
plt.title("Level vs Salary")
plt.xlabel("Level")
plt.ylabel("Salary")
plt.show()

# データの分割
X = df["Level"].values.reshape(-1, 1)
Y = df["Salary"].values
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, train_size=0.7, random_state=0)

# モデルの訓練
model = LinearRegression()
model.fit(X_train, Y_train)

# 予測
Y_pred = model.predict(X_test)

# グラフの可視化
plt.scatter(X, Y, color="blue")
plt.plot(X, model.predict(X), color="red")
plt.title("Level vs Salary Prediction")
plt.xlabel("Level")
plt.ylabel("Salary")
plt.show()

# モデルの評価
mse = mean_squared_error(Y_test, Y_pred)
r2 = r2_score(Y_test, Y_pred)
print(f"テストデータのMSE: {mse}")
print(f"テストデータのR²: {r2}")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/6836a4f2-3aeb-b427-f456-a4d707e09b3c.png)

<b>番外編</b>
・式の作成、モデルの予測
```python
#式の算出
print(f"intercept（切片）は、{model.intercept_}")
print(f"coefficient（傾き）は、{model.coef_[0]}")
```
回帰分析から得られた回帰式は、
y = -187264.57 + 82522.42 x

<b>完成！！！！！！</b>

```python
#仮にレベル12の階級があった時の給与を算出
import numpy as np
x_12 = np.array(12).reshape(-1,1)
y_pred = model.predict(x_12)
y_pred
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/1dea4123-9071-9b18-e651-831237be0e14.png)

仮にレベル12の階級があった時の給与は、だいたい800000くらい・・・。だいぶ乖離がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/007b165c-8129-9dc9-c5e7-fb4119473696.png)


## その２：多項式回帰分析

<b>大まかな流れ</b>
① データの準備と可視化
　 ↓
② モデルの設定と訓練
　 ↓
③ 結果の可視化
　 ↓
④ 式の作成、代入して考察

### ① データの準備と可視化
```python
import pandas as pd
import matplotlib.pyplot as plt

# データの読み込み
df = pd.read_csv("/content/Position_Salaries.csv")
print(df.head())

# 散布図の描画
plt.scatter(df["Level"], df["Salary"])
plt.title("Level vs Salary")
plt.xlabel("Level")
plt.ylabel("Salary")
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/eee958c2-c52c-6c2b-ee5e-33016f10169f.png)

ここまでは先ほどと同じ。

### ② モデルの設定と訓練

```python
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

X = df["Level"].values.reshape(-1,1)
Y = df["Salary"]

# 多項式特徴量の生成
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)

# モデルの訓練
model = LinearRegression()
model.fit(X_poly, Y)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/61e5d46f-6fba-0cf4-4908-493a2e6e66ad.png)

単回帰との違いについて（1次関数）。
こちらはX、Yとの関係が非常にシンプルになっているためそのままmodelに突っ込めばよかった。

一方でそれ以上の関数（2次以上の関数）の場合は、複雑になるため、まずは、Xの累乗値の値を別で求めてあげる必要になる。
※y = ax²の x²の部分

手順としては、
・X、 Yの設定をする
・modelに当てはめる　が単回帰の方法だが、その間にワンクッションを挟む。

具体的には
<b>・X、 Yの設定をする
　　　　 ↓
・高次数にも対応するように「PolynomialFeatures」を設定する
　　　　 ↓
・高次数に対応したX（今回でいうとX_poly）を用いてmodelを訓練する</b>
<br>
【コードの説明】
・`poly = PolynomialFeatures(degree=2)`
　これはdegree=2で2次関数を表す。
　変数Xを2次関数に対応させるための前準備。
・`X_poly = poly.fit_transform(X)`
　先ほど準備したものを、実際に対応させる（出力結果は以下）。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/f9d2dd8e-f2f4-08e6-d33a-1ce1fe8a7218.png)
　今回はLEVELが1~10まであるため、最後の行でx²の値を出力している。
　※2行目がX、3行目がX²の値。

### ③ 結果の可視化

```python
#結果の可視化
plt.scatter(X,Y,color="blue")
plt.plot(X,model.predict(X_poly),color="red")
plt.show()

# より滑らかなカーブを作成する（ために、説明変数(X)をより細かくする）
X_grid = np.arange(min(X),max(X),0.1)
X_grid = X_grid.reshape(-1,1)
plt.scatter(X, Y, color="blue")
plt.plot(X_grid, model.predict(poly.transform(X_grid)), color="red")
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/b4295f91-8bc2-66a4-ff9c-ce20c544473b.png)


### ④ 式の作成、代入して考察

```python
#式を求める
print(f"式は、y = {model.intercept_} + {model.coef_[1]}x + {model.coef_[2]}x^2")

#x=12を代入して、精度を確認
x_12 = np.array(12).reshape(-1,1)
y_pred = model.predict(poly.transform(x_12)) 
y_pred
```

a（切片）・・・`intercept_`で求める
ｂ（傾き）・・・`coef_[1]` `coef_[2]`で求める
※coef_[0]はintercept_と一致（xの0乗の係数を意味する。が実際には機能しない）
※coef_[1]はxの1乗の係数を意味する。
※coef_[0]はxの2乗の係数を意味する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/81d43873-0099-63b9-29d3-cdfa693d47f4.png)
単回帰分析の際は、「仮にレベル12の階級があった時の給与は、だいたい800000くらい・・・。」と出力されたが、今回は、1435893と結果が出て、現実的な値に近づいた。


## 【練習問題】 あさがおの成長を分析

以下、4ステップを意識して実施。
・データの準備と可視化
・モデルの設定と訓練（<b>多項式回帰を用いる</b>）
・結果の可視化
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

# データの準備
df = pd.read_csv("/content/asagao.csv")

# 散布図でデータを可視化
plt.scatter(df['days'], df['length'], color='blue')
plt.title('days vs length')
plt.show()

# データの分割
X = df['days'].values.reshape(-1, 1)
Y = df['length'].values
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)

# モデルの設定と訓練
poly = PolynomialFeatures(degree=4)
X_poly_train = poly.fit_transform(X_train)
X_poly_test = poly.transform(X_test)
model = LinearRegression()
model.fit(X_poly_train, Y_train)

# 結果の可視化
X_grid = np.arange(min(X), max(X), 0.1).reshape(-1, 1)
X_poly_grid = poly.transform(X_grid)
Y_grid_pred = model.predict(X_poly_grid)

plt.scatter(X, Y, color='blue', label='data')
plt.plot(X_grid, Y_grid_pred, color='red')
plt.title('asagao_pred')
plt.legend()
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/3e5beaea-5d6a-e34f-51c0-bfc761928dae.png)

ついでの評価の精度も見ておく。
```python
from sklearn.metrics import mean_squared_error, r2_score
# モデルの評価
Y_train_pred = model.predict(X_poly_train)
Y_test_pred = model.predict(X_poly_test)
train_mse = mean_squared_error(Y_train, Y_train_pred)
test_mse = mean_squared_error(Y_test, Y_test_pred)
train_r2 = r2_score(Y_train, Y_train_pred)
test_r2 = r2_score(Y_test, Y_test_pred)

print(f'Train MSE: {train_mse}, Test MSE: {test_mse}')
print(f'Train R^2: {train_r2}, Test R^2: {test_r2}')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/96559c74-bd4f-1add-858b-fc43118eabe7.png)

精度を試す中で、degree=4の時からR^2が1にだんだん近づいていった。

<br>

続いては、 <b>重回帰分析へGO！！！</b>