yoshikit1996’s diary

日々勉強したことの備忘録です。

ホテリング理論で異常検知

ホテリング理論によって外れ値を検知する方法について説明します.

ホテリング理論による外れ値検知とは,
各データに対する異常度を算出し,異常度が閾値を超えたら外れ値とみなすという方法です.

以下に,ホテリング理論によって外れ値検知を行うアルゴリズムを示します.

1. 正規分布

ホテリング理論は,データの分布として正規分布を仮定しています.なので,まず,実データが正規分布に従うかどうかを確かめます.実データが正規分布から著しく離れている場合,上手く外れ値検知できません.

2. 異常度

次に異常度a(x)を計算します.異常度は平均値からの距離のようなものです.
異常度は下記の式によって算出されます.xはデータ,μは平均値,ρの2乗は分散です.
f:id:yoshikit1996:20180622161528p:plain

3. 閾値の決定

ホテリング理論により,異常度はカイ2乗分布に従うことが証明されています.
手順2によって算出された異常度と確率密度のグラフを描画すると次のようになります.
f:id:yoshikit1996:20180622162106p:plain

次に,このグラフの右側の何%を異常値にするのかを手動で決めます.
上述したグラフでは黄色い面積の部分が全体の面積の30%に対応しており,黄色い面積が始まっている横軸(異常度)の値が閾値になります.
つまり,全体の何%を外れ値にするのかを決定すると,閾値も自動的に決まるのです.

4. 外れ値検知

異常度が閾値より大きければ,外れ値とみなします.

ソースコード

ホテリング理論による異常検知をするソースコードを下記に記載します.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import chi2


if __name__ == "__main__":
    # ランダムなデータを生成
    data = np.random.normal(50, 10, 100)
    X = pd.DataFrame({"data": data})

    # データをプロット
    plt.scatter(X.index, X)
    plt.ylabel("value")
    plt.show()

    # ヒストグラムの表示し,正規分布に従うかどうか確かめる
    plt.hist(X["data"], bins=20)
    plt.show()

    # 平均値と分散値
    mean, var = X.mean()[0], X.var()[0]

    # 異常度を計算する
    anomaly_scores = []
    for x in X.data:
        anomaly_score = (x - mean) ** 2 / var
        anomaly_scores.append(anomaly_score)
    anomaly_scores_col = pd.DataFrame({"anomaly_score": anomaly_scores})
    X = pd.concat([X, anomaly_scores_col], axis=1)

    # 自由度1カイ2乗分布による5%の閾値を決定する
    degree_of_freedom = 1
    threshold = chi2.interval(0.95, degree_of_freedom)[1]

    # 外れ値検知する
    normality = X[X["anomaly_score"] < threshold]
    outliers = X[threshold <= X["anomaly_score"]]

    # 正常値と外れ値をプロット
    plt.scatter(normality.index, normality["data"], label="normality")
    plt.scatter(outliers.index, outliers["data"], c="red", label="outlier")
    plt.ylabel("value")
    plt.legend()
    plt.show()

プログラム実行結果

データをそのままプロット

正規分布に従うように乱数を生成してプロットしました.
縦軸が乱数によって生成された値です.横軸はpandas.DataFrameのインデックスなので特に意味がありません.
f:id:yoshikit1996:20180622163344p:plain

ヒストグラム

正規分布に従っていることが確認できます.
f:id:yoshikit1996:20180622163356p:plain

正常値と外れ値のプロット

グラフを見ると,外れ値っぽい値が外れ値として検知されていることが確認できます.

f:id:yoshikit1996:20180622163409p:plain