【SVM（サポートベクターマシン）】機械学習特訓 ver.5（まとめ）

<b> 【特訓 ver.5】 SVMスタート！！</b>
※この記事では、SVM（サポートベクターマシン）を用いた分類手法についてまとめます

## ▼学習の流れ
まずはSVM（分類）の基本を押さえ、具体的な分析例を通して理解を深める。
※なお、SVMは回帰問題にも応用される「サポートベクター回帰」と呼ばれる手法もありますが、分類問題に比べて使用頻度が低いため本記事では割愛します。

■使用するデータ
（図１）線形用データ：Social_Network_Ads.csv
（図２）非線形用データ：gpt_hisenkei.csv

※データセット：後日

データセットのイメージはそれぞれ以下の通り：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/1c682d28-a9c8-d78b-2e71-b1392c955f70.png)


<font color="#FF0000">■ SVM分析について学習する</font>
上記、赤点と青点を上手に<b>「分類」</b>していく

大まかな流れ）
① データ読み込みや前処理、分割
　- 質的変数は用いることができない

② モデルの設定と訓練
　- 「SVM」で実施する

③ モデルの精度の確認
　- 精度について、以下6項目で確認していく

分類における「学習モデルの性能評価」について確認していく！
(1) 混同行列（confusion matrix）
(2) 正解率（accuracy）
(3) 適合率（precision）
(4) 再現率（recall）
(5) F1スコア（F1-score）
(6) AUC（曲線下面積）
<br>

## ▼復習

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/7dd7a1c3-e9c0-8c22-9a8f-4df5d2839149.png)
※左側が「分類」、右側が「回帰」の例

前回学習したロジスティック回帰では、目的変数が質的の場合に求めていた。いわゆる2択の状態の時。前提情報を用いて、結果を2つに分けることを<b>「分類」</b>と呼ぶ。
対するは、重回帰分析のような、前提情報を用いて数値を予測する場合は<b>「回帰」</b>と呼ぶ。

今まで習ったものや代表的なものをカテゴリ分けすると以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/4b35c745-e827-65d6-8d2c-2be9926e07bc.png)
今回は、その中でもよく分類で使われることが多い「SVM（サポートベクターマシン）分析」に焦点を当てていく。

## ▼SVMとは？
SVMは、複数の説明変数を基に、2つのクラスに分類するための手法である。通常、分類問題に使用される手法だが、回帰問題に対しても拡張して使われることがある。

##### さて、ここでクイズ！！

赤色の点の集まりと、青色の点の集まりを分けたく、分割する線を引くことにした。
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/75a0c67d-7059-b67a-61ab-e850bf786f07.png" width=50%>


以下の線は、どちらの方が綺麗に分けられているでしょうか？！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/156659e6-1759-f0a9-bf2c-e8c966684f64.png)

結論、直感的に見ると<b>「②の方が綺麗に分けられていそう」</b>と言える。
こういった線を簡単に引ける方法があれば嬉しい。
→ この均等に分けるための線（モデル）を作るための手法して用いられるものを「SVM（サポートベクターマシン）」と呼ぶ。

ではこれの仕組みを簡単に理解していく。
<p float="left">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/126400b6-a3de-6337-f038-f9d79435b3fa.png" width=49%">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/10705612-79e5-a18f-d308-38e099270a7e.png" width="49%">
</p>
<p float="left">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/1a75ed26-f3a8-5cdf-9535-c7e07ce01368.png" width=49%">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/79d16366-815c-d999-6a8d-558b4404e2f6.png" width="49%">
</p>

この手順で、②の分類線を作ることができる。
この線を作成するまでの流れを「SVM」で行うことが可能。
<br>
もう少し踏み込んで考えてみる。
今のような、赤点と青線を分けられるものを<b>線形分離可能</b>と呼び、一方で、線形分離<b>不</b>可能なものも存在する。

例として、以下が挙げられる。
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/6cce25f5-74b2-ae72-b556-335a37f40913.png" width=50%>
上記のオレンジの点、青の点を、一本の直線で分けることは不可である。

ではどのように分類するのか？
結論、以下のように<b>「次元を増やして」</b>分類できるようにしてあげる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/c9a67cad-ff87-4bc2-fb19-8b64949d8831.png" width=50%>
参考：https://www.shoeisha.co.jp/book/article/detail/233

身近な例で見ると、富士山などもそうである。
上から見ると分類線が引けないが、正面から見れば分類線が引ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/03e04ae9-e080-bcdc-b933-b7da40cd3ed7.png)

このように、線形分離<b>不</b>可能なものを分けるために次元を増やして考えることを<b>カーネルトリック（カーネル法を用いる）</b>という。

## それでは実際に使ってみよう！！
### 【SVM】
<b>大まかな流れ</b>
① データ読み込みや前処理、分割
　- 質的変数は用いることができない

② モデルの設定と訓練
　- 「SVM分析」で実施する
　- （参照）分類結果のプロット

③ モデルの精度の確認
　- 精度について、以下6項目で確認していく
　　(1) 混同行列（confusion matrix）
　　(2) 正解率（accuracy）
　　(3) 適合率（precision）
　　(4) 再現率（recall）
　　(5) F1スコア（F1-score）
　　(6) AUC（曲線下面積）

### ＜まずは線形用データセットを用いて分析＞

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

# データの読み込み
df = pd.read_csv("/content/Social_Network_Ads.csv")
df.head()
```
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/b91da5a1-7875-2505-1489-fe54fc5ea936.png" width=50%>

〔説明変数〕
・Age（年齢）、EstimatedSalary(お給与)

〔目的変数〕
・Purchased・・・1=購入する、0=購入しない


```python
#説明変数と目的変数に分ける
x = df[["Age","EstimatedSalary"]].values
y = df["Purchased"].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)
```
データの準備完了！
<br>

<b>② モデルの設定と訓練</b>

```python
#線形SVMの学習モデル
from sklearn.svm import SVC
model = SVC(kernel = "linear",C=1.0,probability=True,
            max_iter=10000,random_state=0)
model.fit(x_train_std,y_train)
```
パラメータについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/a57ad22b-0c3f-5e65-d2b9-28286e8b9cd1.png)
`kernel`が大事。
線形分離可能な（直線で分けられる）場合は`linear`を使い、複雑なデータの場合は`rbf`を用いることが多い。

※参照：分析結果をプロット
```python
from mlxtend.plotting import plot_decision_regions

x_train_plot = np.vstack(x_train_std)
y_train_plot = np.hstack(y_train)
x_test_plot = np.vstack(x_test_std)
y_test_plot = np.hstack(y_test)

plot_decision_regions(x_test_plot,y_test_plot,clf=model,legend=2)
```
<p float="left">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/69276f42-17bf-4705-21b2-5f85c89c4e74.png" width=48%">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/8add6ed3-b5c8-b19c-09c8-c6f9d425ea16.png" width="49.6%">
</p>
<b>左図</b>：SVM分析で分割線を引いた図　<b>右図</b>：分割前の図


<b>③ モデルの精度を確認</b>
```python
from sklearn.metrics import confusion_matrix,precision_score,recall_score,f1_score,roc_auc_score

# 混同行列の出力
print("Confusion Matrix:")
print(confusion_matrix(y_true=y_test, y_pred=model.predict(x_test_std)))

# 性能指標の計算と表示
print("正解率(train) =", model.score(x_train_std, y_train))
print("正解率(test) =", model.score(x_test_std, y_test))
print("適合率 =", precision_score(y_true=y_test, y_pred=model.predict(x_test_std)))
print("再現率 =", recall_score(y_true=y_test, y_pred=model.predict(x_test_std)))
print("F1スコア =", f1_score(y_true=y_test, y_pred=model.predict(x_test_std)))
print("AUC =", roc_auc_score(y_true=y_test, y_score=model.predict_proba(x_test_std)[:, 1]))
```

▼ 回帰式の精度を確認
　(1) 混同行列（confusion matrix）
　(2) 正解率（accuracy）
　(3) 適合率（precision）
　(4) 再現率（recall）
　(5) F1スコア（F1-score）
　(6) AUC（曲線下面積）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/fd6a5939-88e4-83fc-bbcf-45ef0d98b9ca.png" width=40%>

### ＜次に非線形用データセットを用いて分析＞

<b>① データ読み込みや前処理、分割</b>
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/ffccb818-9b11-d302-174e-ea109b7f7780.png" width=40%>
 ここまではほとんど同じ。

<b>② モデルの設定と訓練</b>

```python
#非線形SVMの学習モデル
from sklearn.svm import SVC
model = SVC(kernel = "rbf",gamma=1/2,C=1.0,
            probability = True,max_iter=10000,
            random_state=0)
model.fit(x_train_std,y_train)
```
パラメータについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/a57ad22b-0c3f-5e65-d2b9-28286e8b9cd1.png)
`kernel`が大事。
線形分離可能な（直線で分けられる）場合は`linear`を使い、複雑なデータの場合は`rbf`を用いることが多い。
※参照：分析結果をプロット
```python
from mlxtend.plotting import plot_decision_regions

x_train_plot = np.vstack(x_train_std)
y_train_plot = np.hstack(y_train)
x_test_plot = np.vstack(x_test_std)
y_test_plot = np.hstack(y_test)

plot_decision_regions(x_test_plot,y_test_plot,clf=model,legend=2)
```
<p float="left">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/a317114a-e898-2f46-be9f-d498a4b9b868.png" width=52%">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/f96e4f71-3062-09e4-e51f-054251a19f8c.png" width="47.2%">
</p>
<b>左図</b>：SVM分析で分割線を引いた図　<b>右図</b>：分割前の図

<b>③ モデルの精度を確認</b>
```python
from sklearn.metrics import confusion_matrix,precision_score,recall_score,f1_score,roc_auc_score

# 混同行列の出力
print("Confusion Matrix:")
print(confusion_matrix(y_true=y_test, y_pred=model.predict(x_test_std)))

# 性能指標の計算と表示
print("正解率(train) =", model.score(x_train_std, y_train))
print("正解率(test) =", model.score(x_test_std, y_test))
print("適合率 =", precision_score(y_true=y_test, y_pred=model.predict(x_test_std)))
print("再現率 =", recall_score(y_true=y_test, y_pred=model.predict(x_test_std)))
print("F1スコア =", f1_score(y_true=y_test, y_pred=model.predict(x_test_std)))
print("AUC =", roc_auc_score(y_true=y_test, y_score=model.predict_proba(x_test_std)[:, 1]))
```

▼ 回帰式の精度を確認
　(1) 混同行列（confusion matrix）
　(2) 正解率（accuracy）
　(3) 適合率（precision）
　(4) 再現率（recall）
　(5) F1スコア（F1-score）
　(6) AUC（曲線下面積）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/66022e30-6bc9-6207-b4e3-9248601270ec.png" width=40%>

<br>

<b>＜まとめ＞</b>
サポートベクターマシン（SVM） は、データを最適に分類する境界線（または超平面）を見つけるための学習モデル。
主に分類タスクに用いられることが多い（回帰で使われることもある）。
カーネルトリックを用いて非線形の問題にも対応することが可能。

<br>
<b>以上。</b>


<br>
続いては、 <b>決定木</b>へGO！！！