はじめに
サポートベクターマシン(SVM)は、分類と回帰に用いられる教師あり学習手法です。クラス間のマージン(余裕)を最大化する決定境界を求めることで、汎化性能の高い分類器を構築します。
カーネルトリックにより非線形な決定境界も学習でき、高次元・小〜中規模データで特に強力です。
線形SVM
ハードマージン
2クラスの学習データ \(\{(\mathbf{x}_i, y_i)\}_{i=1}^{n}\)(\(y_i \in \{-1, +1\}\))が線形分離可能な場合、決定境界は次の最適化問題で求まります。
\[\min_{\mathbf{w}, b} \frac{1}{2} \|\mathbf{w}\|^2 \tag{1}\]\[\text{subject to} \quad y_i(\mathbf{w} \cdot \mathbf{x}_i + b) \geq 1, \quad \forall i \tag{2}\]マージンの幅は \(2 / \|\mathbf{w}\|\) であり、\(\|\mathbf{w}\|\) を最小化することはマージンの最大化に等しいです。
ソフトマージン
線形分離不可能な場合、スラック変数 \(\xi_i \geq 0\) を導入します。
\[\min_{\mathbf{w}, b, \xi} \frac{1}{2} \|\mathbf{w}\|^2 + C \sum_{i=1}^{n} \xi_i \tag{3}\]\[\text{subject to} \quad y_i(\mathbf{w} \cdot \mathbf{x}_i + b) \geq 1 - \xi_i, \quad \xi_i \geq 0 \tag{4}\]\(C\) は正則化パラメータで、マージンの大きさと誤分類のトレードオフを制御します。
カーネルトリック
双対問題
ラグランジュ双対問題に変換すると、データは内積 \(\mathbf{x}_i \cdot \mathbf{x}_j\) のみを通じて現れます。
\[\max_{\alpha} \sum_{i=1}^{n} \alpha_i - \frac{1}{2} \sum_{i,j} \alpha_i \alpha_j y_i y_j (\mathbf{x}_i \cdot \mathbf{x}_j) \tag{5}\]\[\text{subject to} \quad 0 \leq \alpha_i \leq C, \quad \sum_{i=1}^{n} \alpha_i y_i = 0 \tag{6}\]カーネル関数
内積をカーネル関数 \(K(\mathbf{x}_i, \mathbf{x}_j) = \phi(\mathbf{x}_i) \cdot \phi(\mathbf{x}_j)\) で置き換えることで、明示的に高次元空間への写像 \(\phi\) を計算せずに非線形分類を実現します。
| カーネル | 定義 | 特徴 |
|---|---|---|
| 線形 | \(K(\mathbf{x}, \mathbf{y}) = \mathbf{x} \cdot \mathbf{y}\) | 線形分離可能なデータ |
| RBF(ガウス) | \(K(\mathbf{x}, \mathbf{y}) = \exp(-\gamma\|\mathbf{x}-\mathbf{y}\|^2)\) | 最も汎用的 |
| 多項式 | \(K(\mathbf{x}, \mathbf{y}) = (\gamma \mathbf{x} \cdot \mathbf{y} + r)^d\) | 特徴の交互作用 |
Python実装
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.datasets import make_moons, make_circles
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
# --- データ生成 ---
X, y = make_moons(n_samples=300, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# --- 各カーネルの比較 ---
kernels = ['linear', 'rbf', 'poly']
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
for ax, kernel in zip(axes, kernels):
clf = SVC(kernel=kernel, C=1.0, gamma='scale')
clf.fit(X_train, y_train)
acc = accuracy_score(y_test, clf.predict(X_test))
# 決定境界の描画
xx, yy = np.meshgrid(np.linspace(-3, 3, 200), np.linspace(-3, 3, 200))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
ax.contourf(xx, yy, Z, levels=[-1, 0, 1], alpha=0.2, colors=['blue', 'red'])
ax.contour(xx, yy, Z, levels=[-1, 0, 1], colors='k', linestyles=['--', '-', '--'])
ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='bwr', s=20, alpha=0.6)
# サポートベクターを強調
sv = clf.support_vectors_
ax.scatter(sv[:, 0], sv[:, 1], s=80, facecolors='none', edgecolors='k', linewidths=1.5)
ax.set_title(f'{kernel} (acc={acc:.3f})')
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
plt.tight_layout()
plt.show()
ハイパーパラメータ
C(正則化パラメータ)
- 大きいC: マージンが小さく、訓練データの誤分類を厳しく罰する → 過学習のリスク
- 小さいC: マージンが大きく、一部の誤分類を許容 → 未学習のリスク
gamma(RBFカーネル)
- 大きいgamma: 各サンプルの影響範囲が狭い → 複雑な決定境界、過学習のリスク
- 小さいgamma: 各サンプルの影響範囲が広い → 滑らかな決定境界
from sklearn.model_selection import GridSearchCV
param_grid = {'C': [0.1, 1, 10, 100], 'gamma': [1, 0.1, 0.01, 0.001]}
grid = GridSearchCV(SVC(kernel='rbf'), param_grid, cv=5, scoring='accuracy')
grid.fit(X_train, y_train)
print(f"Best params: {grid.best_params_}, Score: {grid.best_score_:.3f}")
SVMの利点と制約
| 利点 | 制約 |
|---|---|
| 高次元データに強い | 大規模データでは学習が遅い(\(O(n^2)\)〜\(O(n^3)\)) |
| カーネルで非線形対応 | 確率出力には追加処理が必要 |
| 過学習しにくい | 特徴量のスケーリングが必須 |
| サポートベクターのみで決定境界 | マルチクラスは間接的(OvOまたはOvR) |
関連記事
- ベイズ線形回帰の基礎 - 回帰問題へのベイズアプローチとSVR(サポートベクター回帰)の比較が有益です。
- ベイズ最適化の基礎とPython実装 - SVMのハイパーパラメータ(C, gamma)の自動チューニングに活用できます。
- クロスエントロピー法:モンテカルロ最適化の実践的手法 - 最適化の別のアプローチとして比較できます。
参考文献
- Vapnik, V. N. (1995). The Nature of Statistical Learning Theory. Springer.
- Cortes, C., & Vapnik, V. (1995). “Support-vector networks”. Machine Learning, 20(3), 273-297.
- scikit-learn SVM documentation