本文へスキップ
ひもとくAI

サポートベクターマシン:一番太い道と、カーネル法

レッスン 2/7

サポートベクターマシン:一番太い道を通す

境界線は、1本とは限らない

2つのグループを直線で分けるとき、きれいに分けられる直線は、たいてい何本もあります。ロジスティック回帰(第5章)は、確率の罰(交差エントロピー)が一番小さくなる直線を選びました。

サポートベクターマシン(SVM)は、別の考え方で直線を選びます。「2つのグループの間に、できるだけ太い道 を通し、その道の真ん中を境界にする」という考え方です。

特徴量1特徴量2-1012345-2024
  • グループ0
  • グループ1
  • サポートベクター(道の端に接する点)
左下のグループ0(○、20点)と右上のグループ1(■、20点)。2つのグループの間に、右下がりの実線(境界)と、その両側に平行な2本の破線(道の端)がある。道の端の破線にちょうど接している3つの点(★)がサポートベクターで、グループ0の1点(1.33と0.59)と、グループ1の2点(1.84と2.6、3.25と1.38)

実線が境界、2本の破線が道の両端です。道の幅(境界から道の端までの距離)を マージン と呼び、SVMは マージンが一番大きくなる境界 を選びます(マージン最大化)。この例では、道の幅(両端の間)は1.855でした。

サポートベクター:境界を決める、少数の点

道の端にちょうど接している点(★の3点)を、サポートベクター と呼びます。境界は、この3点だけで決まります。道から遠い点を動かしたり取り除いたりしても、道の幅が変わらない限り、境界は変わりません。

太い道を通すのは、新しいデータが少しずれた位置に来ても、正しい側に入りやすくするためです。境界がどちらかのグループのすぐそばを通っていると、そのグループの新しいデータが、少しずれただけで反対側に入ってしまいます。

ソフトマージンと、カーネル法

はみ出しを少し許す:ソフトマージンと C

現実のデータでは、2つのグループが少し混ざり合っていて、どんな直線でもきれいに分けられないことがよくあります。そこで、「道の中や反対側に、少しはみ出す点があってもよい。ただし、はみ出した分だけ罰を与える」と考えます。これを ソフトマージン と呼びます(はみ出しを許さない場合は ハードマージン)。点ごとの「はみ出した量」を表す数を スラック変数 と呼び、SVMは「道の幅を広くすること」と「スラック変数の合計を小さくすること」のバランスをとります。

はみ出しへの罰の重さを決めるのが、ハイパーパラメータ C です。前のスライドのデータで、C を変えました。

C道の幅サポートベクターの数訓練データの正解率
0.01(はみ出しに甘い)4.94523個1.0
11.8553個1.0
100(はみ出しに厳しい)1.8553個1.0
  • C が小さい: はみ出しの罰が軽いので、多くの点が道の中に入るのを許して、太い道 を通します。道の中や端にある23個の点が、すべてサポートベクターになりました
  • C が大きい: はみ出しを強く嫌うので、道は細くなります。このデータはもともときれいに分けられるので、C = 1 と C = 100 は同じ結果になりました

C が大きいほど訓練データに合わせようとして過学習しやすく、小さいほど大まかな境界になります。第8章の 正則化 の強さと同じ役割で、交差検証で選びます。

直線では分けられないデータ:同心円

内側の円と、それを囲む外側の輪の、2つのグループがあるデータ(300点)を考えます。どんな直線を引いても、内側と外側は分けられません。実際、テストデータ(90点)の正解率は、線形SVMで0.411、ロジスティック回帰でも0.411で、半分も当たりませんでした(2つのグループを当て推量しても0.5です)。

xy-101-101
  • 外側の輪
  • 内側の円
同心円のデータ(80点を表示)。内側の円(■)は、中心から半径約0.7までの範囲に集まっている。外側の輪(○)は、中心から半径約0.8〜1.2の範囲に、ぐるりと並んでいる。2つのグループの間に、半径0.75の点線の円を引くと、きれいに分けられる

特徴量を足すと、直線(平面)で分けられる

このデータは、「中心からの距離」を見れば分けられそうです。そこで、新しい特徴量 x2+y2x^2 + y^2(中心からの距離の2乗)を足しました。表示した80点では、内側の円の x2+y2x^2 + y^2 は最大0.479、外側の輪は最小0.65で、この特徴量だけで分かれています。特徴量を (x,y,x2+y2)(x, y, x^2 + y^2) の3つにして線形SVMを使うと、テストデータの正解率は 1.0 になりました。

2次元では直線で分けられないデータも、特徴量を足して高い次元に移すと、平らな面で分けられることがあります。

カーネル法:特徴量を作らずに、高い次元で分ける

どんな特徴量を足せばよいかは、ふつう分かりません。SVMでは、カーネル関数 という「2つの点がどれくらい似ているか」を測る式を使うと、実際に特徴量を作らなくても、高い次元(場合によっては無限の次元)に移して分けたのと同じ計算ができます。これを カーネル法(カーネルトリック)と呼びます。

よく使われる RBFカーネル(ガウスカーネル)は、「近い点ほど似ている」とする、距離にもとづくカーネルです。同心円のデータで、RBFカーネルのSVMは、特徴量を自分で足さなくても、テストデータの正解率 1.0 になりました。

RBFカーネルには、「どれくらい近ければ似ているとするか」を決める gamma というハイパーパラメータがあります。gamma が大きいほど、すぐ近くの点しか似ていないとみなすので、境界が細かく曲がり、過学習しやすくなります(このデータでは gamma = 100 で、訓練1.000、テスト0.989に下がりました)。

PythonでSVMを使う、よくある誤解と振り返り

from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

linear = make_pipeline(StandardScaler(), SVC(kernel="linear", C=1.0))     # 線形SVM
rbf = make_pipeline(StandardScaler(), SVC(kernel="rbf", C=1.0, gamma="scale"))   # RBFカーネル
rbf.fit(X_train, y_train)
print(rbf.score(X_test, y_test))
print(len(rbf[-1].support_))       # サポートベクターの数
  • SVMも距離(道の幅)を使うので、k近傍法と同じく 標準化してから 使います
  • gamma="scale" は、特徴量の数とばらつきから gamma を自動で決める、scikit-learn の既定の設定です
  • 3クラス以上でも、2クラスの分類を組み合わせて使えます(scikit-learn が自動で行います)
  • 数値を予測する回帰には、同じ考え方の SVR(サポートベクター回帰)があります

ほかのモデルと比べる

第9章の乳がんの診断データと、手書き数字のデータで比べました(テストデータの正解率、どれも標準化あり)。

ロジスティック回帰k近傍法(k=5)線形SVMRBFカーネルのSVM
乳がん0.9770.9590.9590.977
手書き数字0.9610.9700.9700.985

手書き数字では、RBFカーネルのSVMが一番高くなりました。ニューラルネットワークが広まる前は、画像の分類でも、SVMがよく使われていました。一方、SVMはデータの数の2乗から3乗に比例して学習の時間が増えるので、何十万件もあるデータには向きません。

よくある誤解

  • 「SVMは、すべての訓練データを使って境界を決める」: 境界を決めるのは、道の端や道の中にあるサポートベクターだけです
  • 「C は大きいほどよい」: C が大きいと、はみ出しを許さず訓練データに合わせすぎて、過学習しやすくなります
  • 「カーネル法は、特徴量を実際にたくさん作って計算している」: 高い次元に移したのと同じ結果を、2点の「似ている度合い」だけで計算するのが、カーネル法の工夫です

振り返り

  • SVMは、2つのグループの間に一番太い道(マージンが最大の道)を通し、その真ん中を境界にする。境界は、サポートベクターだけで決まる
  • ソフトマージンは、はみ出しを罰付きで許す。C は、はみ出しへの罰の重さ(正則化の強さと同じ役割)
  • カーネル法は、特徴量を作らずに高い次元で分けたのと同じ計算をする。RBFカーネルは距離にもとづく

演習

演習を読み込んでいます…