サポートベクター マシンについて、改めて理解を深めてみる

サポートベクトルマシーンについて改めて理解する

サポートベクトルマシーンは
軽量なアルゴリズムとして、
用いられて居ます。

まずは、サポートベクトルマシンはそもそも
どの様にして生まれたのか、
用いる上での注意点は
どのあたりにあるのかについて、纏めたいと思います。

（あくまで、本記事は著者本人の理解であり、もしかしたら理解が間違っている
かも知れません。）

サポートベクトルマシンの特長

(1)ソフトマージンの考え方を用いることによって、
トレーニングデータセットのエラーを許容したこと。
ただし、下記の状態が存在していることが前提
Pr(test error) < Frequency(training error) + Confidence Interval 
つまり、テストデータの質が悪い（負例の割合が多い）場合には、
役に立たない。

(2)訓練データの件数が少ない場合には有効
大まかには数百件程度のデータ数でも有効
（ランダムフォレスト系は１０００件程度以上、NNは一般的には２万件以上）

(3)元々は２クラス(１VSその他)分類問題を解くために生み出された。
２クラス分類問題器を複数個用いることで多クラス分類問題を解く事になるが
多クラス分類問題を解く決定的な方法は存在しない（かも知れない）。

次に、サポートベクターマシンを使って

[iris データセット]
https://github.com/pandas-dev/pandas/blob/master/pandas/tests/data/iris.csv

ひとまずは、綺麗なiris データセットを扱ってみる。

まずは、線形関数を用いて
Iris setosa 
Iris versicolor 
Iris virginica 
を分類してみる。

```
svm = SVC(kernel='linear', C=1.0, random_state=1)
svm.fit(X_train_std, y_train)
y_combined = np.hstack((y_train,y_test))
X_combined_std = np.vstack((X_train_std,X_test_std))
plot_decision_regions(X_combined_std, y_combined, clf=svm)
```

![index.png](https://qiita-image-store.s3.amazonaws.com/0/301975/6eaa2285-7ba8-1f00-575a-9cd6cc3dfdbd.png)

Iris setosa ０
Iris versicolor １ 
Iris virginica ２

次に関数を線形関数からガウスカーネルSVMにかえてみよう

```
svm = SVC(kernel='rbf', C=1.0, random_state=1, gamma=1.0)
svm.fit(X_train_std, y_train)
y_combined = np.hstack((y_train,y_test))
X_combined_std = np.vstack((X_train_std,X_test_std))
plot_decision_regions(X_combined_std, y_combined, clf=svm)
```
![index2.png](https://qiita-image-store.s3.amazonaws.com/0/301975/4fa00883-c09b-9eb3-5878-f6aa550eb109.png)

この数式は

```math
\ k(x,y) = \phi(x)^i\phi(y)^j
```

ガウスカーネルSVMを用いて分類を行う場合には
<img width="187" alt="スクリーンショット 2018-10-18 15.01.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/301975/1b80e5bc-4e07-a0d0-8b9b-852d8b81d661.png">

```math
\gamma = \frac{1}{2\sigma^2}
```

を用いて上記数式を置き換えると

```math
\ k(x,y) = exp(\gamma||x^i - x^j||^2)
```

となり、r を最適化する事が重要だとわかる

無限個の ϕ1(x),ϕ2(x),⋯ を用いて、K(x,y) が構成さているが、無限個のϕには
無限の特徴が含まれているのでγの値を決めて仕舞えば、最適化が出来る事になる

上記の例では
γの値を１００に変更してみた。

```
svm = SVC(kernel='rbf', C=1.0, random_state=1, gamma=100.0)
svm.fit(X_train_std, y_train)
y_combined = np.hstack((y_train,y_test))
X_combined_std = np.vstack((X_train_std,X_test_std))
plot_decision_regions(X_combined_std, y_combined, clf=svm)
```

![index100.png](https://qiita-image-store.s3.amazonaws.com/0/301975/c7ce2981-d72a-ddbd-a66e-268d441e5b9a.png)

すると、適切に分類できることがわかる。
ただし、そもそもγの値をどの様に決めれば良いのかという問題が残る

そこで、グリッドサーチを用いて、最適なγの値を探してみる事にしたい。

```
param_grid = [
    {'gamma': [120.0, 110.0, 100.0, 90.0, 80.0, 70.0, 60.0, 50.0, 40.0, 20.0, 1.0], 'kernel': ['rbf']},
]

scores = ['accuracy', 'precision', 'recall']

for score in scores:
    clf = GridSearchCV(SVC(C=1), param_grid, cv=5, scoring=score, n_jobs=-1) 
    clf.fit(X_train, y_train)

    for params, mean_score, all_scores in clf.grid_scores_:
        print( mean_score / 2 * 100 , params)
               
```
結果
42.38095238095238 {'gamma': 120.0, 'kernel': 'rbf'}
42.38095238095238 {'gamma': 110.0, 'kernel': 'rbf'}
42.38095238095238 {'gamma': 100.0, 'kernel': 'rbf'}
42.857142857142854 {'gamma': 90.0, 'kernel': 'rbf'}
42.857142857142854 {'gamma': 80.0, 'kernel': 'rbf'}
42.857142857142854 {'gamma': 70.0, 'kernel': 'rbf'}
42.857142857142854 {'gamma': 60.0, 'kernel': 'rbf'}
43.333333333333336 {'gamma': 50.0, 'kernel': 'rbf'}
44.761904761904766 {'gamma': 40.0, 'kernel': 'rbf'}
47.61904761904761 {'gamma': 20.0, 'kernel': 'rbf'}
47.61904761904761 {'gamma': 1.0, 'kernel': 'rbf'}

カーネルがrbf の中では
結果としてスコアが高いのがγの値が90.0 であることがわかる

これにより、パラメータが90.0の時に最適化される事がわかる。
グリッドサーチによってハイパーパラメータを最適化してみた。

[gammna=90の場合]

```
svm = SVC(kernel='rbf', C=1.0, random_state=1, gamma=90.0)
svm.fit(X_train_std, y_train)
y_combined = np.hstack((y_train,y_test))
X_combined_std = np.vstack((X_train_std,X_test_std))
plot_decision_regions(X_combined_std, y_combined, clf=svm)
```

![index90.png](https://qiita-image-store.s3.amazonaws.com/0/301975/e0b090e0-0183-2c66-be47-4b7361d4e278.png)


＜参考＞
https://link.springer.com/content/pdf/10.1007/BF00994018.pdf

https://books.google.co.jp/books?id=r_JQDwAAQBAJ&printsec=frontcover&dq=Python