まとめ- One-Class SVM は正常データのみで学習し、その分布の「境界」から外れたデータを異常として検出する。
- カーネルトリックにより非線形な正常領域も捉えられ、高次元データにも適用可能。
- scikit-learn の
OneClassSVM で実装し、nu パラメータで異常の許容割合を制御する。
- SVM — カーネルトリックとマージンの概念を先に理解すると効果的です
直感
#
工場の正常な製品データは大量にあるが、不良品データはほとんどない。One-Class SVM は「正常データを囲む最小の超球」を学習し、その外に出たデータを異常と判定する。Isolation Forest が「異常を直接探す」のに対し、One-Class SVM は「正常を定義して、そこから外れたものを検出する」アプローチ。
詳細な解説
#
ライブラリとデータ
#
1
2
3
4
5
6
7
8
| import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import OneClassSVM
from sklearn.datasets import make_blobs
np.random.seed(42)
X_train, _ = make_blobs(n_samples=300, centers=1, cluster_std=0.5, center_box=(0, 0))
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
|
モデル学習と予測
#
1
2
3
4
5
6
7
8
| model = OneClassSVM(kernel="rbf", gamma="scale", nu=0.05)
model.fit(X_train)
y_pred_train = model.predict(X_train)
y_pred_outliers = model.predict(X_outliers)
print(f"正常データの異常判定率: {(y_pred_train == -1).mean():.2%}")
print(f"外れ値の異常検出率: {(y_pred_outliers == -1).mean():.2%}")
|
決定境界の可視化
#
1
2
3
4
5
6
7
8
9
10
11
| xx, yy = np.meshgrid(np.linspace(-5, 5, 300), np.linspace(-5, 5, 300))
Z = model.decision_function(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), 0, 7), cmap="Blues_r", alpha=0.5)
plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors="red")
plt.scatter(X_train[:, 0], X_train[:, 1], c="blue", s=10, label="Normal")
plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c="red", s=30, marker="x", label="Outlier")
plt.legend()
plt.title("One-Class SVM Decision Boundary")
plt.show()
|
主要パラメータ
#
| パラメータ | 意味 | 推奨 |
|---|
nu | 異常の上限割合 | 0.01–0.1(事前知識に基づく) |
kernel | カーネル関数 | “rbf”(非線形に強い) |
gamma | RBF カーネルの幅 | “scale” or “auto” |
Isolation Forest との比較
#
| 手法 | アプローチ | 高次元耐性 | 計算速度 | パラメータ感度 |
|---|
| One-Class SVM | 正常境界を学習 | ○ | 遅い(O(n²)) | 高い |
| Isolation Forest | 異常を直接分離 | ○ | 速い(O(n log n)) | 低い |