はじめに
OneClassSVMというものがあると知ったので使ってみます。
「1クラスSVM?」と思われると思いますが、要するに異常検知・外れ値検出などで使う手法です。信頼区間を出すのに似ていますが、複雑な分布だったりそもそも分布が想定できないようなデータでも計算してくれるので、シチュエーションによっては役に立ちそうです。
なお、わかりやすい記事があったので先に紹介しておきます。
実験
異常検知・外れ値検出系で使える手法なので、センサデータの処理とか、為替や株価のアルゴリズム取引用の処理なんかをやると適当だと思いますが、私はそんなカッコいいデータは持っていません。
なので、例によって例のごとく、irisをPCAで二次元に落としたデータを使います。
使い方は簡単で、nuに異常値の割合を指定すれば良いようです。なんかドキュメントには意味深なことが書いてありますが、この理解で良さそうです。
ちなみにデフォルトはnu=0.5なので、データの半数が異常値扱いになります。最初は、一体何事かと思いました。あと、predictすると正常値=1,異常値=-1という予測になります。
ドキュメント
sklearn.svm.OneClassSVM — scikit-learn 0.21.3 documentation
コードは以下のとおりです。
import numpy as np import matplotlib.pyplot as plt from sklearn.svm import OneClassSVM from sklearn.datasets import load_iris from sklearn.decomposition import PCA def main(): iris = load_iris() pca = PCA(n_components=2) data = pca.fit_transform(iris.data) x = np.linspace(-5, 5, 500) y = np.linspace(-1.5, 1.5, 250) X, Y = np.meshgrid(x, y) ocsvm = OneClassSVM(nu=0.1, gamma="auto") ocsvm.fit(data) df = ocsvm.decision_function( np.array([X.ravel(), Y.ravel()]).T).reshape(X.shape) preds = ocsvm.predict(data) plt.scatter(data[:,0], data[:,1], c=preds, cmap=plt.cm.RdBu, alpha=0.8) r = max([abs(df.min()), abs(df.max())]) plt.contourf(X, Y, df, 10, vmin=-r, vmax=r, cmap=plt.cm.RdBu, alpha=.5) plt.savefig("result.png") if __name__ == "__main__": main()
予測と決定関数を見るだけという手抜き。雰囲気はこれでわかると思うので、勘弁してください。
なんかcontourfあたりでごちゃごちゃやっていますが、決定境界がcmapの中心と一致するように配慮しています。こうすることで、白色のあたり(というか青と赤の境界)が決定境界になります。
余談ですが、このコードのためにlevelsをキーワード引数で指定しようとしたら、matplotlibのバグを踏みました。ひどい。
スポンサーリンク
結果
プロットされる図を示します。
このように、お手軽に良さげな結果が得られます。分布の形状が複雑でもうまく推定できる訳です。良いですね。
まとめ
SVMなので使いやすくて、うまく動くようです。手軽に良好な異常検知ができる手法としては、かなり便利だと思います。