コンサルでデータサイエンティスト

仕事でPythonを書いてます。機械学習、Webマーケティングに興味があります。趣味は旅です。

One class SVM による外れ値検知についてまとめた

はじめに

異常検知技術が実用システムに導入される例が増えています。今回は外れ値検知手法として人気が高いアルゴリズムのひとつであるOne class SVMについてご紹介します。

One class SVMとは、機械学習の分類アルゴリズムである Support Vector Machine (SVM) を教師なしの1クラス分類に応用した手法です。正常データとして1つのクラス分を学習させ、識別境界を決定することで、その境界を基準に外れ値を検出します。異常がほとんど発生せず、異常クラスのデータが集まらないようなシステムで異常検知を実現したい場合には有効な外れ値検知手法です。

最後にPythonによる簡単な実装例についてご紹介します。

One Class SVMSVMの違い

One Class SVMSVM の違いについて理解するためには、まずSupport Vectorとは何かということを把握する必要があります。Support Vectorとは学習データの中で最も他クラスと近い位置に点を指します。Support Vector Machineでは、各クラスのSupport Vectorを基準として、それらのユークリッド距離が最大化するように識別境界を設定します。これをマージン最大化と呼びます。

f:id:hktech:20181011233116p:plain


また、識別境界が非線形の場合はカーネルを用いてデータを特徴空間に写像します。カーネルを適切に選択することで、複雑なデータ配置でも識別境界を引くことができます。

f:id:hktech:20181011233133p:plain


通常のSVMでは、学習データとして複数クラスのデータが用意されています。したがって、学習時に識別境界を決定すれば、あるデータがどのクラスに分類されるかを判別する分類器として使うことができます。

しかし、One Class SVMでは学習データとして正常データの1つのクラスしか用意されていません。One class SVMは識別境界を設定するという点では共通しているものの、分類手法としての役割を持つSVMと異なり、識別境界を境に正常データと異常データを識別する外れ値検知手法として使うことができます。

One class SVMによる外れ値検知

SVMでは複数のクラスのSupport Vectorを基準として識別境界を決定するということは理解できました。One class SVMでは1つのクラスのみでどのように識別境界を求めるのかということについて明らかにしていきます。

One class SVMではすべての学習データをクラスタ 1とし、原点のみをクラスタ -1に属するようにカーネルトリックと呼ばれる手法を用いて、高次元空間の特徴空間へデータを写像します。このとき、学習データは原点から遠くに配置されるように写像されるため、もとの学習データと類似していないデータは原点の近くに集まるようになります。この性質を用いて正常および異常データの区別をすることができます。

f:id:hktech:20181011233151p:plain

Python + Scikit-learn を使った実装

PythonでScikit-learn (sklearn) を使えば、One class SVMを数行で実装することができます。

from sklearn.svm import OneClassSVM
clf = OneClassSVM(nu=0.003, kernel='rbf', gamma='auto')
clf.fit(X_train)
pred = clf.predict(X_test)


SVMのパラメータとしてkernelとgamma、One class SVM特有のパラメータとして nu があります。
学習データはすべて綺麗なデータであるとは限らないため、識別境界の決定時に考慮しないデータの割合をnuで定義することができます。

predictの返り値としては 正常: 1、異常: -1のリストが返ってくるため、異常と判定されたサンプルのインデックス番号を確認するには次のコードを実行します。

import numpy as np
np.where(pred < 0)

このあたりはLOFの実装のときと同じですね。このように手法が変わっても返り値が同じ形式で得られるのもScikit-learnパッケージの強みです。

まとめ

異常検知技術のひとつであるOne class SVMについてご紹介しました。One class SVMSupport Vector Machineを1クラス分類に応用することで外れ値検知を実現する手法であるということがわかりました。また、Pythonを使って簡単に実装できることも確認することができました。SVMの中身は理解が難しいことで有名であるため、機会があればスクラッチから実装してみたいと思います。