EfficientNetによる異常検知

異常検知でググった際によく出てきたEfficientNetを試してみました。
コードはQiita等の記事をかなり参考にさせて頂きました。
（どういった計算をしているか等、理解できていないところがまだまだ多いです。）

コード以外のメモについては簡単ですが[こちら](https://qiita.com/08tarutaru/items/4c75a56fdb7a9713dfad)

# 推論の流れ
1. データセット作成
    * データはよく出てくる[MVTEC](https://www.mvtec.com/company/research/datasets/mvtec-ad/)の中から木の表面とネジの2種で検証
        * ダウンロード時はgood,scratch,hole等にフォルダ分かれているが、good,badフォルダのみに修正 
    * 前処理やデータ拡張は今回はなし。リサイズのみ。（実際業務でやる際は前処理の検討は重要）
    * クロスバリデーション用にStratifiedKFoldでデータを分割
    * 教師用データはgood（良品）のみ
2. モデル作成
    * 画像認識ライブラリのtimmを利用
    * model_nameは結構種類あったと思いますが、tf_efficientnet_b4_nsを使用（b6も試したけど結果は忘れました）
3. 推論
    * クロスバリデーション3分割で3回実施
    * EfficientNetの指定した層の配列を特徴量として、教師データのマハラノビス距離を算出
    * テストデータの良品、異常品のマハラノビス距離も算出し、f1が最大となるマハラノビス距離の閾値を求める
    * 上の閾値で混同行列を作成し、推論の正誤を確認する

# コード
コードは[こちら](https://github.com/sarah-muller/anomaly_detection)

### 参照
ほとんど以下記事のコードから抜粋です。
大変参考になりました。ありがとうございます。

[【異常検知】MVTec-ADを学習無しで正常/異常分類する](https://qiita.com/sUeharaE4/items/023455822376c07cd6ef)
[【異常検知】学習ゼロの衝撃！を可視化する](https://qiita.com/shinmura0/items/5f2c363812f7cdcc8771)

# 結果
### 1. 木の表面
#### クロスバリデーション毎のマハラノビス距離
* 1分割目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/05fe6f62-8326-396c-a4a0-6b6d8fe8800f.png)

* 2分割目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/239f27c1-d93d-c84b-aa11-798bd05f41e6.png)

* 3分割目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/e3cd6d38-dc55-ceb3-1151-696b08fd2950.png)

教師データのマハラノビス距離は0、テストデータの良品の距離は0.1程度、不良品は0.5以上と分類できていそうな感じ

#### 分類結果の混同行列
* f1が最大となるマハラノビス距離の閾値により分類
* 対象は全テストデータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/29bbb8c1-3aa9-f572-a43a-994a844f9e79.png)
誤りは1つのみ

* 全データのマハラノビス距離の平均とAUC
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/92b75d24-8551-dbc0-e69c-1396ffa2a02d.png)

* マハラノビス距離のヒストグラム
    * テストデータの良品は0-0.3くらい
    * 不良品は0.3-1.0くらい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/fcb7ded6-db39-9ee5-6edd-6fd38016f0a5.png)

* ROC曲線
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/45142275-0e8c-272a-4b39-2d54ab4dd7bc.png)

#### 異常部位の可視化
特徴が大きいところの色が明るくなるように可視化している。
木目模様っぽいところも明るくなってしまっているが、全体的に結構可視化できている
（これは全部[【異常検知】学習ゼロの衝撃！を可視化する](https://qiita.com/shinmura0/items/5f2c363812f7cdcc8771)のおかげです。）

* level=7の場合
    * 特徴量としてEffNetの7個目の層を使用。確か一番深いところで9だった？気がする
    * 覚えていないが9層目より7層目の方が精度高かった気が・・・気のせいかも、いずれにせよ7層でやった深い意味はありません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/b0551fb5-000d-a0bc-f969-41b9859642b0.png)

#### 特徴量として使う層を変えると
* level=2の場合
    * 画像全体的に明るいところが多い
    * よくいう最初の方の層は明るさや輪郭等細かい特徴量を抽出し、深くなるにつれてより大きな特徴を抽出している様子が表れているのかも？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/52ffac3a-0a09-e912-148b-4f1eea32cb0a.png)

* level=4の場合
    * 2と7の中間くらいの抽出具合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/2598ae11-39af-a01f-178d-761f09665749.png)

### 2. ネジ
おまけ程度にやってみました。

#### クロスバリデーション毎のマハラノビス距離
* 1分割目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/46ce6d09-9f8d-1d64-e774-571450307b7b.png)

* 2分割目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/0d7ed911-c972-768c-dc7e-5d37c0a3bee8.png)

* 3分割目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/f234e32f-6015-be20-f538-9e83ac836146.png)

木の表面に比べて、テストデータの良品と不良品の差が小さい。
EffNet調べているときに、素材の表面みたいなのは得意だが、3次元の物体になると精度落ちるという記事を見たがやはりそうなのか。
普通に考えて画像によってネジの向き変わっていたり、EffNetでなくても、ネジの方が何倍も難しそう。

#### 分類結果の混同行列
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/0429c74a-1aad-9792-71fc-6d69679900d5.png)

木の表面と比べると精度大きく落ちている。
特に異常の予測はランダムに近い。

* 全データのマハラノビス距離の平均とAUC
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/e90c2ecc-b893-c637-9dea-e40f084af395.png)

* マハラノビス距離のヒストグラム
テストデータの良品と不良品で結構被ってる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/e5b73b4e-44b4-3f06-6378-52737003f251.png)

* ROC曲線
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/628e7f67-c95f-587a-09a1-09cb0f2ff3ec.png)

#### 異常部位の可視化
なぜ背景が黄色い、、、すみませんめんどうなのでこのまま。
上手く特徴抽出できていないのがよくわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/24e3e937-4703-00d4-41c6-a01733c31a5f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/66283ced-0ea5-8079-dbc2-13f9f27ae0e2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/dad1e32d-d075-ad2b-d723-5d8ff66ddda0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460901/891c7324-e57c-b2d3-1f60-8d61a825d7cd.png)


# 所感
* 木の表面の精度は高かったが、現実でこういうのやろうとすると、ハードルが相当たくさんあって、こんなに簡単に上手くいかないよね（データの質、撮影環境、どう実運用するのか、費用対効果 等々）
* とはいえぱっと使う場合に相性が良いものであれば、ある程度の精度はお手軽に出せるのかも

# おまけ（HLACによる異常検知）
おまけ程度にやってみました。
[HLACによる異常検知](https://qiita.com/08tarutaru/items/19a256e07adf8afb5013)