PatchCoreの論文の理解 (2)　

## はじめに
異常検知の論文のPatch Coreの数式を理解するためのメモです。

https://qiita.com/kotai2003/items/41debb1b5132923fdb18

PatchCore論文(2021)
Towards Total Recall in Industrial Anomaly Detection
https://arxiv.org/abs/2106.08265

## 推論過程

テスト過程における公称パッチ画像特徴メモリバンク M の使用と、異常スコアの計算方法に関する説明を以下に簡潔にまとめます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/1525aeeb-a7af-ff42-af3e-56ed4e8cf19d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/74575684-5465-62b2-b9f7-39c02ca18b24.png)

#### 1. メモリバンクの使用:

- メモリバンク M は、正常な状態の画像から抽出されたパッチの特徴を集めたものです。
- テスト画像 x_test からは、同様にパッチの特徴が抽出されます。
#### 2. 画像レベルの異常スコアの推定:

- s* はテスト画像の全パッチにわたる異常スコアの最大値で、画像レベルでの異常スコアとして扱われます。
#### 3. パッチの異常スコアの計算:

- 各テスト画像のパッチから得られる特徴と、メモリバンク M 内の最も近い正常パッチ特徴 m* とのユークリッド距離を用いてスコアを計算します。
- 距離が大きいほど、パッチは異常である可能性が高くなります。
#### 4. スケーリングと再重み付け:

- 異常候補 m_test,* が m* に最も近く、同時にメモリバンク全体からも遠い場合、異常スコアは高くなります。
- Nb(m*) は m_test,* に最も近いメモリバンク内のトップ b 個の特徴です。
- この再重み付けにより、最大パッチ距離の計算がより堅牢になります。
#### 5. 異常位置のセグメンテーション:

- 与えられたスコア s を用いて、異常が発生している可能性のある画像内の正確な位置を特定します。
- 各パッチのスコアは argmax 操作を用いて計算され、異常位置セグメンテーションマップに直接つながります。
#### 6. セグメンテーションマップの生成:

- パッチの異常スコアを空間位置に基づいて再調整し、異常セグメンテーションマップを生成します。
- 元の入力解像度に合わせるために、バイリニア補間を使用して結果を拡大します。
- 結果をさらに平滑化するために、カーネル幅 σ=4 のガウス分布を用いて平滑化します。
このプロセスは、テスト画像内で異常が発生している正確な位置を特定し、それを画像上でセグメンテーションするためのものです。これにより、異常検出システムは、ただ異常が存在するか否かを判断するだけでなく、その異常がどこにあるかも特定できるようになります。

## 異常度スコア式の説明

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/9df3b225-8b5b-b3f3-061f-572d7f139622.png)

この式は、異常検出アルゴリズムにおけるテスト画像の特定のパッチの異常スコア `s` を計算するためのものです。具体的には、スコアリング関数を使って、テストパッチがどれだけメモリバンク `M` 内の既存のパッチ特徴から外れているかを測定しています。ここでの計算は次のようなステップを含みます：

- `||m_{test,*} - m*||_2`: テストパッチ特徴 `m_{test,*}` とメモリバンク `M` 内の最も近いパッチ特徴 `m*` との間のユークリッド距離を計算します。

- `exp(||m_{test,*} - m*||_2)`: 上記の距離を指数関数に通すことで、大きな距離をより重視するスコアを生成します。

- `\sum_{m \in N_b(m*)} exp(||m_{test,*} - m||_2)`: `m*` の最近傍であるメモリバンク `M` 内の `b` 個のパッチ特徴と `m_{test,*}` の距離の指数関数を計算し、それらを合計します。これは局所的な密度推定に対応し、テストパッチがどれだけ局所的に異常であるかを判断するのに役立ちます。

- `s = (1 - \frac{exp(||m_{test,*} - m*||_2)}{\sum_{m \in N_b(m*)} exp(||m_{test,*} - m||_2)}) \cdot s*`: 最初に計算したテストパッチの距離スコアを局所密度スコアで割り、1から引くことで正規化します。これにより、異常度が高いほど大きな値をとるようになります。最後に、この正規化されたスコアに `s*`（テスト画像の全パッチの中で最も高い異常スコア）を掛け合わせ、最終的な異常スコア `s` を決定します。

この式は、単にテストパッチがメモリバンクの既存のパッチと異なることを測定するだけでなく、そのパッチが周囲のパッチ特徴に対してどれだけ異常かを考慮しています。つまり、単一のパッチだけでなく、そのパッチが所属する周囲のコンテキストも異常スコアに影響を与えます。これにより、局所的な異常をより正確に検出することができます。


## `N_b(m*)`の説明（オプション）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/42b2a033-996d-2fa3-3b24-2996458526a3.png)

`N_b(m*)` は、メモリバンク `M` 内で定義されたパッチ特徴 `m*` の近傍にあるトップ `b` 個のパッチ特徴を指します。これは、`m*` に最も近い `b` 個の特徴の集合であり、`m*` の局所的なコンテキストを提供します。ここでの「近傍」とは、特徴空間内での距離に基づいており、`m*` から最も距離が近い特徴を選択します。

この近傍は異常スコア `s` の計算において重要な役割を果たします。具体的には、`m*` の近傍にある特徴と `m_{test,*}`（テスト画像の特定のパッチから抽出された特徴）との間の距離を用いて、テストパッチがどれだけその近傍から外れているか（つまり、どれだけ異常か）を測定します。この近傍特徴の集合に基づいて、テストパッチの異常度を局所的な観点から定量化することができます。

`N_b(m*)` は、異常検出の際にテストパッチが孤立しているか、それとも正常なパッチの群れの中に位置しているかを理解するために使用されます。もしテストパッチが近傍のパッチと大きく異なる場合、そのテストパッチは異常であると考えられます。逆に、テストパッチが近傍のパッチと似ている場合は、異常でないと考えられます。


## 参考文献
1. https://tech.anytech.co.jp/entry/2023/03/24/100000
1. https://zenn.dev/kwashizzz/articles/ml-anomaly-det-patchcore
1. https://techblog.leapmind.io/blog/20220701-introduction_to_patchcore/
1. https://scikit-learn.org/stable/modules/random_projection.html
1. https://www.chowagiken.co.jp/blog/padim-patchcore
1. https://arxiv.org/abs/2307.10792