<SVM> サポートベクタマシン自主勉強(1):方針
ちょっと間が空いてしまいましたが機械学習のエントリとなります。前回最後にちらっとお話ししたのですが、サポートベクタマシン(SVM)に足を突っ込んでみたいと思っています。
SVMのコーディングが自力でできない問題
ただ、このSVMは何回か挑戦して失敗している経緯があります。前回のようにはじパタ本だけでは私のレベルでクリアができない代物となります。そこではじパタと合わせて、「異常検知と変化検知」の内容と相互補完してみています。
- 作者: 井手剛,杉山将
- 出版社/メーカー: 講談社
- 発売日: 2015/08/08
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
そこでやっと、SVMの概要について理解した。。。。つもりでした。しかしながらいざこれをスクリプトに落とそうとするとどう書いていいのかわからない。つまりロジックがわかったつもりでも、実行に移すとなるとどうしていいのかわからなくなってしまいました。
頼るべきはGoogle先生と集合知
しかしながらもうすでに歴史のあるこの分野では検索してしまえばいくらでもコードが出てきます。今回は以下のサイトさまのコードを拝借してやはりアヤメデータを使った分類を行ってみました。
こちらのコードは の線形で分離をして を1, -1とわけています。アヤメデータもとりあえず、3種のうちの最初の1種を1, その他を-1としてインプットするコードに改造をしてみました。 その結果が以下となります。
おぉ、なんとなく分類する線が学習を経るごとに赤と緑の間にはいっていきますね。赤が1としたアヤメデータなのでうまくいっているようです。
ここからスタート
SVMについてまとめることはたくさんありそうです。ラグランジュ乗数法、正則化、双対問題、KKT条件、カーネルトリック。数学的要素が多くどこまでカバーできるかわかりませんが、まず次回はこのスクリプトについて解いていくことから初めてみようかと思います。正直きちんと着地できるかまだ不明瞭ではあります。
コード
Jupyter Notebookで実行しています。
import sys import numpy as np from sklearn import datasets import itertools import matplotlib.pyplot as plt #inline pyplot from matplotlib import animation from IPython.display import HTML iris = datasets.load_iris() features = iris.data feature_names = iris.feature_names targets = iris.target class SVM(): def __init__(self, v1=0, v2=2, t=0): self.X = np.array([features.T[v1], features.T[v2]]).T self.T = np.array([1 if i==t else -1 for i in targets]) self.N = self.X.shape[0] self.d = self.X.shape[1] self.alpha = np.zeros(self.N) self.beta = 1.0 self.eta_al = 0.0001 self.eta_be = 0.1 self.v = [v1, v2] def test(self): print(self.X.shape) print(self.T) print(self.N) print(self.alpha) def plot_map(self, w, b): plt.subplot(1, 1, 1) seq = np.arange(4.0, 8.0, 0.02) plt.xlabel(feature_names[self.v[0]]) plt.ylabel(feature_names[self.v[1]]) plt.xlim(4, 8) plt.ylim(0, 8) plt.plot(seq, -(w[0] * seq + b) / w[1], 'k-') #plt.autoscale() plt.grid() for t, marker, c in zip(range(3), '>ox', 'rgb'): #print(self.X[self.T==1], 0) #print(self.T) plt.scatter( features[targets == t, self.v[0]], features[targets == t, self.v[1]], marker=marker, c=c, ) #print(linear_pro(w, np.array([1.,1.,1.]))) plt.show() def rtin(self, show=False): k_w = np.array([-100.0, -100.0]) k_b = -100.0 value = [] for _itr in range(1000): for i in range(self.N): self.delta = 1 - (self.T[i] * self.X[i]).dot(self.alpha * self.T * self.X.T).sum() - self.beta * self.T[i] * self.alpha.dot(self.T) self.alpha[i] += self.eta_al * self.delta for i in range(self.N): self.beta += self.eta_be * self.alpha.dot(self.T) ** 2 / 2 index = self.alpha > 0 w = (self.alpha * self.T).T.dot(self.X) b = (self.T[index] - self.X[index].dot(w)).mean() value.append([w, b]) if (np.power(np.array([k_w - w]), 2) < 0.00001).all() and (k_b - b) ** 2 < 0.00001: print(_itr) break if _itr % 10 == 0 and show: self.plot_map(w, b) k_w = w k_b = b return value svm = SVM(t=0) _ = svm.rtin(True)