【単回帰分析】機械学習特訓 ver.1（まとめ）

## はじめに
タイタニック（分類）や住宅価格予測（回帰）のコンペで練習したものの後半の機械学習モデルの選定あたりからイメージがつかない・・・。
そもそも参考書によって使うモデルもバラバラで何基準で考えているのかわからない・・・。
なので、機械学習モデルを順番に触れて大まかなイメージを掴んでいきます！

#### 【特訓 ver.1】 単回帰分析からスタート！！

## ▼学習の流れ
まずは、大まかな流れを抑える
（ボストン市郊外の地域住宅価格に関するデータを用いる）

<b>▼練習問題</b>
アイスコーヒの売り上げとその日の最高気温

## それではスタート！！
##### 大まかな流れ
① 回帰式を求める意味があるか検討する
　    ↓
② 回帰式を求める
　    ↓
③ 回帰式の精度を確認する

## 大まかな流れを知る（ボストンの住宅価格）
・データセットを読み込む
```python
import pandas as pd
df = pd.read_excel("/content/boston_clean.xlsx")
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/ee4e9119-545e-c7bc-9d06-e87206bbd9ed.png)

単回帰分析・・・x（勤続年数）とy（年収）との関係を考えて式を作る。
例）勤続年数2年目で300万円、4年で550万円、7年目で800万円。さて、6年目でいくら？みたいな感じ。

なので、今回は、2つの関係値がありそうな以下を取り上げる。
・RM（説明変数）・・・平均部屋数（住宅の広さなど）
・MEDV（目的変数）・・・住宅の価格


### <font color="##0000FF">**▼ ① 回帰式を求める意味があるか検討する**
・データの可視化をして、関係がありそうかを確認
</font>
```python
import matplotlib.pyplot as plt
plt.scatter(df["RM"],df["MEDV"])
plt.title("RM vs MEDV")
plt.xlabel("RM")
plt.ylabel("MEDV")
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/d568cb85-8ce8-c19a-b50f-5dba6d56d528.png)

➡️ 何となく右上がりに点がプロットされている（から2つに関係がありそう）

・相関係数が「1」または「-1」に近いかどうか
```python
df[["RM","MEDV"]].corr()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/5d4fa0d9-7099-45d4-5a5a-2aa5c29fc10f.png)

➡️ 0.7と低くはない・・・（から2つに関係がありそう）

関係があるはずなので回帰式を求めるステップへGO！！

### <font color="##0000FF">**▼ ②回帰式を求める**

y = a + bx
a（切片）・・・`intercept`で求める
ｂ（傾き）・・・`coef[0]`で求める 

自力で式を作るのは大変なため、最小二乗法によって算出できる、
<font color="##FF0000">**LinearRegression（リニアリグレッション）** を利用する。

```python
from sklearn.linear_model import LinearRegression  # 予測モデルである「線形回帰」を使えるようにする
model = LinearRegression()  # 線形回帰を使って予測モデルを作る
X = df["RM"].values.reshape(-1,1) # 部屋の数をNumpy配列にして、それを表のような形に変えます
Y = df["MEDV"].values  # 家の価格もNumpy配列にする
model.fit(X,Y)  # 部屋の数と家の価格を使って、予測モデルを学習させる
```
※reshape(-1,1) は、部屋の数のリストを、コンピュータが予測しやすい表の形に変えるために使う。これにより、コンピュータは各家について1つずつ数を認識することができる。


```python
print(f"intercept（切片）は、{model.intercept_}")
print(f"coefficient（傾き）は、{model.coef_[0]}")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/15b2eaa0-fb43-305a-821e-85a2223e48b9.png)

回帰分析から得られた回帰式は、
y = -34.67 + 9.10 x
###### 完成！！！！！！

<br>
せっかくなのでグラフ化まで行う。式は赤色にて記述。


```python
plt.scatter(X,Y,color="blue")
plt.plot(X,model.predict(X),color="red")
plt.show()
```
※model.predict(X)は、学習済みの線形回帰モデルを使って、部屋の数（X）から住宅価格（Y）を予測する値を計算している。回帰モデルによって最小二乗法で求められており、予測結果を直線（XとYをplotして結ぶ）でグラフに表示している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/56edc4be-c68d-2160-952d-29ba62067e0c.png)


続いて、作った回帰式を用いて値を算出してみる。
x = 9 までが最大値なので、 X = 10 の時の値を算出。

y = -34.67 + 9.10 x 　に　X = 10 を代入すると、
y = 56.35

コードでの記述する場合は・・・

```python
x_10 = np.array(10).reshape(-1,1)
y_pred = model.predict(x_10)
y_pred
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/8b7c350d-5b55-ed33-65f5-3611c1960327.png)

### <font color="##0000FF">**▼ ③ 回帰式の精度を確認する**

・学習に用いるデータと、性能評価に用いるデータを分ける（7:3が一般的）※7の方を訓練データ、3の方をテストデータと呼ぶ。

⬇️画像参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/a9d6c1d8-d9fc-8fdb-1afa-d7762ceb1185.png)



#### 【確認方法】
その１）残差プロットでの確認
その２）平均二乗誤差（MSE）での確認
その３）決定係数（R²）での確認
※目的に合わせて使い分ける！

#### その0） 訓練データとテストデータに分ける

```python
from sklearn.model_selection import train_test_split
X_train,X_test,Y_train,Y_test = train_test_split(
    X,Y,train_size=0.7,random_state=0)
```
⬇️ その後、学習モデルまで作成
```python
model = LinearRegression() #線形回帰を使うための準備
model.fit(X_train,Y_train) #訓練データを使って、予測の勉強をさせる
Y_pred = model.predict(X_test) #テストデータ（X）を用いてYを予測する
```
#### その1） 残差プロット
特徴：残差プロットは、予測した値と実際の値の違い（残差）を点で示す。これを見ることで、モデルがどれだけ上手に予測できているかが一目でわかる。
今回の場合は、予測したY_predとY_testの差分を表示して0に近くんなっているかどうかを確認。明らかに数値がはみ出している場合は、「外れ値」の可能性がある。
```python
plt.scatter(Y_pred,Y_pred - Y_test,color="red")
plt.hlines(y=0,xmin=0,xmax=50,color="black") #視覚化しやすいように理想値0に線を引く
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/7abbbea4-fd63-ebef-3e8e-b22b3c1ae629.png)

#### その2） 平均二乗誤差（MSE：Mean Square Error）
特徴：予測の間違いを数値で表す。この値が小さいほど、モデルの予測が正確であると言える。具体的には、予測と実際の値の違いを二乗して平均を取ることで計算される。

```python
from sklearn.metrics import mean_squared_error
test_mse = mean_squared_error(Y_test, Y_pred) #X_testから予測したY_predと、Y_testの二乗誤差を算出
print("テストデータのMSE:", test_mse)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/053ec314-c387-313a-bf62-1c863e822d97.png)

この数字だけだと精度が高いか確認しづらいため、X_trainから予測したY_train_predとY_trainでも算出する。
```python
Y_train_pred=model.predict(X_train)
train_mse = mean_squared_error(Y_train, Y_train_pred) #X_trainから予測したY_train_predと、Y_trainの二乗誤差を算出
print("訓練データのMSE:", train_mse)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/98a56f13-f702-4a95-ca30-da755cd0e98f.png)

【47と42を比較する意味】
訓練データのMSEが42、テストデータのMSEが47という場合、これを比較することで、モデルがどれだけ「一般的に」機能しているかがわかる。

もし訓練データのMSEよりテストデータのMSEがずっと高い場合（例：訓練は30、テストは70など）：
これはモデルが過学習（訓練データには非常によく合うが、新しいデータにはうまく適応できない）している可能性がある。
<br>
訓練データとテストデータのMSEが近い場合（例：訓練は42、テストは47）：
これはモデルが訓練データと新しいデータの両方で同様にうまくまたはそれなりに機能していることを示しており、一般的には良いサインである。

完全に一致はしなくても、近ければ近いほどモデルが安定していると考えることができます。


#### その3） 決定係数（R²）
特徴：決定係数は、0から1までの範囲で表され、モデルがデータをどれだけうまく説明しているかを示す。1に近いほど良いモデルで、0.6以下はモデルの性能が低いとされ、0.9以上はデータに過剰にフィットしている「過学習」の可能性がある。

```python
from sklearn.metrics import r2_score
test_r2_score = r2_score(Y_test,Y_pred)
print("テストデータの決定係数:",test_r2_score)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/7514356b-cf98-f6bd-80c2-2f436fddffd5.png)


```python
train_r2_score = r2_score(Y_train,Y_train_pred)
print("訓練データの決定係数:",train_r2_score)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/9b9f38f2-14b1-6e12-e791-8e0543a6e812.png)

一貫して決定係数が高いか確認することが大切。

<br>
<b>それでは、練習問題に行ってみよー！！

## 【練習問題】 アイスコーヒの売り上げとその日の最高気温
以下、4ステップを意識して実施。
・データセットを読み込む
・回帰式を求める意義があるか検討
・回帰式を求める
・回帰式の精度を確認

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

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

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

# 散布図の描画
plt.scatter(df["temperature"], df["icecoffee"])
plt.title("Temperature vs Ice Coffee Sales")
plt.xlabel("Temperature")
plt.ylabel("Ice Coffee Sales")
plt.show()

# データの分割
X = df["temperature"].values.reshape(-1, 1)
Y = df["icecoffee"].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_train_pred = model.predict(X_train)
Y_pred = model.predict(X_test)

# 残差プロット
plt.scatter(Y_test_pred, Y_pred - Y_test, color="red")
plt.hlines(y=0, xmin=Y_pred.min(), xmax=Y_pred.max(), color="black")
plt.show()

# 訓練データとテストデータでのモデル評価
train_mse = mean_squared_error(Y_train, Y_train_pred)
test_mse = mean_squared_error(Y_test, Y_pred)
train_r2 = r2_score(Y_train, Y_train_pred)
test_r2 = r2_score(Y_test, Y_pred)

print("訓練データのMSE:", train_mse)
print("テストデータのMSE:", test_mse)
print("訓練データの決定係数:", train_r2)
print("テストデータの決定係数:", test_r2)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/58df499a-8831-2621-998a-1c08d5effd4e.png)

【考察】
・気温とアイスコーヒーの売り上げの相関
　∟ 相関係数が92%であるため、気温が売り上げに大きく影響している
・決定係数が80%を超えているため、モデルの予測精度が比較的良い。
・他の影響要因、外れ値の除外
　∟ 曜日効果や特別なイベントの影響を考慮することで、売り上げ予測の精度をさらに向上させる可能性がある。また、外れ値の特定と除去、または適切な処理を行うことで、モデルの信頼性と精度を向上させることができる。

<br>
続いては、
<b>多項式回帰分析へGO！！！</b>