ファイナンス、情報通信技術のスキル・アグリゲーション・サイト

' . iseeit.jp Finance × ICT . '
 
機械学習の外れ方 ③

「異常」は、誰が決めたのか
閾値と基準の恣意性

異常検知のツールは「異常です」と教えてくれます。 ところがその線を引いたのはモデルではなく、こちらでした。 閾値を下げれば誤検出が増え、上げれば見逃す。 さらに厄介なことに、同じ −2% の下落が 2.93σ にも 0.86σ にもなります

異常検知 閾値 適合率 / 再現率 基準の移動

[ 1 ]

「異常」と言われても

AutoEncoder による異常検知を 公開したとき、画面には「異常」と表示される点が並びました。 それらしく見えます。

ただ、どこからが異常なのかは、モデルが決めたわけではありません。 モデルが出すのは「どれくらい普段と違うか」という連続値だけです。 そこに線を引いて「これ以上は異常」としたのは、実装した側です。

この記事で扱うこと

異常スコアの計算方法ではなく、そのスコアをどう判定に変えるかを扱います。 AutoEncoder でも移動平均でも、連続値を二値にする段階で同じ問題が起きます。

今回は分かりやすさのため、移動窓の標準化残差を異常スコアとします。 直近60日の平均と標準偏差を基準に、今日の変化が何σ離れているかを測る方法です。

[ 2 ]

閾値を動かすと、結果が総取り替えになる

合成データに5つの急変を仕込みました。−6.2%、−7.8% といった、 誰が見ても異常と言える下落です。これを検出できるか試します。

閾値検出数正しく検出誤検出見逃し
1.5 σ585530
2.0 σ274231
2.5 σ144101
3.0 σ8352
3.5 σ5322
5.0 σ3213

5つとも検出できるのは σ1.5 だけ——ただし誤検出が53件つきます。 σ3.5 まで上げると誤検出は2件に減りますが、3つしか拾えません

注目したいのは、どこにも「ちょうどよい」点が無いことです。 仕込んだ急変は −6.2% や −7.8% という、 誰が見ても異常と言える大きさでした。それでも取りこぼします。

適合率と再現率

適合率=「異常」と言ったもののうち、本当に異常だった割合。 再現率=本当の異常のうち、検出できた割合。 片方を上げると、もう片方が下がります

閾値適合率再現率
1.5 σ9 %100 %
2.5 σ29 %80 %
3.5 σ60 %60 %
5.0 σ67 %40 %
データからは、どこで切るべきか決まりません。 決めるのは「見逃しと誤検出、どちらが痛いか」という判断です。 これは統計の問題ではなく、使う場面の問題です。
[ 3 ]

どちらが痛いかは、場面で違う

場面重く見るもの閾値
サーバー障害の検知見逃したくない(止まったら困る)低く
相場の急変アラート誤報が続くと無視される高く
不正取引の検出見逃しの損害が大きい低く
自動売買の停止判断誤って止めると機会損失高く

同じ手法でも、用途によって正しい閾値が変わります。 「この手法の精度は◯%」という言い方が成り立たないのは、そのためです。

誤検出には、見えにくいコストがあります。 アラートが頻発すると、人はそれを見なくなります。 σ1.5 で58件——週1回を超えます。この頻度では、 本当の異常が混ざっていても気づけません。 「検出できている」ことと「役に立っている」ことは別です。
[ 4 ]

基準そのものが、動いている

ここからが本題です。閾値を固定しても、判定は安定しません。 σ という単位が、直近の変動の大きさに依存しているからです。

前半が穏やか、後半が荒れる合成データで確かめました。

期間日次の標準偏差
前半0.88 %
後半1.74 %(2.0倍)

同じ下落が、違う扱いになる

同じ −2.0% の変動
前半 (i=139)   スコア 2.93 σ   ← 閾値σ3 なら、ほぼ異常
後半 (i=330)   スコア 0.86 σ   ← 平常の範囲

同じ 2% の下落です。それが 2.93σ にも 0.86σ にもなる。 後半はもともとよく動いているので、2% 程度は「いつものこと」と判定されます。

荒れている時期ほど、異常が検出されにくくなります。 基準が直近から作られるため、変動が大きい状態に慣れていくのです。 本当に警戒したいのは荒れている局面のはずですが、 そのときこそ、モデルは何も言わなくなります

前回の 「学習窓を変えると答えが変わる」と、同じ構造です。 あちらは予測、こちらは判定ですが、 どちらも「何を基準にするか」で結果が動きます

[ 5 ]

線を、引いてみる

閾値と基準の窓を動かせます。仕込んだ急変が検出されるか、 いくつ誤検出が出るかを見てください。実データでも試せます。

Interactive · threshold & baseline
どこからを「異常」とするか
移動窓の標準化残差を異常スコアとします。合成データには急変を5つ仕込んであります(実データには正解がないため、検出数のみ表示)。
異常スコア(縦線=検出/▼=仕込んだ急変)
閾値 3.0 σ
基準の窓 60 日

閾値を σ2.0 あたりまで下げると、検出が一気に増えます。 逆に σ4 まで上げると、ほとんど反応しなくなる。 その間のどこかに線を引く根拠は、データの中にはありません

[ 6 ]

「正解」がないという問題

ここまでは仕込んだ急変を正解として数えてきました。 合成データだからできることです。

実データには、正解がありません。 2%下げた日が「異常」なのか「よくある変動」なのか、 誰も答えを持っていない。 だから適合率も再現率も計算できません。 デモで実データを選ぶと、検出数しか表示されないのはそのためです。

これは異常検知の根本的な難しさです。予測なら「翌日の値」という答え合わせができますが、 異常検知は正解ラベルを人が作る必要があります。

やり方問題
既知の事件を正解とするその事件を検出するよう調整してしまう
大きく動いた日を正解とする循環論法(大きい=異常と定義している)
人が目視でラベル付け基準が人によって違う。量も作れない
検出後に何が起きたかで評価時間がかかるが、実用的
結局、運用してみるしかない場面が多い。 閾値は「決める」ものではなく「調整し続ける」ものだと考えたほうが、 実態に合っています。 最初に決めた線が正しいという前提を持たない—— それが一番の対処かもしれません。
[ 7 ]

それでも、使うために

実務的に効きそうなことを、いくつか挙げます。

やること狙い
閾値を明記する「異常5件」ではなく「σ3で5件」と書く
基準の窓も明記するσ は窓に依存する。単位ではない
スコアをそのまま見せる二値にせず、連続値のまま提示する
絶対値の条件も併用「σ3 かつ −3%以上」で、荒れた時期の鈍化を補う
検出頻度を監視週1回を超えたら、閾値か基準を見直す合図

とくに絶対値との併用は、§4で見た「荒れた時期に鈍くなる」問題に効きます。 σ だけだと基準が動きますが、「−3%以上の下落」は動きません

ただし、条件を足すほど「決めごと」も増えます。 −3% という数字にも根拠はありません。 恣意性は消せず、置き場所が変わるだけです。 できるのは、どこに何を決めたかを書き残しておくことくらいだと思います。
[ 8 ]

まとめ

3回にわたって、自分で公開したツールを測り直してきました。 予測の精度、学習期間、そして異常の判定。 どれも「モデルが出した答え」に見えて、 実際にはこちらが決めた前提の産物でした。

この記事のまとめ

  • モデルが出すのは連続値。「異常」に変えているのは実装した側の線引き。
  • 閾値 σ1.5 で誤検出53件、σ3.5 で見逃し2件。どちらも同じデータ、同じ手法。
  • 適合率と再現率はトレードオフ。どちらを重く見るかは用途で決まる。
  • 誤検出が多いと人が見なくなる。検出できることと役立つことは別。
  • σ は基準の窓に依存する。同じ −2% が 2.93σ にも 0.86σ にもなる
  • 荒れた時期ほど検出されにくい。基準が直近から作られるため。
  • 実データには正解がない。適合率も再現率も計算できない。
  • 絶対値の条件を併用すると鈍化を補えるが、恣意性は置き場所が変わるだけ
機械学習の外れ方 — シリーズ
  1. 予測は、当たっているのか
    「精度」という言葉が隠すもの
  2. 学習期間を変えると、答えが変わる
    窓幅の選び方と、1行のリーク
  3. 「異常」は、誰が決めたのか(この記事)
    閾値と基準の恣意性

関連記事

『「異常」は、誰が決めたのか — 閾値と基準の恣意性』を公開しました。

ファイナンシャル・プランニング
債券利回り計算(単利)

最終利回り計算(単利) : 債券を購入時点から、最終償還日まで保有していた場合に得られる収益の利回りを単利にて計算します。

所有期間利回り計算(単利) : 債券の購入時点から、最終償還日前の売却時点までの所有期間に得られる収益の利回りを単利にて計算します。