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

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

今回は、英語のチュートリアル記事を参考に、PyODのデータ生成機能で作った人工データを用いて、教師なし学習の8つの手法を適用してみた。尚、PyODライブラリ利用のためにはインストールが必要です。Anacondaの場合は、ターミナルから「conda install -c conda-forge 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.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,X_test,Y_train,Y_test=generate_data(n_train=200,n_test=100,n_features=2,behaviour='new')

# 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),
    '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()