サポートベクトルマシンとは？

#サポートベクトルマシン(SVM)とは？
- **「マージン最大化」**と呼ばれる考えに基づき、主に**2値の分類問題**に使われる。(多クラス分類、回帰問題への拡張も可能)

- 計算コストが比較的大きいため、大規模なデータセットには適していない。よって、主に**中小規模のデータセット**で使われる。

#線形分離可能とは？
**直線**でクラス分類が可能か否か。

- 線形分離可能な場合、**ハードマージンSVM**

- 線形分離不可能な場合、**ソフトマージンSVM**
と呼ぶ。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/ee5e553d-58d4-b2b7-63d7-bccbec269ea4.png" class="img" alt="データ">

#「マージン最大化」のイメージ(線形分離可能)
分割した直線から最も近い点までの距離を**マージン**と呼ぶ。

その最も近い点を**サポートベクトル**と呼ぶ。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/5b803655-bec2-d911-358f-df3a6fd5fea0.png" class="img" alt="データ">


#実験①
```py
import mglearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

iris=load_iris()
X=iris.data[50:,2:] #target=0or1or2
y=iris.target[50:]-1


mglearn.discrete_scatter(X[:,0],X[:,1],y)#第1引数…xの1番目の特徴量,第2引数…xの2番目の特徴量,第3引数…正解ラベル
plt.legend(["versicolor","virginica"],loc="best")
plt.show()
```

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/77ccbee8-7091-5a2d-5501-680346e10a58.png" class="img" alt="データ">

##ハイパーパラメータを操作(C=1 or C=100)
```py
from sklearn.svm import LinearSVC
from sklearn.model_selection import train_test_split

X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)

svm=LinearSVC(C=1.0).fit(X_train,y_train)

def plot_separator(model):
    plt.figure(figsize=(10,6))
    mglearn.plots.plot_2d_separator(model,X)
    mglearn.discrete_scatter(X[:,0],X[:,1],y)
    plt.xlabel("petal length")
    plt.ylabel("petal width")
    plt.show()
    
plot_separator(svm)

#Cが大きい→ハードマージンSVMに近づく
#Cが小さい→誤分類を許容しやすい
svm_100=LinearSVC(C=100).fit(X_train,y_train) #default=1
plot_separator(svm_100)
```
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/3307a5d6-6f47-58e6-a5d9-c7bc915419e1.png" class="img" alt="データ"><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/8f2fe536-527d-7a1d-8a2c-b247f6f7663f.png" class="img" alt="データ">



```py

print("score on training set :{:.2f}".format(svm.score(X_train,y_train)))
print("score on test set :{:.2f}".format(svm.score(X_test,y_test)))

print("score on training set :{:.2f}".format(svm_100.score(X_train,y_train)))
print("score on test set :{:.2f}".format(svm_100.score(X_test,y_test)))
```

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/a054decb-c73d-0c52-07cf-73bcf517b795.png" class="img" alt="データ">


#実験②

```py
import mglearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons

moons=make_moons(n_samples=200,noise=0.1,random_state=0)

X=moons[0]
y=moons[1]

plt.figure(figsize=(12,8))
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.plot()
```
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/4280c819-1264-675f-6e1b-4b2e6c8bcea5.png" class="img" alt="データ">

実験①とは異なる二値分布になりました。

```py
from sklearn.svm import LinearSVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

scaler=StandardScaler()
X_scaled=scaler.fit_transform(X)

X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)

lin_svm=LinearSVC().fit(X_train,y_train)

plt.figure(figsize=(12,8))
mglearn.plots.plot_2d_separator(lin_svm,X)
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.xlabel("$x_0$",fontsize=20)
plt.ylabel("$x_1$",fontsize=20)
plt.show()
```

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/9fa59f7b-e9de-58e7-2f8a-7c52790a876e.png" class="img" alt="データ">


線形分離できていないことがはっきり分かりますね。

##高次元特徴量空間生成
```py
from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(degree=3)
X_train_poly=poly.fit_transform(X_train)
X_test_poly=poly.fit_transform(X_test)

#10次元まで拡張できたことを確認
poly.get_feature_names()
```
<img width="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/4cb7a154-7f53-68a1-6fa5-a9a4680e2157.png" class="img" alt="データ">


##標準化
```py
X_train_poly_scaled=scaler.fit_transform(X_train_poly)
X_test_poly_scaled=scaler.fit_transform(X_test_poly)

lin_svm = LinearSVC().fit(X_train_poly_scaled,y_train)
```

```py
#コードが楽になるバージョン
from sklearn.pipeline import Pipeline

poly_svm=Pipeline([
    ("poly",PolynomialFeatures(degree=3)),
    ("scaler",StandardScaler()),
    ("svm",LinearSVC())
])
poly_svm.fit(X,y)
```

```py
def plot_decision_function(model):
    _x0 = np.linspace(-1.5,2.5,100)
    _x1 = np.linspace(-1.0,1.5,100)
    x0,x1 = np.meshgrid(_x0,_x1)
    X=np.c_[x0.ravel(),x1.ravel()]
    y_pred=model.predict(X).reshape(x0.shape)
    y_decision=model.decision_function(X).reshape(x0.shape)
    plt.contourf(x0,x1,y_pred,cmap=plt.cm.brg,alpha=0.2)
    plt.contourf(x0,x1,y_decision,lavels=[y_decision.min(),0,y_decision.max()],alpha=0.3)
    
def plot_dataset(X,y):
    plt.plot(X[:,0][y==0],X[:,1][y==0],"bo",ms=15)
    plt.plot(X[:,0][y==1],X[:,1][y==1],"r^",ms=15)
    plt.xlabel("$x_1$",fontsize=20)
    plt.ylabel("$x_2$",fontsize=20,rotation=0)

plt.figure(figsize=(12,8))
plot_decision_function(poly_svm)
plot_dataset(X,y)
plt.show()
```

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/a61746bf-d7d3-daa8-fa3d-4f4b5d592dfb.png" class="img" alt="データ">


#カーネル法を用いて計算負荷量軽減
カーネル法は**高次元特徴量を計算する**際に計算量を軽減してくれるもの。(内積計算が得意)

```py
from sklearn.svm import SVC

kernel_svm=Pipeline([
    ("scaler",StandardScaler()),
    ("svm",SVC(kernel="poly",degree=3,coef0=1))#poly=多項式
])

kernel_svm.fit(X,y)

plt.figure(figsize=(12,8))
plot_decision_function(kernel_svm)
plot_dataset(X,y)
plt.show()
```

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/9b21c895-d353-9aa1-9bf7-bcbba3bb2990.png" class="img" alt="データ">




#可視化
```py
def plot_decision_function(model):
    _x0 = np.linspace(-1.5,2.5,100)
    _x1 = np.linspace(-1.0,1.5,100)
    x0,x1 = np.meshgrid(_x0,_x1)
    X=np.c_[x0.ravel(),x1.ravel()]
    y_pred=model.predict(X).reshape(x0.shape)
    y_decision=model.decision_function(X).reshape(x0.shape)
    plt.contourf(x0,x1,y_pred,cmap=plt.cm.brg,alpha=0.2)
    plt.contourf(x0,x1,y_decision,lavels=[y_decision.min(),0,y_decision.max()],alpha=0.3)
    
def plot_dataset(X,y):
    plt.plot(X[:,0][y==0],X[:,1][y==0],"bo",ms=15)
    plt.plot(X[:,0][y==1],X[:,1][y==1],"r^",ms=15)
    plt.xlabel("$x_1$",fontsize=20)
    plt.ylabel("$x_2$",fontsize=20,rotation=0)

plt.figure(figsize=(20,15))

for i,degree in enumerate([2,3,5,10]):
    poly_kernel_svm=Pipeline([
        ("scaler",StandardScaler()),
        ("svm",SVC(kernel="poly",degree=degree,coef0=1))
    ])
    poly_kernel_svm.fit(X,y)
    
    plt.subplot(221+i)
    plot_decision_function(poly_kernel_svm)
    plot_dataset(X,y)
    plt.title("d={}".format(degree),fontsize=30)
    
plt.show()
```

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/a2a8ead1-4ba7-8f10-e7b4-8fed5be44b20.png" class="img" alt="データ">

**3次以降の写像**はあまり変化がないことが読み取れる。

※参考資料　
https://www.slideshare.net/moa108/8-28571831