SVMの理論とPythonを使った実装方法について
こんにちは、Vet Analyticsでデータアナリストをしている富永です。
Vet Analyticsは獣医学に機械学習の知見を導入しようと日々奮闘しているデータサイエンス・エンジニアチームです! 東京大学本郷キャンパス付近でいつも活動しているので興味がありましたらtwitterアカウントから連絡してください。
前回はk-means法についての理論とpythonを使った実装方法について解説しました。 vetanalytics.hatenablog.com
今回はSVM(サポートベクトルマシン)の理論と実装方法について説明していきたいと思います!
SVM(サポートベクトルマシン)とは
SVM(サポートベクトルマシン)はかなりよく見る機械学習のアルゴリズムの1つで機械学習初心者ならば必ずおさえておきたい アルゴリズムの1つです。 SVMは乱暴にいうと「クラスター同士の真ん中に境界を引くアルゴリズム」のことです。
上のように2つのクラスターがある時直感的には一本の境界が引けそうですよね? でもその一本はどのようにして決めますか??
明確な定義がないと境界線が定まらないのです!
そこでSVMではこの境界の定義を 「その境界に一番近い点との距離の最大化」としました。
この境界線と直交するようなベクトル をwとすると この2つの点を通るような直線は
となるので、この2つの式から
これの両辺をベクトル の長さで割ると
となり、これは左辺が2つの境界線の距離を表しているので右辺を最大化すればいいことがわかりますね。 これは、
を最小化する問題と同値なので、 誤分類によるペナルティをpとすると 最小化すべき問題は
となります。(ここでCは定数) これを最小化することがSVMの1番の目標となるわけです。この問題をPythonを使って実装していきたいと思います。
SVMのpythonでの実装方法
今回はSVMをPythonモジュールのScikit-learnを用いて実装していきたいと思います。 まずは例によってサンプルデータの作成をしていきます。
%matplotlib inline from sklearn.datasets import make_blobs import matplotlib.pyplot as plt from sklearn.svm import SVC x_train,y_train = make_blobs(n_samples=200, #plotするサンプル数 n_features=2, #特徴量(2次元) centers=4, #クラスターの数 cluster_std=0.4, #クラスターごとの標準偏差 shuffle=True, random_state=0) x_test,y_test = make_blobs(n_samples=300, #plotするサンプル数 n_features=2, #特徴量(2次元) centers=4, #クラスターの数 cluster_std=0.8, #クラスターごとの標準偏差 shuffle=True, random_state=0)
この時にrandom_stateの値をtrainとtestで変えると予測モデルが使えなくなるので注意してください。 このコードによって生成されたサンプルデータをplotしていきます。
plt.scatter(x_train[:,0], x_train[:,1], c="red", marker="o", s=40) plt.tight_layout() plt.show() plt.scatter(x_test[:,0], x_test[:,1], c="green", marker="o", s=40) plt.tight_layout() plt.show()
次にtrainデータを用いて予測モデルの訓練と予測の実行を行っていきたいと思います。
svm = SVC(kernel="linear", C=1.0, random_state=0) svm.fit(x_train,y_train) predict = svm.predict(x_test)
この時Cがペナルティの許容度です。(前章参照) これで予測完了です。予測モデルの分類がうまくいっているかどうかを確かめてみましょう
plt.scatter(x_test[predict==0,0], x_test[predict==0,1], s=40, c="red", marker="o", label="1") plt.scatter(x_test[predict==1,0], x_test[predict==1,1], s=40, c="green", marker="o", label="2") plt.scatter(x_test[predict==2,0], x_test[predict==2,1], s=40, c="blue", marker="o", label="3") plt.scatter(x_test[predict==3,0], x_test[predict==3,1], s=40, c="yellow", marker="o", label="4") plt.legend(scatterpoints=1) plt.tight_layout() plt.show()
予測モデルが正しくクラスターを分類できていることがわかります。
この予測はデータセットの形状からも納得できる結果だと思います。 しかし、訓練データと予測データの形状が異なる場合はどうなるのでしょうか?
SVMの予測失敗例
例えば、
のような直感的にもデータの分布が異なる場合について予測モデルを組み立てるとどうなるのでしょうか?
これに対して先ほどのように予測モデルを立てると 全く予測できていないことがわかります
このように訓練データに対して予測データが異なると対応できないのが教師あり学習の弱いところです。 テストデータが学習時と似通っているほど精度が高くなります。
これは多くの機械学習プロジェクトで障壁となっている問題の1つです。 数多くのプロジェクトがこの障壁にぶつかり頓挫しました(笑) 次回以降にそれらのプロジェクトにも触れられたらと思います!
次回はロジスティック回帰について書きます。
Vet Analyticsは様々な方のコンタクトを歓迎しています!DMへのご連絡をお待ちしております!