プログレスバーを表示するためのPythonライブラリ progressbar2を使ってみた

はじめに

Yoshipon氏の以下のツイートからprogressbar2の存在を知ったので、使ってみたということ。

インストール

pipでインストール可能。

progressbar2 · PyPI

テスト

まずは、こんなスクリプトを書いてみた。

# -*- coding: utf-8 -*-

from time import sleep

from progressbar import progressbar as prg

for i in prg(range(10), prefix="A demonstration", suffix="\n"):
    sleep(0.1)
    print(i)

ターミナル出力はこんな感じ(アニメーションを用意したい!)。

A demonstration  0% (0 of 10) |                                                                           | Elapsed Time: 0:00:00 ETA:  --:--:--
0
A demonstration 10% (1 of 10) |#######                                                                    | Elapsed Time: 0:00:00 ETA:   0:00:00
1
A demonstration 20% (2 of 10) |###############                                                            | Elapsed Time: 0:00:00 ETA:   0:00:00
2
A demonstration 30% (3 of 10) |######################                                                     | Elapsed Time: 0:00:00 ETA:   0:00:00
3
A demonstration 40% (4 of 10) |##############################                                             | Elapsed Time: 0:00:00 ETA:   0:00:00
4
A demonstration 50% (5 of 10) |#####################################                                      | Elapsed Time: 0:00:00 ETA:   0:00:00
5
A demonstration 60% (6 of 10) |#############################################                              | Elapsed Time: 0:00:00 ETA:   0:00:00
6
A demonstration 70% (7 of 10) |####################################################                       | Elapsed Time: 0:00:00 ETA:   0:00:00
7
A demonstration 80% (8 of 10) |############################################################               | Elapsed Time: 0:00:00 ETA:   0:00:00
8
A demonstration 90% (9 of 10) |###################################################################        | Elapsed Time: 0:00:00 ETA:   0:00:00
9
A demonstration100% (10 of 10) |##########################################################################| Elapsed Time: 0:00:01 Time:  0:00:01

シェルのリダイレクトを活用してテキストファイルにログとして残す場合はちょっと注意が必要である。 例えば、上記のスクリプトをdemo.pyとして保存して実行するならば、

python3 demo.py > log.txt 2>&1

と行った具合に標準出力と標準エラー出力を束ねるわけである。progressbarは標準エラー出力に向いているので。

redirect_stdout=Falseのとき(デフォルト)、log.txtの中身は

A demonstration  0% (0 of 10) |          | Elapsed Time: 0:00:00 ETA:  --:--:--
A demonstration 10% (1 of 10) |#         | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 20% (2 of 10) |##        | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 30% (3 of 10) |###       | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 40% (4 of 10) |####      | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 50% (5 of 10) |#####     | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 60% (6 of 10) |######    | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 70% (7 of 10) |#######   | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 80% (8 of 10) |########  | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration 90% (9 of 10) |######### | Elapsed Time: 0:00:00 ETA:   0:00:00
A demonstration100% (10 of 10) |#########| Elapsed Time: 0:00:01 Time:  0:00:01
0
1
2
3
4
5
6
7
8
9

となる(標準エラー出力と標準出力が分離しているものをリダイレクトで束ねたので、こういう見かけ)。

redirect_stdout=Trueのときは、スクリプトはこうなる(デフォルトではFalseなので明示的にTrueにする)。

# -*- coding: utf-8 -*-

from time import sleep

from progressbar import progressbar as prg

for i in prg(range(10), prefix="A demonstration", suffix="\n", redirect_stdout=True):
    sleep(0.1)
    print(i)

その際、log.txtの中身は

A demonstration  0% (0 of 10) |                                                                           | Elapsed Time: 0:00:00 ETA:  --:--:--
0                                                                                                                                                
A demonstration  0% (0 of 10) |                                                                           | Elapsed Time: 0:00:00 ETA:  --:--:--
1                                                                                                                                                
A demonstration 10% (1 of 10) |#######                                                                    | Elapsed Time: 0:00:00 ETA:   0:00:01
2                                                                                                                                                
A demonstration 20% (2 of 10) |###############                                                            | Elapsed Time: 0:00:00 ETA:   0:00:01
3                                                                                                                                                
A demonstration 30% (3 of 10) |######################                                                     | Elapsed Time: 0:00:00 ETA:   0:00:00
4                                                                                                                                                
A demonstration 40% (4 of 10) |##############################                                             | Elapsed Time: 0:00:00 ETA:   0:00:00
5                                                                                                                                                
A demonstration 50% (5 of 10) |#####################################                                      | Elapsed Time: 0:00:00 ETA:   0:00:00
6                                                                                                                                                
A demonstration 60% (6 of 10) |#############################################                              | Elapsed Time: 0:00:00 ETA:   0:00:00
7                                                                                                                                                
A demonstration 70% (7 of 10) |####################################################                       | Elapsed Time: 0:00:00 ETA:   0:00:00
8                                                                                                                                                
A demonstration 80% (8 of 10) |############################################################               | Elapsed Time: 0:00:00 ETA:   0:00:00
9                                                                                                                                                
A demonstration 90% (9 of 10) |###################################################################        | Elapsed Time: 0:00:01 ETA:   0:00:00
A demonstration100% (10 of 10) |##########################################################################| Elapsed Time: 0:00:01 Time:  0:00:01

となっており、 冒頭に示したターミナル上での実行と見かけは一緒になる(それはそう)。

深層学習系のスクリプトを回す時、エポック毎のlossを表示させながらprogressbarも出したい時、便利ではなかろうか。tqdmだとテキストファイルに出力したときに表示が崩れるので。

以上。

Hydraのtutorialに従って書いたらpylintに怒られたので修正した話

最近Hydraを使い始めた。tutorialに従えばひとまず使えるようにはなる。 例えば以下のyamlファイルをconfig.yamlとして保存したとする(ニューラルネット的なconfig)。

model:
  hidden_dim: 128
  latent_dim: 32
  output_dim: 256
training:
  epoch: 100
  batch_size: 16

次にconfig.yamlと同じディレクトリに、以下のexample.pyを保存しておくとする。

# -*- coding: utf-8 -*-
"""Hydra example.

Copyright (C) 2022 by ballforest

MIT licence.
"""

from omegaconf import DictConfig

import hydra


# config_pathはyamlファイルの場所(ディレクトリ)
# config_nameはyamlファイル名から拡張子を抜いたもの("config.yaml" なら "config")
@hydra.main(version_base=None, config_path=".", config_name="config")
def main(cfg: DictConfig):
    """Perform examples."""
    print(cfg.model.hidden_dim)
    print(cfg["model"]["latent_dim"])


if __name__ == "__main__":
    main()

そして実行する。

python3 example.py

実行結果は

128
32

といった具合で、yamlの中身を引っ張ってこれる。

このexample.pyをpylintにかけたところ、以下の警告文で怒られた。

example.py:21:4: E1120: No value for argument 'cfg' in function call (no-value-for-parameter)

つまりmain関数の呼び出しに際して、引数がないので怒られているというわけだ。pylintがhydraのデコレータを解釈できないので、それはそうなのだが、修正方法はあるのか?と。

tutorialを引き続き調べると、initialize と composeを使えば良いことがわかった。

"""Hydra example.

Copyright (C) 2022 by ballforest

MIT licence.
"""

from omegaconf import DictConfig

from hydra import compose, initialize


def main(cfg: DictConfig):
    """Perform examples."""
    print(cfg.model.hidden_dim)
    print(cfg["model"]["latent_dim"])


if __name__ == "__main__":
    with initialize(version_base=None, config_path="."):
        config = compose(config_name="config")
        main(cfg=config)

このコードならばpylintから怒られずに済む(引数を明示的に与えているので)。

以上、備忘録であった。

wav2pixがpython2系で実装されていたので、python3系で動くように修正した

wav2pixというGANの派生モデルがある。

要するに、音声から顔画像を生成するgeneratorを持つGANである。

図1: wav2pixのネットワーク構成

qiita.com

wav2pixの実装はgithub上に見つかるのだが、いかんせんpython2系で実装されておりイマイチだったので、 これをpython3系でも動くよう、取り急ぎfixしたということ。

github.com

動作確認環境はpython3.6.9 on Ubuntu 18.04 LTSである。スクリプト全体はblackによりフォーマット済である。

実際にwav2pixを手元で動かして得られた生成画像はこんな感じ。

図2: wav2pixによる生成結果
上記の記事で紹介されているものと同様の画像であり、悪くない結果と言えるだろう。

ソースコードをpylintでチェックするとまだスコアが低いので、コードの修正はさらに必要である。

オンラインOCSVMに基づく外れ値検知をPythonで実装し、訓練時間削減の効果をベンチマークデータで検証した

はじめに

scikit-learn 1.0の新機能として、OC-SVMのオンライン版が紹介されている。 scikit-learn.org

オンライン化のご利益は訓練時間の大幅な削減である。 そこで本記事では、「結局オンライン化でどれくらい速くなったの?」という疑問に答えるべく、オンライン版OCSVMを使いやすい形となるようPyODのフォーマットで実装し、外れ値検知のベンチマークデータセットの上で性能を評価した。

準備

pip3 install pyod
pip3 install scikit-learn -U  # 最新版1.0系を入れるという意味

作成したクラス

SGD_OCSVMクラスを作成した。以下がソースコードである。

カーネル近似のためのNyström methodを実装したNystroemクラスと、SGDOneClassSVMクラスをそれぞれインスタンス化して実装している。

Nyström methodによりグラム行列を低ランク近似&feature mapを手に入れる。feature mapによりデータを(一般には)高次元空間に写像した後に、OC-SVMの目的関数が最小となるべく、パラメタをSGDで更新する。

つまり内部的には

  • 訓練データに対するNystroemのfit & transform
  • transform後のデータに対して、SGDOneClassSVMのfit

ということであり、sklearn的なパイプラインである。

参考までにそれらクラスの公式ドキュメントを示しておく。

今回は2クラスの引数をそのまま受け継ぐ形でSGD_OCSVMクラスを実装しているので、引数の数が多いのはイケてないが、やむを得ない。

使い方の例

上記のPythonファイルを、例えばsgd_ocsvm.pyとして保存する。使い勝手はPyODに合わせるようにした。

# PyODのOCSVM(バッチ型)の訓練
from pyod.models.ocsvm import OCSVM
clf = OCSVM(gamma="auto")  # デフォルトはRBFカーネル
clf.fit(X)

# SGDによるオンライン型のOCSVMの訓練
from sgd_ocsvm import SGD_OCSVM
clf = SGD_OCSVM(gamma="auto")  # デフォルトはRBFカーネル
clf.fit(X)

実験

PyODのベンチマークセット15種類に対して、バッチ型とオンライン型それぞれでモデルを訓練し、その所要時間および異常検知精度を比較する。 データセットは以下のサイトから入手できる。

これらデータセットの特性を簡単にまとめておく。

データセット サンプル数 特徴量次元 外れ値比率
arrhythmia 452 274 14.6%
cardio 1831 21 9.61%
glass 214 9 4.21%
ionosphere 351 33 35.9%
letter 1600 32 6.25%
mnist 7603 100 9.21%
musk 3062 166 3.17%
optdigits 5216 64 2.88%
pendigits 6870 16 2.27%
pima 768 8 34.90%
satellite 6435 36 31.6%
satimage-2 5803 36 1.22%
vertebral 240 6 12.5%
vowels 1456 12 3.43%
wbc 378 30 5.56%

実験に使用したノートブックを示す。なお訓練時のデータには外れ値は含まれている(訓練データとテストデータを6:4で分割)。

gist.github.com

結果

ノートブックより得られるグラフを図1に示す。左から、「訓練時間」「ROC」「Precision @ n」である。OCSVMはバッチ型、SGD-OCSVMはオンライン型である。

図1: 性能比較(バッチ型とオンライン型; 15データセットの平均)

上図より、訓練時間はデータセット平均でも劇的に削減できていることが分かる。なおかつ、異常検知精度は据え置きであり、今回はカーネル近似の影響をほぼ受けていない結果となった。

各データセットごとの訓練時間を示したのが図2である。

図2: 各データセットの訓練時間

上図より、サンプル数の多いmnistやoptdigits、pendigits、satellite、satimage-2で時間削減の効果が大きいことが読み取れる。特にmnistに関しては99%の時間削減となった (1- 0.053 / 6.1873 = 0.99) 。それ以外のデータセットについてはサンプル数が少なく、時間削減の効果は小さい。

参考までに、各データセットごとのROCスコアとPrecision @ nスコアを図3と図4にそれぞれ示す。ROCはほぼ同じグラフである。Precision @ nがオンライン化でやや劣るケースが見られるのは近似の影響であろう。

図3: 各データセットROCスコア

図4: 各データセットのPrecision @ n スコア

おわりに

今回の要点:

  • SGDを用いた最適化に基づくOC-SVMを、PyODフォーマットで利用可能となるように実装。カーネル近似手法の一つであるNyström methodの組み合わせ(パイプライン)。
  • 15ベンチマーク用データセットを用いて、訓練時間削減の効果を検証。サンプル数が多い場合に時間削減の効果が大きいことを確認。

みんなPyOD使おうぜ!

カーネルPCAに基づく外れ値検知にサブセットのサンプリング機能を実装して計算量削減を図った話

はじめに

先の記事

tam5917.hatenablog.com

にてカーネルPCAに基づく外れ値検知を実装したが、計算量が多く使い物にならない。

そこで本記事では、

tam5917.hatenablog.com

の記事にある、データセットのサブサンプリングを組み込むことで計算量を減らしつつ、検知性能がどの程度キープされるかを簡単に確認してみた。

実装

実装は以下の通り。

ここをクリックしてコードを表示する gist.github.com

検証

サブセットのサイズは、元のデータセットの20%になるようにランダムサンプリングした。以下がそのノートブックである。

gist.github.com

KPCA(SP)がサブセットのサンプリング版である。サンプル数の多いデータセットほど時間削減の幅は大きい(mnist、optdigits、pendigits、satellite、satimage-2)。 平均するとサンプリングなしと比較して10分の1程度までにはなった。注目すべきはサブセットをランダムサンプリングしても、サンプリングを行わないKernel PCAと比べて性能の低下はそれほど大きくない(ことが多い)ということである。むしろデータセットによっては、検知性能(ROC)がサンプリング後で改善しているものもあった(ionosphereやpendigits)。もっとも改善自体は乱数の「引き」の問題であり、たまたま良くなった、なのではあるが。各データセットの外れ値の割合を考えれば、サブサンプリングしたデータはほぼnormalなデータなので、性能の低下が抑えられているともいえる。

検証その2

先と同様に、サブセットのランダムサンプリングしたサイズは元のデータセットの20%とした。 さらに、random_stateを変えることで異なるサブセットを取る。今回の実験では5セットを作ることにした。それらの上でKernel PCAをそれぞれfitする。つまり検出器は5つである。 5つの検出器のアンサンブルを考えるために、各検出器から出力される異常度スコアの「平均」「最大値」「メディアン」を取り、ROCスコアをそれぞれ計算して比較する。異常度スコアのアンサンブルにはPyODのcombinationモジュールが利用できる。比較のため、サブサンプリングをまったく行わない、フルサイズのデータセットを使った場合の検出器も用意した。これらの間でROCスコアの変動を見ようというわけである。

アンサンブル型検出器の訓練とフルサイズの検出器の訓練で、どれほど計算時間が変化するかも見ることにした。

以下がノートブックである。 gist.github.com

グラフを示しておく。図1がROCスコア (アンサンブル型は「平均」)、図2が計算時間である。横軸はそれぞれのデータセットであり、各データセットについてサブセットサンプリング&アンサンブルを青、アンサンブルなし(フルサイズ)をオレンジの棒で示している。

図1: ROCスコア

図2: 計算時間

結果を要約すると:

  • サブセットのアンサンブル型でも、フルサイズのデータセットに匹敵する性能が出るケースが多いが、依然として負けるケースもある(図1)。サブサンプリングすることで大きく性能が向上したケース(musk)もあり、興味深いが、これはデータセットの特性に由来するものだろう。
  • データセットのサンプル数が多い場合、アンサンブル型にすることでも、依然として計算時間削減の効果は大きい(図2)

サブセットのサンプリングで性能低下しがちな面をアンサンブルで補った形と言えよう。

外れ値の比率が事前に分かっていれば、検知性能を損なわずにランダムサンプリング率をさらに小さくして計算時間の削減が可能ではある。運用上は比率が事前に分かっていることはあまりないだろう。なので今回の検証も参考程度に。

議論はあるか?

実用に持っていくためにはハイパーパラメータの調整が不可欠である。以下の論文では、カーネルPCAに基づくアンサンブル型モデルを用いた異常検知に関連して、ガウスカーネルのハイパーパラメータの最適化に関して議論されている。

Nicholas Merrill, Colin C. Olson; Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR) Workshops, 2020, pp. 112-113 openaccess.thecvf.com

カーネル主成分分析による外れ値検知をPyODフォーマットで実装した

はじめに

カーネル主成分分析を用いて外れ値検知ができるので、それを実装してみたということ。

カーネル主成分分析を外れ値検知に使うとは?

以下の論文にすべて書いてある(説明の手抜き!)。

  • Heiko Hoffmann, "Kernel PCA for novelty detection," Pattern Recognition, vol.40, no.3, pp. 863-874, 2007. Link

要するに、カーネルによって一意に決まる特徴空間上でPCAを実行し、さらに特徴空間上での再構成誤差を異常度として用いる。pre-image最適化を用いて、もとの空間に逆変換してから再構成誤差を計算する方法も考えられるが、今回は上記の論文に従うことにした。

実装

PyODのインストール

pip install pyod

KPCAクラス

PyODフォーマットに従って、KPCAクラスを実装した。以下を適当なファイル名(kpca.pyなど)で保存する。

ここをクリックしてコードを表示する gist.github.com

実装はscikit-learnのKernelPCAをラップする形である。

Toy example

PyODのexampleスクリプトを改変して実行した。うまく動いているように見える。 gist.github.com

ベンチマーク

PyOD付属のベンチマーク用のスクリプトを少し改変する。15のデータセット上で評価した。 外れ値検知の代表的な手法たちと比較する。

  • Angle-based Outlier Detector (ABOD)
  • k-Nearest Neighbors Detector (kNN); k = 5
  • Isolation Forest (IForest)
  • Local Outlier Factor (LOF); k=10
  • One-Class SVM (OCSVM)
  • Principal Component Analysis (PCA)
  • Kernel PCA (KPCA)

gist.github.com

Kernel PCAの性能はROC的にはまずまず。PCAと比較したときの優位性は十分に明らかとなった。Precisionはそれほど。サンプル数の多いデータセットは計算時間が特にかかることがわかる。

おわりに

PyOD使おうぜ!

Random Projection Outlyingness(RPO)に基づく外れ値検知をPyODフォーマットで実装した

はじめに

データ分布に対する各サンプル点の外れ度合いを測る指標として、Random Projection Outlyingness(RPO)が存在する。今回はRPOに基づく外れ値検知をPythonで実装したので、紹介する。

Random Projection Outlyingnessとはなにか?

depthについて

David Donoho先生らによる、以下の論文を参考にする。

David L. Donoho and Miriam Gasko, "Breakdown Properties of Location Estimates Based on Halfspace Depth and Projected Outlyingness," vol.20, no.4, pp.1803-1827, The Annals of Statistics, 1992.

projecteuclid.org

論文タイトルにも含まれている「depth」という量は、Tukeyらによって提案された(ちなみTukeyはFFTアルゴリズムの開発者の一人としても有名)。ある1つのデータ点(一般には多次元ベクトル)が、手元のデータセット(同次元のベクトル集合)の「分布的な意味でどのあたりに位置しているか」を記述する量がdepthである。以下にdepthの定義を示す。1次元のdepthの定義は

\displaystyle \mathrm{depth}_{1} = \mathop{\rm min} (\; \# \{ i \mid X_i \leq x\}, \; \# \{ i \mid X_i \geq x\})

である。ここで、$X$はデータセット $X =\{X_1, X_2, \ldots, X_n\}$である。入力データ$x$の左側と右側にくるデータの数を数えて、小さいほうをとる。これを$d$次元データに拡張するには、データを1次元空間に射影し、スカラーの集合に変換して比較可能にすることで、depthが計算できる。定義は

\displaystyle \mathrm{depth}_{d} = \mathop{\rm min}\limits_{\| u \|=1} \; \# \{i \mid u^{T}X_i \geq u^{T} x \}

とする。ここで$u$が射影軸を表すベクトルであり、$u^{T}X_i$は$i$番目のデータサンプルを$u$に射影した成分(内積を取っているのでスカラー)である。$u^{T} x$が当該サンプル$x$を射影したときの成分であり、成分が$u^{T} x$より大きくなるサンプルの数は大小関係を比較しながらカウントすることができる(有限集合なので比較は有限回で終わる!)。そして$\mathrm{min} $は正規化された射影軸$u$に渡って取る(暗黙的にそのような$u$の集合は有限濃度を考えている)。$d$次元版の観点から1次元版の定義を眺めると、数直線の右向きの軸および左向きの軸への射影を考えているわけである。

上記の論文で紹介されているが、1次元空間で考えるとsample maximumとsample minimumはdepthが1である。また上位/下位四分位数に対応するのは、depthとしてほぼn/4であり、メディアンに対応するのはdepthとしてn/2である(nはサンプルサイズ)。sample maximum/minimumは分布の際(きわ)に位置しているので「一番浅く」、depth的には最小値を取る。メディアンは分布のほぼ真ん中に位置しているので「一番深く」、depth的には最大値を取る。1次元のヒストグラム(山が一つ)をイメージすると分かりやすいかもしれない。上記のdepthを使うと、ロバスト統計にとって色々と興味深い議論ができる。

outlyingnessについて

さてDonoho先生らは、多次元データであってもdepthのように1次元空間に射影して統計的な性質を議論できることに目をつけ、多次元データにおける外れ度合い(outlyingness)の議論も同様にあてはまるだろうとした。1次元空間において、中心(平均)からのデータの乖離を測るために以下の量を考えるのは素朴である(1次元のホテリング$T^{2}$法において定義される異常度の平方根に相当する)。

\displaystyle \frac{|x - \mathrm{mean}(X) |}{\mathrm{std}(X)}

ここで$\mathrm{mean}(X)$と$\mathrm{std}(X)$はそれぞれ、$X$上で計算した標本平均と標本標準偏差である。しかしながら、この量は外れ値の影響を受けやすい。そこで標本平均をメディアン(median; MED)、標本標準偏差を中央絶対偏差(median absolute deviation; MAD)に置き換えた

\displaystyle r_1(x; X) = \frac{|x - \mathrm{MED}(X) |}{\mathrm{MAD}(X)}

を外れ値にロバストなoutlyingessとして考えることができる。MEDとMADは外れ値の影響を受けにくいことが知られている。

Random Projection Outlyingness (RPO)

depthと1次元射影のことを踏まえて、$d$次元のoutlyingnessへと拡張するには

\displaystyle r_d(x; X) = \mathop{\rm max}\limits_{\| u \|=1} \;  \; r_1 \left(  u^{T}x ; \{u^{T}X\} \right)

とすればよい。ここで$u^{T}X$は$u$上に射影したデータセットを表し、$u^{T}x$は$x$を$u$上に射影したデータ点(スカラー値)を表す。$\max$を取る$u$の集合は有限であり、したがって単位超球面$S^{d-1}$上から有限個をランダムサンプリングしたうえで計算する。以上がRandom Projection Outlyingness (RPO)である。文献によっては、Stahel-Donoho outlyingnessとも呼ばれる。これを外れ値検知における異常度スコアとして利用することができるというわけである。

実装

PyODのインストール

pip install pyod

RPOクラス

PyODフォーマットに従って、RPOクラスを実装した。以下を適当なファイル名(rpo.pyなど)で保存する。

ここをクリックしてコードを表示する gist.github.com

実装はとても簡単。ちなみに中央絶対偏差の計算にはscipy.statsのmedian_abs_deviation関数を使うことができる。

Toy example

PyODのexampleを実行した。 gist.github.com

ベンチマーク

PyOD付属のベンチマーク用のスクリプトを少し改変する。15のデータセット上で評価した。 外れ値検知の代表的な手法たちと比較する。

  • Angle-based Outlier Detector (ABOD)
  • k-Nearest Neighbors Detector (kNN); k = 5
  • Isolation Forest (IForest)
  • Local Outlier Factor (LOF); k=10
  • One-Class SVM (OCSVM)
  • Random Projection Outlyingness (RPO) (今回の手法; 射影次元は500 つまり射影軸を500本保持する) gist.github.com RPOは外れ値検知性能と省計算量とを両立していることがわかる。射影次元を大きくすれば計算時間とメモリ消費量は大きくなる(射影軸の集合をたくさん保持しないといけないので)。

参考文献

  • Donoho, D. L., Gasko, M., et al. Breakdown properties of location estimates based on halfspace depth and projected outlyingness. The Annals of Statistics, 20(4):1803–1827, 1992. Link

  • Zuo, Y. et al. Projection-based depth functions and associated medians. The Annals of Statistics, 31(5):1460–1490, 2003. Link