One-Class SVM

2.9.4

One-Class SVM

最終更新 2026-03-03 読了時間 2 分
まとめ
  • 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”(非線形に強い)
gammaRBF カーネルの幅“scale” or “auto”

Isolation Forest との比較 #

手法アプローチ高次元耐性計算速度パラメータ感度
One-Class SVM正常境界を学習遅い(O(n²))高い
Isolation Forest異常を直接分離速い(O(n log n))低い
  • Isolation Forest — ツリーベースの異常検知
  • SVM — 二値分類版の SVM
  • DBSCAN — 密度ベースの外れ値検出