Pythonの異常検知ライブラリPyOD(その1)

昨年より仕事のデータ解析のためにPythonプログラムを書いている。昨年はデータ前処理と作図が殆どだったが、今年から統計手法のライブラリを使い始めた。最近、異常検知のためのPythonライブラリを探していたら、PyODというライブラリを見つけた。PyODは、多変量の観測データの異常検知が行えるライブラリで、提供されている手法は、統計モデルや機械学習など20に及ぶ。多様な異常検知手法を統一したインタフェースで適用して結果を相互比較できるという優れものである。リリースされてから日が浅く、日本語の解説記事はまだ殆どないようである。

今回は、英語のチュートリアル記事を参考に、PyODのデータ生成機能で作った人工データを用いて、教師なし学習の8つの手法を適用してみた。尚、PyODライブラリ利用のためにはインストールが必要です。

【ライブラリのインポート】PyODライブラリは、各手法毎にインポートする。

import numpy as np
import pandas as pd
import matplotlib. pyplot as plt
from matplotlib import rcParams
rcParams['font.family'] = 'MS Gothic'
from pyod.utils.data import generate_data, get_outliers_inliers
# import PyOD library models
from pyod.models.abod import ABOD
from pyod.models.cblof import CBLOF
from pyod.models.feature_bagging import FeatureBagging
from pyod.models.hbos import HBOS
from pyod.models.iforest import IForest
from pyod.models.knn import KNN
from pyod.models.lof import LOF
from pyod.models.pca import PCA

【人工データの生成】変数の数、異常データの出現割合(ここではデフォルト0.1)を指定して、分析用の人工データ(観測データ、正常/異常データ)を生成することができる。

# generate random data with two features
X_train, Y_train, X_test, Y_test = generate_data(n_train=200, n_test=100, n_features=2)

# plot training data
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(X_train[:,0], label='Col 1')
ax1.plot(X_train[:,1], label='Col 2')
ax1.set_title('PyOD Training Data')
ax1.legend()
plt. show()

【手法の記述】分析に用いる手法を辞書型変数として記述する。

# Define eight outlier detection tools to be compared
random_state = np.random.RandomState(42)
outliers_fraction = 0.05
classifiers = {
    'Angle-based Outlier Detector (ABOD)': ABOD(contamination=outliers_fraction),
    'Principal Component Analysis (PCA)': PCA(contamination=outliers_fraction),
    'Cluster-based Local Outlier Factor(CBLOF)': CBLOF(contamination=outliers_fraction,check_estimator=False,random_state=random_state),
    'Feature Bagging': FeatureBagging(LOF(n_neighbors=35), contamination=outliers_fraction,check_estimator=False,random_state=random_state),
    'Histogram-base Outlier Detection (HBOS)': HBOS(contamination=outliers_fraction),
    'Isolation Forest': IForest(contamination=outliers_fraction,random_state=random_state),
    'K Nearest Neighbors (KNN)': KNN(contamination=outliers_fraction),
}

【各手法のデータへの当てはめと異常判定】ここでは辞書リストの要素についてのループを組んでいる。

# Loop for outlier detection tools
for i, (clf_name, clf) in enumerate(classifiers.items()):
    # fit the dataset to the model
    clf.fit(X_train)
    # predict raw anomaly score
    scores_pred = clf.decision_function(X_test)
    # prediction of a datapoint category outlier or inlier
    y_pred = clf.predict(X_test)
    # prediciton error rate
    y_ErrRate = (y_pred != Y_test).sum() / len(Y_test)
    # plot scores_pred
    x = np.arange(100)
    y1 = scores_pred
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax1.plot(x,y1, 'k-', label='Anomaly Score')
    ax1.plot(x[y_pred==1], y1[y_pred==1],'ro', label='Outlier')
    ax1.set_title('PyOD Result: ' +clf_name + ' Error Rate: '+str(round(y_ErrRate,3)))
    ax1.legend()
    plt.show()