線形サポートベクトルマシン (2)

[昨日](http://qiita.com/ynakayama/items/d204e9d9d4a18ab13a39)は[サポートベクトルマシン](http://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%83%99%E3%82%AF%E3%82%BF%E3%83%BC%E3%83%9E%E3%82%B7%E3%83%B3)の分類境界において最大のマージンを求める式を説明しました。

scikit-learn には機械学習のためのさまざまなアルゴリズムが実装されています。たとえば[教師あり学習のアルゴリズムの一覧](http://scikit-learn.org/stable/supervised_learning.html)を見るだけでも多種多様なものがあり、サポートベクトルマシンの実装だけでも分類、回帰、密度推定などと豊富です。

Support Vector Machines
http://scikit-learn.org/stable/modules/svm.html

線形サポートベクトルマシンは特徴空間 Φ(x) において線形分離可能であることを仮定し、得られる SVM は入力空間 x において訓練データを完全に分離し、負例を 0 、正例を 1 とした二値のクラス (scikit-learn においてはラベル) にします。

SVM に代表される教師あり学習では、教師データとして使われる情報をトレーニングデータ、実際に分類される情報をテストデータと呼びます。

実際に SVM ライブラリで分類をしてみましょう。

```py3
from sklearn import svm
X = [[0, 0], [1, 1]]
y = [0, 1]
clf = svm.SVC()
clf.fit(X, y) # トレーニング

# テスト
clf.predict([[0., 2.]])
# => array([1])
clf.predict([[0., 0.]])
# => array([0])
clf.predict([[1., 0.]])
# => array([1])
clf.predict([[0., 1.]])
# => array([1])
```

### 多クラス分類

線形サポートベクトルマシンは多クラス分類において 1 対他方式を採用します。これは多クラス SVM において最もよく用いられる方法で K 個のクラスがあるときにあるクラス Ck に属するデータを正例、それ以外のデータを負例として K 個の別々の SVM yk(x) を学習します。

```py3
X = [[0], [1], [2], [3]]
Y = [0, 1, 2, 3]
lin_clf.fit(X, Y)
dec = lin_clf.decision_function([[1]])
dec.shape
# => (1, 4)
```

### サンプルデータセットによる分類

load_digits メソッドで読んだデータセットを train_test_split メソッドでトレーニングとテストデータに分割します。分割比率は 3:1 です。

```py3
from sklearn.datasets import load_digits
from sklearn.cross_validation import train_test_split
from sklearn.svm import LinearSVC
digits = load_digits(2)
data_train, data_test, label_train, label_test = train_test_split(digits.data, digits.target)

print (data_train)
# トレーニング用のデータ
#[[  0.   0.   0. ...,  16.   7.   0.]
# [  0.   0.   2. ...,   1.   0.   0.]
# [  0.   0.   0. ...,  16.   0.   0.]
# ..., 
# [  0.   0.   0. ...,  16.   1.   0.]
# [  0.   0.   2. ...,  16.  10.   3.]
# [  0.   0.   5. ...,   8.   0.   0.]]

print (label_train)
# データに対するラベル、正例が 1 で負例が 0 となる
#[1 0 1 1 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 0 1 0 0 0 0 1 1 1 1 0 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 0 1 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 1 1 0 1 0 1 1 0 1 1 0 0 1 0 1 1 0 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 1 1 0 0 0 1 1 1 1 0]

estimator = LinearSVC(C=1.0)
# トレーニングデータで線形サポートベクトルマシンを訓練する
estimator.fit(data_train, label_train)

# テストデータを分類する
estimator.predict(data_test)
# => [0 0 0 1 0 0 0 1 0 0 1 1 0 1 1 0 1 1 1 1 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 0 0 0 1 1 1 0 1 1 1 0 0 1 0 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 1 0 0]
# テストデータに対する「予測されたラベル (= クラス)」が返る
```

分類データの評価メトリクス、正解率を算出することもできます。またビルドインされたいくつかのカーネル関数と、それ以外に独自のカーネル関数を定義することができます。詳しくは[リファレンス](http://scikit-learn.org/stable/model_selection.html)を参照すると良いでしょう。

## 考察

駆け足で説明しましたが、複雑なサポートベクトルマシンの諸実装を scikit-learn ライブラリを用いることで実現できることがわかりました。複雑な計算理論についてはできるだけよくテストされたライブラリを用いて誤計算を防ぐことが大切です。また背景にある理論への理解も同時に必要です。