機械学習システムの監視に入門する

# 1. なぜ監視するのか
* Jupyter Notebookでの実験が実を結び、MLパイプラインを通して本番で稼働させるモデルが作成され、無事にデプロイされてREST API経由でそのモデルを運用するまでに至ったのでミッションは完了か？
* → デプロイが本当のゴールではない。世界に放たれたそのモデルが期待通りに動作しているかを継続的に監視し続けなければならない
    * 世界は刻々と変化するが、モデルの開発では通常、過去のデータから**静的な**モデルを構築する
* → 監視をすることで、予測精度の低下を検知することができ、**適切な**モデル更新タイミングを知ることができる
    * モデルの再学習にはコストがかかるので、精度とのトレードオフがある

---
# 2. 何を監視するのか
1. Software metrics
    * メモリ/CPU/GPUなどのハードウェアリソースの使用量、レスポンスタイム、リクエスト数、成功率
2. Input metrics
    * 入力値の統計値、欠損値やNaNの頻度
3. Output metrics
    * 予測値のあるwindowでの平均、メディアン、最大値、最小値、標準偏差などの統計値や分布
    * AUC、LogLoss、Relative Information Gain、相対誤差
    * ビジネスメトリクス 

→Output metrics（精度など、モデルの質的な指標）を直接監視するのが望ましいが、正解ラベルが必要であり、かつ正解ラベルが利用可能になるまで時間がかかることが多いので、Input metricsについても監視していく

---
## 補足: 監視対象の洗い出し方法
* モデルを期待通りに動作させなくし得る要因をブレストする
* → その問題を発見するための統計や指標をブレストする
* メトリクスは、はじめは多めでも良く、だんだん減らしていけば良い

---
## Input metricsの監視
* Feature Distribution monitoring
    * **特徴量分布** におけるデータの変化・ドリフトを検知するもの
* Feature Attribution monitoring
    * **特徴量の重要度** におけるデータの変化・ドリフトを検知するもの
    * Attribution: 予測に対する特徴量の貢献度に比例し、特徴量が予測に対して役立つかどうかを示す
* その他
    * 欠損値やNaNの頻度
---
### ドリフト
1. コンセプトドリフト
    * モデルの入力と、目的とする推論対象の関係が変化したときに発生する
    * 例
        * 敵対者側に適応能力があり、状況に応じて自身の行動を変化させる場合など
        * スパムが、アンチスパムシステム対策で文言を変えてきた
        * クレジットカードの不正利用は、ICカード普及後はオンライン上へと移行した
2. データドリフト
    * 予測モデルに与えられるデータが訓練時に使用したデータから変化したときに発生する
    * 例
        * 「コロナ」は2019年までコロナビールや太陽コロナの意味だったが、2020年にはコロナウイルスという意味で使われることが多くなった
        * 近くにスキーリゾートがオープンして病院がより多くの若年層を診察するようになった
        * 元の入力データのスキーマが変更された
            * データが想定された範囲か、既知のカテゴリ値か、Nan/Inf値が生成されていないか、特徴量の多次元配列の要素数は同じか、特定の入力がなくなっていないか

補足: トレーニング時にしたモデル性能とサービング時の性能の差を「Training-serving skew」と呼ぶことがある（Googleの論文などでよく使われる）

---
### Feature Distribution monitoringの課題
(1) 特徴量のドリフトスコアは、ドリフトがモデルの予測に寄与する影響を明らかにするものではありません。
(2) 特徴量の種類や表現（数値、カテゴリ、画像、埋め込みなど）において機能する統一的なドリフト測定値はありません。
(3) 特徴量のドリフトスコアは、特徴量間の相関を考慮するものではありません。

→ Distributionだけでなく、Attributionを合わせて考慮することが大切

引用: [Feature Attributions の監視：Google はいかに大規模な ML サービスの障害を乗り越えたのか](https://cloud.google.com/blog/ja/topics/developers-practitioners/monitoring-feature-attributions-how-google-saved-one-largest-ml-services-trouble)

---
### Feature Distribution とFeature Attributionsの組み合わせ
![スクリーンショット 2022-02-11 20.21.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92368/444440cf-bd4f-b304-9431-961d6ffe6bca.png)

引用: [Feature Attributions の監視：Google はいかに大規模な ML サービスの障害を乗り越えたのか](https://cloud.google.com/blog/ja/topics/developers-practitioners/monitoring-feature-attributions-how-google-saved-one-largest-ml-services-trouble)

---
# 3. どうやって監視するのか
* 監視ツール・サービスの利用（主に2.Input metrics）
    * TFX、GCP、AWS
* ラベリングによる精度確認（主に3.Output metrics）
    * ラベリングサービス、暗黙のフィードバック（例:ユーザが推奨事項をクリックしたかどうか）、Human in the loop

---
## TFX / TensorFlow Data Validationとは
* Tensorflow Data Validation（TFDV）は、トレーニングとサービスのデータを分析して次のことを行うことができる
    * 記述計算の統計情報
    * 推論スキーマ
    * 検出データの異常
* 分布の比較では、カテゴリ値にチェビシェフ距離、数値にJensen-Shannon divergenceで閾値を設けて学習時の分布と異なる分布になっていることを検出する

---
## TFX / TensorFlow Data Validationの例
* 統計の計算と可視化

```python
stats = tfdv.generate_statistics_from_tfrecord(data_location=path)
tfdv.visualize_statistics(stats)
```

![スクリーンショット 2022-02-12 0.17.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92368/23ed1a6e-4ce0-27c1-0380-a336ec2bf86a.png)

* データのスキューとドリフトをチェックする

```python
# トレーニングデータセットとサービスデータセット内の「payment_type」機能の間にスキューがあるかどうかを確認する
    serving_stats = tfdv.generate_statistics_from_tfrecord(data_location=serving_data_path)
    tfdv.get_feature(schema, 'payment_type').skew_comparator.infinity_norm.threshold = 0.01
    skew_anomalies = tfdv.validate_statistics(
        statistics=train_stats, schema=schema, serving_statistics=serving_stats)
```

引用: [Tensorflowデータ検証を開始する](https://www.tensorflow.org/tfx/data_validation/get_started)

---
## GCP / Vertex AI Monitoringとは
* Google Cloud における ML/AI 向け統合プラットフォーム Vertex AI に含まれる監視サービス
* 受信リクエストの一部（サンプリング）が、BigQueryテーブルに記録され、分析用に解析される
* モデルのスキュー検出を有効にするには、トレーニングデータを提供する必要がある。Cloud StorageまたはBigQueryのURIを指定する。ドリフト検出を有効にするには、トレーニングデータは必要ない。
* 分布の比較では、カテゴリ値にチェビシェフ距離、数値にJensen-Shannon divergenceで閾値を設けて学習時の分布と異なる分布になっていることを検出する

---
## GCP / Vertex AI Monitoringの例
* モニタリングジョブを作成する

```bash
gcloud ai model-monitoring-jobs create \
    --project=PROJECT_ID \
    --region=REGION \
    --display-name=MONITORING_JOB_NAME
    --emails=EMAIL_ADDRESS_1,EMAIL_ADDRESS_2 \
    --endpoint=ENDPOINT_ID \
    --feature-thresholds=FEATURE_1=THRESHOLD_1,FEATURE_2=THRESHOLD_2 \
    --prediction-sampling-rate=SAMPLING_RATE \
    --monitoring-frequency=MONITORING_FREQUENCY
```

* スキューデータとドリフトデータを分析する

![スクリーンショット 2022-02-12 0.28.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92368/bbc88202-d49d-7289-e7d1-845c536e58eb.png)

引用: [特徴のスキューとドリフトをモニタリングする](https://cloud.google.com/vertex-ai/docs/model-monitoring/using-model-monitoring#drift-detection)

---
# 4. 監視してどうするのか
* 評価指標が閾値を下回った場合に、モデルの再学習が始まるようにする
    * → **刻々と変わる世界の中で、モデルが期待通りに動作し続けるように**
    * 閾値は、精度の絶対値として設定されることもあれば、性能の変化率として設定されることもある
    * 閾値は、ビジネス要件・コストとのトレードオフを踏まえて決定する。コストに対してどの程度の性能低下を許容できるか。ビジネス側を巻き込んで決定していくことが必須。
    * 例: 新生児の出生体重の予測のように問題がかなり静的なものであれば再訓練の頻度は少なくても十分
* → CI/CD/CTパイプラインを構築し、1回のAPI呼び出しで全ての再学習プロセスが実行できるよう自動化しておく

---
## 補足: CI/CD/CTパイプラインの構成要素
* 特徴量エンジニアリングのロジックのユニットテスト
* 学習時の損失が収束するテスト
* パイプラインがモデルなどのアーティファクトを生成するテスト
* 予測の秒間クエリ数
* 予測の精度が閾値を超えているかの確認
* ステージング環境へのPRのマージなどをトリガーとしてモデルなどのデプロイ
* ステージング環境でのパイプラインの動作検証

---
# 参考
* [機械学習による実用アプリケーション](https://www.oreilly.co.jp/books/9784873119502/)
* [機械学習デザインパターン](https://www.oreilly.co.jp/books/9784873119564/)
* [仕事ではじめる機械学習](https://www.oreilly.co.jp/books/9784873118215/)
* [AIエンジニアのための機械学習システムデザインパターン](https://www.shoeisha.co.jp/book/detail/9784798169453)
* [Feature Attributions の監視：Google はいかに大規模な ML サービスの障害を乗り越えたのか](https://cloud.google.com/blog/ja/topics/developers-practitioners/monitoring-feature-attributions-how-google-saved-one-largest-ml-services-trouble)
* [Vertex Model Monitoring で活用する、Google の MLOps 監視手法](https://cloud.google.com/blog/ja/topics/developers-practitioners/monitor-models-training-serving-skew-vertex-ai)
* [Model monitoring](https://medium.com/prosus-ai-tech-blog/model-monitoring-1849fb3afc1e)