サポートベクターマシン(SVM)とは?〜基本からPython実装まで〜
この記事はこんな人にオススメです
  • サポートベクターマシンSVMについて詳しく知りたい方
  • 機械学習で分類や回帰などをやってみたい方
  • SVMをパパッと実装してみたい方

こんにちは.
今日は機械学習の一つであるサポートベクターマシンについて書いていきます.
(ここでは,線形SVMに限って説明していきます)
分類とか回帰などの問題を解くときに使われる手法で,1960年代からある手法です.
ここでは,サポートベクターマシンがどのようなものなのかを説明して,実際にPythonを使ってプログラムを組んでいきます.

サポートベクターマシンSVMとは

話を簡単にするために,2次元の2つのクラスに分類する絵で説明します.
(線形サポートベクターマシンと言います)

SVMとは,クラスを明確に分ける境界線を引くための手法です.
上の図の例では,のクラスを明確に分ける境界線を引いてますね.

ペンのすけ

明確に,赤と青の場所の決めているんだね!これで,もし赤か青か分からないデータが来たときには,どっちのクラスに属するか一目瞭然なんだね


ここで,上の特徴量としては2つ(2次元)なので「線」を引きますが,3次元になると「面」を引きます.
数学的に線形の場合,「直線」や「平面」の一般化として超平面という概念があるために,n次元(任意の次元)に対して求まる境界を超平面と言います.

特徴量の次元と線形SVMの境界の種類について
特徴量の次元 境界の種類
2次元 直線
3次元 平面
n次元 超平面

超平面の定め方はマージン最大化

例えば,上の2クラスのデータを分離する境界線の引き方は無限にあると思いますが,SVMでは「マージン最大化」という方法で線を引きます.

マージンというのは「余白」を意味する言葉ですが,境界からもっとも近いベクトル(特徴量も持った点)との距離を表します.
上の例の場合は,のクラスからもっとも近いベクトルを2点ずつ選んで,そのマージンを最大にするように線を引いてます.
この選ばれたベクトルをサポートベクトルと呼びます.

つまり,マージンを最大化することは,赤のクラスからも青のクラスからももっとも遠い境界を引くということを意味しています.

一度境界を定めると,サポートベクターマシンを使った「分類器」が完成します.
この分類器に対して,特徴量1と2を持つ新しいデータを入力したときに,赤のクラス青のクラスのどちらかに属するか判別することが可能です.

しっかりとした理論的な説明を知りたい人は,以下をご覧ください.

必要な前提:線形分離可能であること

SVMでマージン最大化するにあたって,必要な前提があります.
それは,データが線形分離可能であることです.
すなわち,二つのクラス(例だとか)を持つデータでなければいけません.

メリット:計算コストが小さい

このSVMには計算コストが小さいというメリットがあります.
線形分離可能であるデータに対して,境界を引くときに必要なデータはサポートベクトルだけだからです.
サポートベクトル以外の点は,境界を引くのに関係がありません.
(すなわち,計算しなくても良い)

理論的な解説はスライド資料へ

Pythonプログラムについて

今回は,Pythonを使ってSVMの実装をしていきます.
分類するのに使うデータはおいらが研究で使用している脳波データです.

プログラムについて

使うデータについて

teach.txtとtest.txtのファイルの構造は以下のようになっています.

teach.txtとtest.txtのファイル構造
No 特徴量1 特徴量2 特徴量3 特徴量4 クラス(0 or 1)
1 〇〇 〇〇 〇〇 〇〇 0
2 〇〇 〇〇 〇〇 〇〇 0
・・・ ・・・ ・・・ ・・・ ・・・ ・・・
61 〇〇 〇〇 〇〇 〇〇 1
62 〇〇 〇〇 〇〇 〇〇 1
・・・ ・・・ ・・・ ・・・ ・・・ ・・・

0列目は,ベクトル個数のナンバリング(No)です.
1列目から4列目までは,それぞれの特徴量を表すデータが入ってます.
スカラー量ですね.

最後の5列目は,その状態を0か1かで格納してます.
ここでは,「0:リラックス時の脳波データ」,「1:ストレス時の脳波データ」という形で状態を保持しています.

おいらの場合は,脳波の時系列のデータからある処理を行って,特徴量を4つ抜き出して,リラックスかストレスかの状態分けをしてます.
ここの特徴量の設計の部分は人間はやらないといけない部分です.

例えば,上の特徴量1から3を使ったデータを可視化すると以下のようになります.
(記載しているプログラムも,特徴量1~3を使ってSVMを回しています)

データの抜き出しと変数への格納

上のデータの抜き出しと格納は以下のように行ってます.

p_teach[ : , 1:4 ]と書くと,1列目から3列目までが抜き出されます.
これをベクトルの変数Xに格納してます.
(特徴量ですね)
3列目までなので,気をつけてください.

クラスの状態(0 or 1)は,変数yに格納です.
これは,5列目なので,p_teach[ : , 5]という風に書きます.
」がない場合,列指定になるので,これで,各ベクトルに対するクラスの指定ができました

testデータも同様に行います.

サポートベクターマシンは3行でかける

サポートベクターマシンSVMは,サイキットラーン(Scikit-learn)のライブラリを使います.
ここで,サイキットラーン(Scikit-learn)は機械学習をするときに,便利なライブラリで色々な機能が入っているのでオススメです.
Scikit-learnをお使いのパソコンに入れてください.
インストールが終わると,プログラムの初めに,以下の定義をしてください.
これでSVMが使えます.

SVMは,Scikit-learnを使用して,以下の3行で書くことができます.

ここで,svm.SVC(  )で,サポートベクターマシンによる分類器を呼び出して,clfという変数に一度格納しておきます.
内側のパラメータであるCとKernelはそれぞれ,ペナルティ寄与サポートベクターマシンのタイプです.

ペナルティ寄与Cとは,境界を決める時のペナルティの寄与の大きさです.
Cが大きいほど,誤認識された点へのペナルティが大きくなります.
(このへんは,ハードマージンという概念が必要ですが,話がややこしくなるので飛ばします.)
デフォルトの「C=1.0」でも十分分類できるので,取っ掛かりとしてはそれで大丈夫です.

「kernel=’linear’」は線形のサポートベクターマシンを利用するということです.
(他にも「kernel=’rbf’」という動径基底関数というものもあります.)

「clf.fit(X, y)」で,分類器に特徴量のデータとクラスの状態が渡され,境界を作ります.

最後に,「R = clf.predict(x_test)」で,テストデータを入れて,分類器が上手く機能しているか確認をしています.

詳しく知りたい方は,Scikit-learnのオフィシャルサイトへどうぞ

ではー!皆さんも楽しいSVMライフを!
SVMを実践に使いたい人へのオススメ図書です.