【番外編】正則化について（まとめ）

<b> 【番外編】 正則化スタート！！</b>
※この記事では正則化についてまとめます

## ▼学習の流れ
まずは正則化の概念を学び、具体的な分析例を通して理解を深めていく。

■使用するデータ
乳がんに関するデータ（全データ569）
説明変数：30個（腫瘍の半径、面積、深さ・・・）
目的変数：0は悪性(癌である)、1は良性(癌でない)

このデータを使用して、様々な測定値に基づいて腫瘍が悪性か良性かを予測するモデルを構築していく。

※データセット：後日（breast_cancer_data.csv）

<font color="#FF0000">■ 正則化について学習する</font>
- 不足学習（未学習）と過学習の復習
- 過学習を防ぐための手法の一つとして、正則化を紹介

<font color="#FF0000">■ どんな種類があるのか</font>
- リッジ回帰
- ラッソ回帰
- Elastic Net回帰

<br>
<b>▼練習問題</b>　【番外編】のため省略。


## ▼復習
・<b>過学習とは</b>
モデルが学習データに過剰に適合し、新しいデータや少し異なるデータに対して柔軟に対応できない状態を指す。この状態のモデルは実運用では効果的に機能しにくい。

（イメージ）
・テスト前に一夜漬け学習した学生のようなもの
→ 丸暗記状態のため、少しひねった問題を出されたら解けなくなる状態💧
<br>

例１：不足学習（未学習）の場合
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/2346a3df-6ed9-d99c-7628-98c3d3da0964.png" width=60%>
このグラフでは、データを無理やり1次関数で予測している。このアプローチでは自由度が低すぎ、かつ、データの複雑性を捉えられていないため、予測能力があまりない。

例２：過学習の場合
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/f32ec60c-de21-2272-5595-fe760ea2d845.png" width=60%>
反対に、このグラフのモデルはデータ点を完璧に通るように過剰に調整されている。結果として、このモデルはデータのノイズまで学習してしまい、実際の予測においては役立たずとなる可能性が高い。まさに丸暗記状態。
 
これらを防ぐために、<b>「正則化」</b>を行う。
以下、実際に正則化を行なった時のグラフになる。
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/02f797bb-ab1c-5c6e-0253-a421420f1b34.png" width=60%>
このグラフでは、フィットが改善され、データに適度に合わせることができている。正則化により、過剰な自由度が抑制され、モデルの汎用性が向上する。
<br>

イメージで言うとこんな感じ ↓
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/dec2700e-b73c-b060-b0f2-84b353e0c96f.png">



※参照：過学習を防ぐための方法は以下が代表的。
・学習データの量を増やす（いつも増やせるとは限らない）
・モデルの複雑さを減らす（精度が落ちる可能性がある）
・ドロップアウトを使用する
・正則化を適用する　<font color="#FF0000">← 今回はコレ！</font>

## ▼正則化とはどんな種類があるのか？
正則化には、L2正則化（リッジ回帰）、L1正則化（ラッソ回帰）、およびそれらを組み合わせたElastic Netがある。
※細かな数式等については現時点では省略します
（以下、記事が非常にわかりやすい！）
　https://qiita.com/c60evaporator/items/784f0640004be4eefc51

#### リッジ回帰（L2正則化）
リッジ回帰は、特徴の重みを完全にはゼロにせず、小さくすることに焦点を置く。これにより、すべての特徴がある程度モデルに影響を与えるが、過剰適合を防ぐことができる。

#### ラッソ回帰（L1正則化）
ラッソ回帰は、不要な特徴を完全に取り除くことができる。これは特徴選択としても役立ち、重要でないデータの影響をモデルから排除する。具体的には、モデルの一部の重みをゼロにして、シンプルで解釈しやすいモデルを作る。

#### Elastic Net回帰
Elastic Netはラッソとリッジの両方の特性を持つ。つまり、不要な特徴を排除しつつ、残りの特徴の重みも適切に調整する。これにより、ラッソの特徴選択の利点とリッジの安定性を兼ね備えたモデルを作ることができる。

## それでは実際に使ってみよう！！
### 【正則化の違いについて確認する】
<b>大まかな流れ</b>
① データ読み込みや前処理、分割
② モデルの設定と訓練<b>
　- 1. ロジスティック回帰分析 で実施する
　- 2. リッジ回帰（L2正則化）で実施する
　- 3. ラッソ回帰（L1正則化）で実施する
　- 4. Elastic Net回帰 で実施する</b>

③ モデルの精度の確認
　- 精度について確認していく
　- <b>trainデータでの正解率、testデータでの正解率</b>に着目する
　- trainデータとtestデータ、どちらも良いものが理想的。

### ① データ読み込みや前処理、分割
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# データの読み込み
df = pd.read_csv("/content/breast_cancer_data.csv")
df.head()
```
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/be08d2ad-9905-ea9e-c237-97979c00dfbb.png)

↑ 乳がんに関するデータ（全データ569）
説明変数【下記以外の全て】：30個（腫瘍の半径、面積、深さ 等）
目的変数【type】：0が悪性（癌）、1が良性（癌でない）

```python
#説明変数と目的変数に分ける
x = df.drop(["type"],axis=1).values
y = df["type"].values

#データを学習用と検証用に分割
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)
    
#標準化
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
x_train_std = sc.fit_transform(x_train)
x_test_std = sc.transform(x_test)
```
データの準備完了！


### ② モデルの設定と訓練
##### パラメータ設定の違いについて
model = LogisticRegression(　)の（　）内に書く値によって、正則化をするかどうか、またその種類を決めることができる。

※参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/80b97a29-69ff-6742-3058-095b2142e755.png)
正則化の種類を指定する`penalty`は、モデルの学習方法に大きな影響を与える。また、選択した`penalty`に適した学習アルゴリズムを指定するために、`solver`も同時に変更する必要がある。

##### 1.ロジスティック回帰分析（正則化なし）の場合
`penalty='none'` を指定して正則化を適用しない設定にする。

```python
from sklearn.linear_model import LogisticRegression

# ロジスティック回帰モデル（正則化なし）
model_logistic = LogisticRegression(solver="lbfgs", penalty="none")
model_logistic.fit(x_train_std, y_train)
```
##### 2.リッジ回帰の場合
`penalty='l2'`でリッジ回帰（L2正則化）を適用。`C=1.0`で正則化の強さを標準的に設定する。

```python
from sklearn.linear_model import LogisticRegression

# リッジ回帰モデル（L2正則化）
model_ridge = LogisticRegression(solver="lbfgs", penalty="l2", C=1.0)
model_ridge.fit(x_train_std, y_train)
```
##### 3.ラッソ回帰の場合
`penalty='l1'`はラッソ回帰（L1正則化）を適用。`solver='saga'`はL1正則化に対応させて、`max_iter=5000`で収束に必要なイテレーション数を増やす。

```python
from sklearn.linear_model import LogisticRegression

# ラッソ回帰モデル（L1正則化）
model_lasso = LogisticRegression(solver="saga", penalty="l1", C=1.0, max_iter=5000)
model_lasso.fit(x_train_std, y_train)
```
##### 4.Elastic Net回帰の場合
`penalty='elasticnet'`はElastic Net正則化を適用。`l1_ratio `はL1とL2の正則化の混合比率である。
```python
from sklearn.linear_model import LogisticRegression

# Elastic Net回帰モデル
model_elasticnet = LogisticRegression(solver="saga", penalty="elasticnet", C=1.0, l1_ratio=0.5, max_iter=5000)
model_elasticnet.fit(x_train_std, y_train)
```

### ③ モデルの精度を確認
```python
print("正解率(train):",model.score(x_train_std,y_train))
print("正解率(test):",model.score(x_test_std,y_test))
```
上記をテンプレートとして、回帰の結果をそれぞれ出力する。
<b>左上</b>：1.ロジスティック回帰分析（正則化なし）
<b>右上</b>：2.リッジ回帰
<b>左下</b>：3.ラッソ回帰
<b>右下</b>：4.Elastic Net回帰
<p float="left">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/72a5df62-bfcd-5afa-94e1-38c14929ab27.png" width=49%">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/1c85f3ca-e829-0c4d-9f03-67e09a206773.png" width="49%">
</p>
<p float="left">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/d2c20661-7bf5-1eff-ba31-5fc52149a3e6.png" width=49%">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/196b6b11-ee06-518d-5d8e-3a444c6f9c80.png" width="49%">
</p>

こちらをみると、<b>testデータの精度が高かったのは、右上、右下のデータである。</b>そのため、今回のケースでいうと、リッジ回帰とElastic Net回帰に軍配が上がった。
一方で、<b>左上のデータは、trainデータは完璧ではあるもの、本番のtestデータで成果が落ちている</b>。これは<b>「過学習」</b>の特徴として挙げられるものである。
このように、バランスよく成果を出せるモデルを作るために、正則化を用いることが必要。
<br>
なぜこのような違いが出るのかを以下、簡単にまとめてみる。
モデルの式を見てみるとわかりやすいためそちらに着目する。
1.ロジスティック回帰分析（正則化なし）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/709d4424-8515-6efa-79ff-4bae18d8c7d4.png)
2.リッジ回帰
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/3f7dfd77-3826-1f22-4f2c-fbed2390e11d.png)
3.ラッソ回帰
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/6b147454-b0f4-b302-280e-87d3737b2352.png)
4.Elastic Net回帰
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/b6b4b59e-8ac0-44b4-ecb7-833ba2d3e3ca.png)

プロットされた点を全て通るように、あえて係数を大きくしてまで調整してしまっていることが過学習の要因。

Cofficient（係数）に着目した場合、以下が気付きポイント。
・ロジスティック回帰分析（正則化なし）の値が大きく、それに比べて、その他の分析モデルは小さい。
・ラッソ回帰は0が多くあり、不要だと判断した値は「0」にしている。
・ラッソ回帰、リッジ回帰とそれぞれのバランスをとる形でElastic Net回帰が作られている。
※とはいえ、場合によっては、ラッソやリッジ回帰の方が良い結果が出ることもある。
<br>
<b>以上。</b>