TaPRとは?point-adjustの水増しを断つ『時系列を意識した』異常検知の評価指標

時系列の異常検知で、ある論文が「F1スコア0.95を達成」と書いていたとします。本当に優秀なのでしょうか? 実は、ほとんど何も検出していない『まぐれ』のモデルでも、評価指標の選び方しだいでF1=0.95に化けてしまうことがあります。これは誇張ではなく、後ほど実測で示します。

時系列の異常は「ある1つの時刻」ではなく「ある区間(イベント)」として起こります。ところが、機械学習で標準的に使われる適合率・再現率・F1は、各時刻をバラバラの独立した点として数えます。この食い違いが、強い手法とそうでない手法の区別をできなくしてしまうのです。

この記事で扱う TaPR(Time-series aware Precision and Recall) は、この問題に正面から答えるために提案された、時系列を意識した適合率・再現率です。具体的には次の2つの場面で効いてきます。

  • 論文・コンペの結果を正しく読む: 「F1が高い」が本当に「異常をよく見つけている」を意味するのかを見抜く
  • 自分のモデルを誠実に評価する: 長い異常を1つ覆っただけで満点に見える、といった錯覚を避ける

本記事の内容

  • 時系列の異常が「区間」であること、そこから来る点ごとF1の限界
  • point-adjustの水増し(まぐれ検出器が高スコアに化ける様子を実測)
  • TaPRの考え方 — 検出スコア $\mathrm{TaR}_d$ と被覆スコア $\mathrm{TaR}_p$ への分解
  • パラメータ $\theta$(検出に必要な被覆)・$\delta$(曖昧領域)・$\alpha$(重み)の役割
  • 3つの検出器を3つの指標で採点する実測比較

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

時系列の異常は「点」ではなく「区間」である

まず、なぜ普通の指標ではダメなのかを直感で押さえましょう。下の図を見てください。上段が「真の異常」、下段が「あるモデルの予測」です。真の異常には、長く続く異常が1つと、短い異常イベントが3つあります。

同じ予測でも採点のものさしで評価が変わる

ポイントは、同じ予測でも「採点のものさし」を変えると評価がまるで変わることです。図の下半分に3つのものさしを並べました。点ごと(point-wise)は時刻を1つずつ数え、point-adjustは区間を1点でも当てれば区間まるごと正解にし、TaPRは「何個のイベントを検出したか」と「どれだけ覆ったか」を分けて測ります。この3つがどう違うのか、ここから順に掘り下げます。

センサーの故障、通信の障害、設備の異常——現実の異常は「始まり」と「終わり」を持つ期間です。1点だけ正常値を外れて即座に戻る異常もありますが、多くは数十〜数千ステップ続きます。つまり評価指標は「異常というイベントを、いくつ、どれだけ正確に捉えたか」を測るべきで、「正解した時刻が何個あるか」を測るのは本質からずれているのです。

では、標準的な点ごとF1は具体的に何を見落とすのでしょうか。

point-wise F1 の限界 — 長い異常が点数を独占する

点ごと(point-wise)の適合率・再現率は、各時刻が「異常(1)か正常(0)か」の二値分類だとみなして計算します。再現率なら $\mathrm{Recall} = \mathrm{TP}/(\mathrm{TP}+\mathrm{FN})$ で、TP・FNは時刻の数です。

この「時刻を1つずつ数える」やり方には、時系列ならではの落とし穴があります。長い異常が点数を独占するのです。

point-wiseは長い異常が点数を独占する

この図は、先ほどの真の異常(長い異常200点+短い異常3つ各5点、合計215点)を、点ごと評価への寄与で見たものです。長い異常1つだけで全体の 93% を占めています。つまり、短い異常イベント3つを全部見逃しても、長い異常さえ覆っていれば再現率は0.93を超える。「4つの異常のうち1つしか見つけていない」という重大な事実が、点数にほとんど反映されません。

実運用では、短い異常こそ見逃したくない突発故障だったりします。点ごとF1は、その重要性を「点数が少ないから」という理由で過小評価してしまうのです。

この欠点を「区間単位で見る」ことで直そうとしたのが、次の point-adjust です。ところがこれは、逆方向に振れすぎてしまいます。

point-adjust の水増し — 1点当てれば区間まるごと正解

point-adjust(PA)は、時系列異常検知で広く使われてきた調整法です。考え方はシンプルで、真の異常区間のうち1点でも検出できていれば、その区間全体を「正解(検出済み)」とみなすというもの。「異常に気づきさえすれば、全体を検出したのと同じ」という実務的な発想です。

point-adjustの水増し:1点で区間まるごと正解

一見もっともらしいのですが、これが深刻な水増しを生みます。上の図のように、長さ200の異常区間でたった1点を当てただけで、200点ぶんがTP(真陽性)に化けます。区間が長いほど、1点の「ご褒美」は大きくなります。

どれくらい危険か、実際に数値で確かめましょう。「散発的に数点だけ異常と鳴らし、そのうち1点がたまたま長い異常区間に入った」だけのまぐれ検出器を採点してみます。

まぐれ検出器はpoint-adjustだけ高評価

結果は衝撃的です。このまぐれ検出器の点ごとF1は 0.009(ほぼゼロ、正しい評価)なのに、point-adjust F1は 0.952 に跳ね上がります。中身は「数点鳴らしただけ」なのに、論文に載れば「F1=0.95の高性能手法」に見えてしまうわけです。一方、後で導入する TaF1 は 0.001 と、正しく低い評価を返します。

この point-adjust の過大評価は Kim ら(AAAI 2022)によって理論・実験の両面から指摘され、「ランダムなスコアでも高いPA-F1が出る」ことが示されました。つまりpoint-adjustのF1だけを見て手法の優劣を語るのは危険なのです。

点ごとは厳しすぎて短い異常を軽視し、point-adjustは甘すぎてまぐれを高評価する。ちょうどよい「区間を意識した、でも水増ししない」評価が欲しい——これがTaPRの出発点です。

TaPRの考え方 — 「検出」と「被覆」を分けて測る

TaPRは Hwang ら(CIKM 2019)が提案した指標で、論文タイトルは “Time-Series Aware Precision and Recall for Anomaly Detection”。鍵となるアイデアは、再現率・適合率をそれぞれ2つの成分の重み付き和に分解することです。

時系列を意識した再現率 $\mathrm{TaR}$ は次のように書けます。

$$ \begin{equation} \mathrm{TaR} = \alpha \cdot \mathrm{TaR}_d + (1-\alpha)\cdot \mathrm{TaR}_p \qquad (0 \le \alpha \le 1) \end{equation} $$

TaRの分解=検出スコアと被覆スコアの重み付き和

2つの成分は、それぞれ別の問いに答えています。

  • 検出スコア $\mathrm{TaR}_d$(detection score): 「異常イベントを何個見つけたか」。区間の長短に関係なく、イベント1個を単位として数える。これが「4つの異常のうち1つしか見つけていない」を点数に反映させる仕組みです。
  • 被覆スコア $\mathrm{TaR}_p$(portion score): 「各イベントをどれだけの割合覆ったか」。検出できたイベントについて、その範囲をどこまで正確に当てたかを測ります。

$\alpha$ は、この2つをどう混ぜるかのつまみです(既定値は $\alpha=0.5$)。$\alpha=1$ なら「とにかくイベントを見つけたか」だけ、$\alpha=0$ なら「どれだけ覆ったか」だけを見ることになります。適合率 $\mathrm{TaP}$ も同じ構造で、$\mathrm{TaP}_d$(予測した区間が真の異常と重なっているか)と $\mathrm{TaP}_p$(予測のうち正しく当たっている割合)の重み付き和です。

最後に、両者の調和平均で TaF1 を作ります。

$$ \begin{equation} \mathrm{TaF1} = \frac{2 \cdot \mathrm{TaP} \cdot \mathrm{TaR}}{\mathrm{TaP} + \mathrm{TaR}} \end{equation} $$

では、検出スコアと被覆スコアが具体的にどう計算されるのか、順に見ていきましょう。

検出スコア $\mathrm{TaR}_d$ と閾値 $\theta$

検出スコアは「各異常イベントを検出できたか」をイベント単位で数えますが、「少しでもかすれば検出」ではまた水増しに逆戻りです。そこでTaPRは、異常区間のうち一定割合 $\theta$ 以上を当てて初めて『検出した』と認めるという条件を置きます。

検出スコア:異常区間をθ以上覆えば検出

図の例では $\theta=0.5$ としています(既定値)。イベントAは70%覆っているので「検出 ✓」、イベントBは30%しか覆っていないので「未検出 ✗」です。検出できたイベント数を全イベント数で割ったものが $\mathrm{TaR}_d$ になります。

$$ \mathrm{TaR}_d = \frac{\theta\text{以上覆えた異常イベントの数}}{\text{全異常イベントの数}} $$

この $\theta$ が、point-adjustの「1点でもOK」($\theta \to 0$ に相当)との決定的な違いです。$\theta=0.5$ とすれば、「区間の半分以上を当てないと検出として認めない」ので、まぐれの1点では検出スコアが立ちません。先ほどのまぐれ検出器の $\mathrm{TaR}_d$ が 0.000 だったのは、まさにこの条件のおかげです。

検出できたイベントについて、次は「どれだけ丁寧に覆ったか」を測ります。

被覆スコア $\mathrm{TaR}_p$ と曖昧領域 $\delta$

被覆スコア $\mathrm{TaR}_p$ は、各異常区間に対して「予測が覆った割合」を平均したものです。これで「区間の端だけかすめた」のか「ほぼ全体を当てた」のかを区別できます。

ここでTaPRはもう一工夫しています。異常の『終わり』のラベルは曖昧だ、という現実への配慮です。異常がいつ完全に収まったのかは、人間がラベルを付けるときも判断が難しい。にもかかわらず、異常区間の直後に検出が少し続いただけで「誤報(False Positive)」と厳しく罰するのは酷です。

被覆スコアと曖昧領域δ

そこでTaPRは、異常区間の直後に長さ $\delta$ の『曖昧領域』を設け、そこでの検出には正の(ただし減衰する)スコアを与えます。図のように、異常が終わった直後はスコアが高く、$\delta$ の終端に向かって滑らかに0へ減衰します。これにより、「異常が終わった直後にまだ鳴っている」検出を即・誤報とせず、ラベルの曖昧さに過度に依存しない評価ができます。論文タイトルの “Addressing Ambiguous Labeling”(曖昧なラベリングへの対処)はこの部分を指しています。

被覆スコアにはもう1つ、実務的に嬉しい仕掛けを入れられます。

早期検出を評価する — 立ち上がりへの重み

異常検知では、「異常に早く気づくこと」に価値があります。区間の後半をダラダラ当てるより、立ち上がりを捉えたほうが対処が早まり被害も小さい。TaPRの被覆スコアは、異常区間内の位置に応じた重みを掛けることで、この「早期検出」を評価できます。

早期検出の評価:立ち上がりを当てるほど高得点

図のように、立ち上がり付近(位置0)で重みを高く、終端(位置1)に向けて減衰させると、早く検出した予測ほど被覆スコアが高くなるよう設計できます。逆に「誤報を減らしたいので終端を重視する」といった重み付けも選べます。論文タイトルの “Considering Variety of Detection Result”(検出結果の多様性の考慮)は、この柔軟な重み付けと、長短さまざまな異常を公平に扱う設計を指しています。

ここまでで、検出スコアと被覆スコアの中身が分かりました。両者を混ぜる $\alpha$ が、評価の性格をどう変えるかを見てみましょう。

$\alpha$ で「検出」と「被覆」を混ぜる

$\alpha$ のつまみを動かすと何が起きるのか、「長い異常だけ検出器」(長い異常はほぼ完璧に当てるが、短い異常3つは全部見逃す)を例に見てみます。

長い異常だけ検出器のTaRをαで動かす

この検出器は、4つのイベント中1つ(長い異常)しか検出していないので $\mathrm{TaR}_d = 0.25$、被覆も平均すると $\mathrm{TaR}_p = 0.25$ です(長い1つを当て、短い3つは0%被覆)。$\alpha$ を0から1へ動かすと $\mathrm{TaR}$ はこの2点の間を直線的に動きます。

重要なのは、どちらの端でも「4分の1しか見つけていない」事実が点数に出ていることです。点ごとF1ではこの検出器の再現率が0.93に見えていたのに(長い異常が点数を独占するため)、TaPRでは検出・被覆ともに0.25付近に落ちます。$\alpha$ は「イベントを見つけたこと自体をどれだけ重視するか」を調整するつまみであって、水増しを生む方向には働きません。

理屈が揃ったので、最後に3つの検出器を3つの指標で採点し、TaPRの威力を実測で確認します。

実測 — 3つの検出器を3つの指標で採点する

ここまでの図はすべて、次の実装で実際に計算した数値に基づいています。TaPRの骨子(検出スコアと被覆スコアの重み付き和)を、概念に忠実な簡易版として書いてみます。

import numpy as np

T = 1000
GT = np.zeros(T, dtype=int)
events = [(150, 350), (500, 505), (650, 655), (820, 825)]  # 長い1つ+短い3つ
for s, e in events:
    GT[s:e] = 1

def to_ranges(mask):
    rng, in_seg = [], False
    for i, v in enumerate(mask):
        if v and not in_seg: s, in_seg = i, True
        elif not v and in_seg: rng.append((s, i)); in_seg = False
    if in_seg: rng.append((s, len(mask)))
    return rng

def point_wise(pred):
    tp = ((pred == 1) & (GT == 1)).sum(); fp = ((pred == 1) & (GT == 0)).sum()
    fn = ((pred == 0) & (GT == 1)).sum()
    p = tp / (tp + fp) if tp + fp else 0; r = tp / (tp + fn) if tp + fn else 0
    return 2 * p * r / (p + r) if p + r else 0

def point_adjust(pred):
    adj = pred.copy()
    for s, e in events:           # 区間を1点でも当てたら区間全体をTP扱い
        if pred[s:e].any(): adj[s:e] = 1
    tp = ((adj == 1) & (GT == 1)).sum(); fp = ((adj == 1) & (GT == 0)).sum()
    fn = ((adj == 0) & (GT == 1)).sum()
    p = tp / (tp + fp) if tp + fp else 0; r = tp / (tp + fn) if tp + fn else 0
    return 2 * p * r / (p + r) if p + r else 0

そして、TaPRの核心部分です。検出スコアは $\theta$ 以上覆えたイベント数、被覆スコアは平均被覆割合で計算します。

def tapr(pred, theta=0.5, alpha=0.5):
    # --- 再現率側 ---
    detected = sum(1 for s, e in events if pred[s:e].sum() / (e - s) >= theta)
    TaR_d = detected / len(events)                       # 検出スコア
    TaR_p = np.mean([pred[s:e].sum() / (e - s) for s, e in events])  # 被覆スコア
    TaR = alpha * TaR_d + (1 - alpha) * TaR_p
    # --- 適合率側 ---
    pr = to_ranges(pred)
    TaP_d = (sum(1 for s, e in pr if GT[s:e].any()) / len(pr)) if pr else 0
    TaP_p = (((pred == 1) & (GT == 1)).sum() / pred.sum()) if pred.sum() else 0
    TaP = alpha * TaP_d + (1 - alpha) * TaP_p
    TaF1 = 2 * TaP * TaR / (TaP + TaR) if TaP + TaR else 0
    return TaR_d, TaR_p, TaR, TaF1

3つの検出器を用意します。「良い検出器」は全イベントをほぼ覆い、「長い異常だけ検出器」は長い区間しか当てず、「まぐれ検出器」は数点鳴らすだけ(1点だけが長い異常区間に入る)です。

good = np.zeros(T, int)                                # 全イベントをほぼ覆う
good[150:349] = 1; good[500:505] = 1; good[650:654] = 1; good[820:825] = 1
long_only = np.zeros(T, int); long_only[150:350] = 1   # 長い異常だけ当てる
lucky = np.zeros(T, int)
for p in [200, 60, 410, 730, 900, 950]: lucky[p] = 1   # 散発的、1点だけ異常区間内

for name, pred in [("良い", good), ("長いだけ", long_only), ("まぐれ", lucky)]:
    print(name, round(point_wise(pred), 3), round(point_adjust(pred), 3),
          round(tapr(pred)[3], 3))

採点した結果が次の表です。

検出器 点ごとF1 point-adjust F1 TaF1 ($\mathrm{TaR}_d$)
良い検出器(全イベントを覆う) 0.995 1.000 0.987 (1.00)
長い異常だけ検出器 0.964 0.964 0.400 (0.25)
まぐれ検出器(数点鳴らすだけ) 0.009 0.952 0.001 (0.00)

この表が、TaPRの価値を一目で物語ります。

3検出器×3指標の比較:TaF1だけが正しく序列化する

グラフから3つのことが読み取れます。第一に、point-adjust F1は3つの検出器をほとんど区別できません(0.95〜1.00)。まぐれ検出器すら0.952を叩き出し、まともな手法と見分けがつきません。第二に、点ごとF1は「長い異常だけ検出器」を0.964と高評価してしまい、4つ中1つしか見つけていない事実を隠します。第三に、TaF1だけが3つを正しく序列化します(0.987 > 0.400 > 0.001)。「全部覆った > 1つだけ覆った > まぐれ」という、私たちの直感に合う順序です。

なお、ここでの tapr 関数はTaPRの骨子を示すための簡易実装です。公式実装(後述のeTaPR)では曖昧領域 $\delta$ や被覆の重み付けがより精緻に扱われますが、「検出スコアと被覆スコアに分けて水増しを防ぐ」という本質は同じです。

この説得力こそ、新しい手法の論文がTaPRを採用する理由です。

TaPRはどれくらい使われているのか — eTaPRとTime-CAD

TaPRの被引用数は、Semantic Scholar基準でおよそ49件(うち影響度の高い引用7件)。point-adjustやVUSのような数百件級の「デファクト」ではありませんが、評価の誠実さを重視する層に着実に使われている指標です。特に産業制御システム(ICS)のセキュリティ分野では定番で、HAIデータセットや関連コンペの公式評価ツールが、TaPRの改良版 eTaPR(enhanced TaPR) を採用しています。eTaPRは検出スコアと重なりスコアの両方を要求し、適合率の重み付けに平方根を使う(点ベースとイベントベースの折衷)など、TaPRの考え方をさらに洗練させたものです。

そして、この指標の使われ方として象徴的なのが Time-CAD(Nam ら, ECML PKDD 2023)です。文脈を考慮した深層時系列分解による異常検知手法で、論文の評価指標の選択にこう書かれています——「従来の点ごと指標は系列の特性を見落とし、広く使われるpoint-adjustは過大評価の問題を抱える。そこでTaPRと対応する $\mathrm{TaF1}$ で性能を評価する」。実際、Time-CADは閾値依存を避けるためにスコアを1000段階で走査し、各モデルの最良 $\mathrm{TaF1}$(best TaF1)を報告しています。

論文の性能比較表(Table 2)から代表値を引くと、Time-CADは4つの実ベンチマーク全体で平均 best $\mathrm{TaF1}=0.955$ を達成し、比較した全手法中1位でした(OmniAnomalyやTranADが約0.77、SR-CNNが約0.75、TFADが約0.80)。文脈的な異常が支配的なデータでは平均で最大46%の改善が報告されています。

ここで効いてくるのが、本記事で見てきたTaPRの性質です。もしTime-CADがpoint-adjustのF1で「0.95」を主張していたら、「まぐれでも0.95出る指標だよね」と疑う余地が残ります。しかし水増ししないTaPRで全手法を横並びにして1位を取ったという事実は、ずっと強い証拠になります。評価指標を誠実に選ぶことが、結果の説得力そのものを支えているのです。

出典: Y. Nam, P. Trirat, T. Kim, Y. Lee, J.-G. Lee, “Context-Aware Deep Time-Series Decomposition for Anomaly Detection in Businesses,” ECML PKDD 2023. / W.-S. Hwang et al., “Time-Series Aware Precision and Recall for Anomaly Detection,” CIKM 2019.

最後に、TaPRが評価指標ファミリーのどこに位置するのかを整理しておきましょう。

評価指標ファミリーの中の位置づけ

時系列異常検知の「区間を意識した」評価指標は、TaPRだけではありません。系譜として押さえておくと、論文を読むときの見通しがよくなります。

指標 出典 特徴
点ごと P/R/F1 時刻を独立に数える。長い異常が点数を独占
point-adjust Xu+ 2018 区間を1点でも当てれば区間全体を正解。水増し
範囲ベース P/R Tatbul+ 2018 存在報酬+重なりで区間を評価
TaPR / TaF1 Hwang+ 2019 検出スコア+被覆スコア、θで水増し防止、δで曖昧ラベル対処
affiliation Huet+ 2022 距離ベース。重ならなくても近さを評価
VUS Paparrizos+ 2022 閾値非依存。buffer長を動かした体積

TaPRは、範囲ベース指標(Tatbul)の「存在+重なり」の発想を引き継ぎつつ、検出と被覆を明示的に分け、$\theta$ で水増しを断ち、$\delta$ でラベルの曖昧さを吸収する点が独自です。affiliationやVUSが「距離」や「閾値非依存」という別の角度から同じ問題に挑んでいるのと合わせて理解すると、評価指標の地図が立体的になります。

最後に、TaPRを実際に使うときの勘どころを整理しておきます。

TaPRを使うときの実務的な勘どころ

TaPRには $\theta$・$\delta$・$\alpha$ という3つのパラメータがあり、既定値はそれぞれ $\theta=0.5$、$\delta=0$、$\alpha=0.5$ です。これらをどう設定するかで、評価の「性格」が変わります。

まず $\theta$(検出に必要な被覆割合)です。$\theta$ を大きくするほど「区間をしっかり覆わないと検出として認めない」厳しい評価になり、小さくするほど point-adjust に近い甘い評価になります。$\theta=0$ にすると「1点でも当たれば検出」となり、まさに point-adjust の水増しが復活してしまうので、$\theta$ は0より十分大きく取るのが定石です。区間の半分を1つの目安として $\theta=0.5$ から始め、用途に応じて調整します。

次に $\delta$(曖昧領域の長さ)です。これは「異常の終端ラベルがどれくらい曖昧か」というデータの性質で決めます。ラベルが正確に付いているデータなら $\delta=0$ で構いませんが、人手でざっくり区間を引いたデータや、異常が緩やかに収束するデータでは、$\delta$ を異常区間の数%〜十数%程度に取ると、終端付近の検出を過度に罰しなくなります。

最後に $\alpha$(検出スコアの重み)です。「とにかく見逃しを減らしたい」なら $\alpha$ を大きくして検出スコア $\mathrm{TaR}_d$ を重視し、「検出した異常を正確に切り出したい」なら $\alpha$ を小さくして被覆スコア $\mathrm{TaR}_p$ を重視します。どれを重視するかは応用しだいですが、重要なのはパラメータを論文・レポートに明記することです。$\theta$ や $\alpha$ を変えればスコアは動くので、条件を書かずに「TaF1=0.9」とだけ報告するのでは、point-adjustの数値を裸で出すのと同じ落とし穴にはまります。評価条件まで含めて初めて、TaPRの誠実さが活きるのです。

まとめ

本記事では、時系列異常検知の評価指標 TaPR を、point-wise と point-adjust の問題点と対比しながら解説しました。

  • 時系列の異常は「区間(イベント)」であり、時刻を独立に数える点ごとF1は長い異常に点数を独占され、短い異常イベントの見逃しを軽視する
  • point-adjustは1点当てれば区間全体を正解にする水増しがあり、まぐれ検出器でもF1=0.952に化ける(実測)
  • TaPRは再現率・適合率を「検出スコア $\mathrm{TaR}_d$」と「被覆スコア $\mathrm{TaR}_p$」に分解し、$\alpha$ で混ぜる。検出は $\theta$ 以上の被覆を要求して水増しを防ぎ、$\delta$ の曖昧領域でラベルの曖昧さに対処する
  • 3つの検出器を採点すると、TaF1だけが「全部覆った > 1つだけ > まぐれ」を正しく序列化(0.987 / 0.400 / 0.001)
  • eTaPRはその改良版で、Time-CAD(ECML PKDD 2023)が best TaF1 で全手法1位を主張するなど、誠実な評価の土台として使われている

評価指標は「結果の見え方」を決めるレンズです。同じ予測でも、レンズしだいで天才にも凡人にも見える——だからこそ、自分のモデルを評価するときも、論文を読むときも、「どのものさしで測ったのか」を意識することが、異常検知では決定的に重要です。

次のステップとして、以下の記事も参考にしてください。