旅行好きなソフトエンジニアの備忘録

プログラミングや技術関連のメモを始めました

【異常検知】 One class SVMによる外れ値検知

外れ値検出手法の一つであるOne class SVMを試したのでメモします。

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm

np.random.seed(42)

# Generate train data
X = 0.3 * np.random.randn(100, 2)

# fit the model
clf = svm.OneClassSVM(nu=0.1, kernel='rbf', gamma='auto')
clf.fit(X)

# Generate some abnormal novel observations
ANOMALY_DATA_COUNT = 20
X_outliers = np.random.uniform(low=-4, high=4, size=(ANOMALY_DATA_COUNT, 2))
X = np.r_[X + 2, X - 2, X_outliers]

y_pred = clf.predict(X)
# 正常を1、異常を-1と判定するようです
ANOMALY_DATA = -1
predicted_outlier_index = np.where(y_pred == ANOMALY_DATA)
predicted_outlier = X[predicted_outlier_index]

# plot the level sets of the decision function
xx, yy = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.title("One Class SVM")
plt.contourf(xx, yy, Z, cmap=plt.cm.Blues_r)

a = plt.scatter(X[:200, 0], X[:200, 1], c='yellow',
                edgecolor='k', s=30, marker='o')
b = plt.scatter(X[200:, 0], X[200:, 1], c='red',
                edgecolor='k', s=30, marker='o')
c = plt.scatter(predicted_outlier[:, 0], predicted_outlier[:, 1], c='blue',
                edgecolor='k', s=10, marker='x')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([a, b, c],
           ["normal observations",
            "abnormal observations",
            "observations predicted as abnormal"],
           loc="upper left", prop={'size': 12})
plt.show()

ハイパーパラメータにnuというやつがいるのですが、これは0 \leq nu \leq 1の範囲を取り、異常データ割合の上限を教えることができるようです。

qiita.com

今回は220個のデータの内20個を異常データとしているので、nu=0.1としました。
f:id:ni4muraano:20171113225032p:plain 試しにnu=0.5とすると、確かに異常と見なされるデータ数が増えています。
f:id:ni4muraano:20171113225045p:plain