LoginSignup
12
16

More than 5 years have passed since last update.

scikit-learnのLOFでテストデータの判定をする

Posted at

scikit-learnでは外れ値検知の手法の1つであるLOF(Local Outlier Factor)が提供されていますが、versionが0.19以前ではテストデータに対する正常データ・異常データの判定ができませんでした。version0.20からテストデータに対する正常データ・異常データの判定機能が実装されましたので、そちらを紹介します。

使い方

One Class SVMのようなscikit-learnに実装されている外れ値検知の手法では、正常データが大多数であるような訓練データを与え、fitメソッドで学習をおこないます。学習済みのモデルのpredictメソッドを使うことで、テストデータが正常か異常かが判定されます。LOFを使う場合にも同様の流れになりますが、fitメソッドを使うときにちょっとだけ違いがあり、novelty=Trueという引数が必要になります。例えば、次のように訓練と予測をおこないます。

lof_ex.py
from sklearn.neighbors import LocalOutlierFactor

model = LocalOutlierFactor(n_neighbors=1,
                           novelty=True,
                           contamination=0.1)
model.fit(train_data) # train_dataは正常データが大多数であるような訓練データ
prediction = model.predict(test_data) # テストデータに対する予測
score = model.score_samples(test_data) # テストデータの異常度

使ってみる

人工的にデータを生成し、それらに対してLOFを適用していきたいと思います。
以下のような訓練データとテストデータを生成しました。緑が正常の訓練データ、オレンジが正常のテストデータ、赤が異常のテストデータになります。(手書き風のグラフはmatplotlibの機能を使っていて、自分の趣味です)。
lof_features.png

上記のデータを生成するコードは以下のとおりです。

データ生成
from sklearn.datasets import make_blobs

X, _ = make_blobs(n_features=2, centers=1, cluster_std=[1], random_state=0, n_samples=100)
test_normal = X[:4]
train = X[4:]
test_anomaly = np.array([[0, 0], [-2.5, 2], [5, 4], [-2, 7]])

さて、実際にこれらのデータに対して訓練と予測を適用してみます。

lof適用
model = LocalOutlierFactor(n_neighbors=2, novelty=True, contamination=0.1)
model.fit(train)
normal_result = model.predict(test_normal)
anomaly_result = model.predict(test_anomaly)

print("各正常データのスコア", normal_result)
print("各異常データのスコア", anomaly_result) 

# 次のように出力される
# 各正常データのスコア [1 1 1 1]
# 各異常データのスコア [-1 -1 -1 -1]

正常データに対しては1が出力され、異常データに対しては-1が出力されますが、きちんと正しい結果を得られていることがわかります。

12
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
16