【外れ値,python】Local outlier Factor(LoF)の紹介【scikit-learn】

LoF(Local outlier Factor)について勉強したので紹介します。

LoFとは(概要)

LoF は外れ値を検知するための手法の一つです。密度ベースの手法で、以下の図のように近傍のデータの密度等を用いて比較することで、外れ値かどうかを判定します。

「密度等」と書きましたが、実際には各データのLoF値という値を計算して、その値によって外れ値とする手法です。

LoF値は以下のような式で求めます。

lrdは後で説明しますが、密度を表します。

式の分子を見てもらうとわかると思いますが、
データAのlrd(密度)でデータAのk近傍のデータ群のlrdを割っています。
この部分から、

  • 近傍のデータ群の密度とデータAの密度が同じぐらいなら LoF は1に近く
  • 近傍のデータ群の密度よりデータAが高密度なら LoF は1より小さく
  • 近傍のデータ群の密度よりデータAが低密度なら LoF は1より大きく

なることがわかります。

LoF値の導出

この式がどこから出てきたかを順番に見ていこうと思います。

まず、到達可能性距離rd(reachability distance)という値を定義します。

\begin{aligned}
rd(A, B) = \max(d(A,B), kd(B))
\end{aligned}

\( d(A,B) \) はデータA,データBとの距離(例:ユークリッド距離等)、kd(B)(k-distance(B))はBのk近傍の中で一番遠いデータとの距離を表します。

次にデータAとその近傍のデータ群 \( N_k(A) \) との距離の平均を分母とした局所到達可能性密度lrd(local reachability density)を定義します。

\begin{aligned}
lrd_k(A)=1/\frac{\sum^{k}_{c \in N_k(A)}rd(A,C)}{| N_k(A)|}
\end{aligned}

各データとの距離の平均の逆数なので、名前にある通り密度を表します。

ここまで来たら、最後にLoF値の式を見てみます。

\begin{aligned}
LOF_{k}(A)=\frac{\sum_{c \in N_k(A)}\dfrac{lrd_{k}(c)}{lrd_{k}(A)}}{|N_k(A)|}
\end{aligned}

分子の式を見てわかるとおり、データAのlrdでデータAのk近傍のデータ群のlrdを割っています。

なので、先程も述べましたが、このLoF値は、

  • 近傍のデータ群の密度とデータAの密度が同じぐらいなら LoF は1に近く
  • 近傍のデータ群の密度よりデータAが高密度なら LoF は1より小さく
  • 近傍のデータ群の密度よりデータAが低密度なら LoF は1より大きく

なります。

LoFを使ってみる(scikit-learn)

scikit-learnを使ってLoF試してみます。

まず、必要なモジュールをimportします。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from sklearn import datasets
from sklearn.neighbors import LocalOutlierFactor

次に、簡単なデータセットを用意します。

X, Y = datasets.make_blobs(n_samples=200, centers=2, n_features=2, cluster_std=0.4, random_state=0)
plt.scatter(X[:, 0], X[:, 1], c="blue")
データ

ではLoFで外れ値を見つけてみます。

labels = LocalOutlierFactor(n_neighbors=5).fit_predict(X)

これだけです。ではプロットしてみます。

unique_labels = np.unique(labels)
for label in unique_labels:
    x = X[np.where(labels==label)]
    plt.scatter(x[:, 0], x[:, 1],label=label)
plt.legend()
LoFの結果

青(-1)が外れ値です。うまく外れ値を見つけることができているように思います。

終わりに

今回は簡単にLoFについて書きました。
もしなにか間違いがあれば教えていただければと思います。

参考文献

コメント

タイトルとURLをコピーしました