🙌

ベイズ目線で理解するMLOpsのデータセットシフト

に公開

はじめに

機械学習といえば生成 AI がトレンド独占している今日このごろですが、
MLOps における「データセットシフト」というややニッチ?な概念について調べる機会がありました。

WEB で少し調べてみても、データセットシフトについて数式を使った説明をしている記事はあまりなかったのと、
個人的に「ベイズモデリングの観点からデータセットシフトの解釈とかできないのか?」と思いいろいろ解釈を試みたので、その内容を記事にしてみました。

どなたかの参考になれば嬉しいです。

データセットシフトの種類

データセットシフトとは、機械学習において学習データとテストデータの分布に差異が発生し、予測に悪影響が出る現象を指します。

これは、MLOps の枠組みで対応すべき課題の1つとされており、
主な分類としては、以下の3種類があります。(参考: [Moreno-Torres et al., 2012])

  • ターゲットシフト(Target Shift)
  • 共変量シフト(Covariate Shift)
  • コンセプトシフト(Concept Shift)

ベイズの定理のおさらい

かの有名なベイズの定理は以下です。

p(Y|X) = \frac{p(X|Y) \cdot p(Y)}{p(X)}

また、各項目は以下のように呼ばれます。

  • p(Y|X):事後分布
  • p(X|Y):尤度
  • p(Y):事前分布
  • p(X):周辺分布

ベイズモデリングの枠組みでは、事後分布 (条件付き確率分布) p(Y|X) 自体が予測モデルとして表現されます。

また、分母の p(X) は入力データ X が与えられた際に定数(周辺確率)となるため、以下のように書けます。

p(Y|X) \propto p(X|Y) \cdot p(Y)

ターゲットシフト (Target Shift)

数式による定義

以下のように、学習時とテスト時の目的変数が従う確率分布が異なることを指します。

p_{\mathrm{tr}}(Y) \neq p_{\mathrm{te}}(Y), \quad p_{\mathrm{tr}}(X|Y) = p_{\mathrm{te}}(X|Y)

ここで、

  • p_{\mathrm{tr}}(\cdot):学習データの分布
  • p_{\mathrm{te}}(\cdot):テストデータの分布
  • Y:目的変数
  • X:特徴量(共変量)

とします。

つまり、ターゲットシフトは目的変数の分布は変化するが、各クラスにおける特徴量の分布は不変という状態のことを言います。

直感的なイメージ

そばとうどんの画像を分類するモデルを例として考えてみます。

ターゲットシフトとは、学習時にはそばとうどんの画像を 5:5 の比率で学習したとしても、実際の運用時(テスト時)にめちゃめちゃそばの画像が入力される(9:1 など)のような状態を指します。

このとき、

  • そばとうどんの出現頻度(Yの分布)は学習とテストで変わる
  • そば/うどんそれぞれの特徴量の性質(そばは細い、うどんは太い、等)は学習とテストで変わらない

というのが特徴です。

ベイズモデリングの観点からの理解

ベイズの定理を再掲します。

p(Y|X) \propto p(X|Y) \cdot p(Y)

ターゲットシフトは、ベイズの定理における事前分布p(Y)が学習とテスト間で変わることを意味します。

また、ターゲットシフトでは

\quad p_{\mathrm{tr}}(X|Y) = p_{\mathrm{te}}(X|Y)

でもあるので、次も言えます。

\quad p_{\mathrm{tr}}(Y | X) \neq p_{\mathrm{te}}(Y | X)

これは事後分布、つまり予測モデルの識別境界そのものが変化してしまうことを意味します。

主な対応策

ターゲットシフトに対する主な対応策としては以下があります。(細かい説明は省略します)

  • しきい値調整: 分類で使うしきい値(0.5 以上なら正例、など)をテストデータの分布に合わせて調整
  • クラス重み付け: 学習時に各クラスの重みを調整

特に、しきい値の調整は比較的簡単に実装できるので、ターゲットシフトの調整と意識せずに対応していた方もいるのではないでしょうか。

共変量シフト(Covariate Shift)

数式による定義

以下のように、学習時とテスト時の共変量(特徴量)が従う確率分布が異なることを指します。

p_{\mathrm{tr}}(X) \neq p_{\mathrm{te}}(X), \quad p_{\mathrm{tr}}(Y|X) = p_{\mathrm{te}}(Y|X)

直感的なイメージ

ここでも、そばとうどんの画像分類モデルを例に考えてみます。

のっぴきならぬ事情により、学習時にうどんにおいては讃岐うどんのデータだけを使って学習したとします。
しかし、テスト時には稲庭うどん、ひもかわうどん、伊勢うどんなど様々なうどんが入力されてきてしまうことが分かりました。
(簡単のためそばの画像は学習/テスト間でほぼ同じになっていたとします)

このとき、

  • 様々なご当地うどんは太さ、長さ、ツユの色などの特徴量はそれぞれ異なりますが、「うどんである」という点は同じ
    • つまり、学習とテストでうどんと識別するための特徴量の性質は変わっていない
    • 数式としてはp_{\mathrm{tr}}(Y|X) = p_{\mathrm{te}}(Y|X)に相当
  • 学習とテストの間で入力されるうどんの種類が異なるので、うどんの特徴量の分布p(X)は変わってしまっている

ということが言え、この状態を共変量シフトと呼びます。

ベイズモデリングの観点からの理解

ベイズの定理を再掲します。

p(Y|X) \propto p(X|Y) \cdot p(Y)

共変量シフトではp_{\mathrm{tr}}(X) \neq p_{\mathrm{te}}(X)となりますが、上記の式にはp(X)が含まれていません。

また、そもそも共変量シフトでは、p_{\mathrm{tr}}(Y|X) = p_{\mathrm{te}}(Y|X) が成り立つため、ベイズの定理だけを考えると特に悪影響は無いと言えます。

しかしながら、実際の運用では共変量シフトは予測モデルに悪影響を及ぼすことが多いです。

直感的な説明としては、
たとえば学習時に与えられていない特徴量の組み合わせがテスト時に現れた場合、モデルがうまく予測できない可能性が容易に想像されます。
(たとえば、学習データには存在しなかった種類のうどんがテスト時に入力されると、おそらく予測精度が下がる)

もう少し数式的に理解したいので、
簡単な例として以下のような重回帰の推定パラメータの式を考えてみます。

\hat{\boldsymbol{\beta}} = (\boldsymbol{X}^T\boldsymbol{X})^{-1}\boldsymbol{X}^T\boldsymbol{y}

ここで、\boldsymbol{X}\boldsymbol{y}がそれぞれ中心化されているという前提のもと、

\boldsymbol{X}^T\boldsymbol{X} \propto \mathrm{Var}(\boldsymbol{X})
\boldsymbol{X}^T\boldsymbol{y} \propto \mathrm{Cov}(\boldsymbol{X}, \boldsymbol{y})

が言えます。

\mathrm{Var}(\boldsymbol{X})\mathrm{Cov}(\boldsymbol{X}, \boldsymbol{y})はその値の計算の際にp(X)を使うので、
共変量シフトp_{\mathrm{tr}}(X) \neq p_{\mathrm{te}}(X)が発生すると推定パラメータ\hat{\boldsymbol{\beta}}の値が変わりうることが分かります。

学習とテストの間で推定パラメータ\hat{\boldsymbol{\beta}}が異なる可能性があるということは、同じ\boldsymbol{X}を入力しても学習とテストで異なる予測値が返されることを意味するため、
これは結局モデルの識別境界が変化していると解釈することができます。

共変量シフトはベイズの定理上は影響無いはずでは?

実は共変量シフトが問題にならないのは、
共変量シフトp_{\mathrm{tr}}(X) \neq p_{\mathrm{te}}(X)が発生しても、予測モデルのパラメータの推定値に変動が発生しないような、完璧な学習が行われた場合に限られることを意識することが重要です。

いかなる共変量\boldsymbol{X}に対しても出力\boldsymbol{y}を完璧に予測できるモデルを手に入れられた、という理想的な学習が行われた状況では、
共変量シフトp_{\mathrm{tr}}(X) \neq p_{\mathrm{te}}(X)が発生しても、p_{\mathrm{tr}}(Y|X) = p_{\mathrm{te}}(Y|X)も同時に成り立つためモデルへの悪影響はありません。

ただ、正直このような条件が満たされることは現実的にはほとんど無いので、
共変量シフトも他のデータセットシフトと同様に発生したら対応を検討する、という感じに実際はなるかと思います。

(じゃあ完璧な学習が行われた前提での数式の解釈に意味はあまりないのではって?うるさい!

主な対応策

共変量シフトに対する主な対応策としては「要度重み付け(Importance Weighting)」があります。

この手法も、ターゲットシフトの対策のクラス重み付けと同様に、学習時の分布とテスト時の分布の差を補正する考えがベースになっています。
(手法の詳しい説明は別記事に譲ります)

コンセプトシフト (Concept Shift)

数式による定義

学習時とテスト時の条件付き確率分布が異なることを指します。

p_{\mathrm{tr}}(Y|X) \neq p_{\mathrm{te}}(Y|X)
p_{\mathrm{tr}}(X|Y) \neq p_{\mathrm{te}}(X|Y)

直感的なイメージ

ここでもこれまでと同様、そばとうどんの分類モデルを例に考えてみます。

現在の一般的なそばとうどんの画像を使ってモデルを学習したところ、
麺が細いほどそば、麺が太いほどうどんと識別されるモデルが得られたとします。

しかし明日から急にめちゃめちゃ麺が太いそばが大流行し、モデルに入力されるそば画像の麺の太さが極太のものばかりになってしまったらどうでしょう?
当然、麺の太さという特徴量ではそばとうどんを誤って識別してしまい、モデルの精度劣化に繋がります。

このように、特徴量と目的変数の関係性が学習とテスト時で変化してしまうことをコンセプトシフトと呼びます。

ベイズモデリングの観点からの理解

ベイズの定理を再掲します。

p(Y|X) \propto p(X|Y) \cdot p(Y)

コンセプトシフトではp_{\mathrm{tr}}(Y|X) \neq p_{\mathrm{te}}(Y|X), \quad p_{\mathrm{tr}}(X|Y) \neq p_{\mathrm{te}}(X|Y)なので、
事後分布も尤度も学習とテストの間で異なっていることを意味します。
(つまり、ターゲットシフトと同様にモデルの識別境界ごと変わってしまっているパターンです。)

また、現実世界でこのようなケースでは、p_{\mathrm{tr}}(Y)p_{\mathrm{tr}}(X)も変化していることが多いため、
ターゲットシフトや共変量シフトの時のように重み付けのような手法で対応することも出来ない、という状況になり得るのがコンセプトシフトの特徴です。

主な対応策

潔くモデルを再学習しましょう。

ただし、コンセプトシフトが部分的に発生している場合は、徐々にモデルを更新していくオンライン学習の手法などがあるようです。
(説明は他記事に譲ります)

おわりに

本記事では、機械学習におけるデータセットシフトについて、ベイズモデリングの観点から解釈を試みました。

正直、こんなにデータセットシフトについて細かく考えずとも、
「モデルの精度が劣化したら学習を回し直す」みたいな単純な運用でなんとかなってしまうケースも多いかもしれません。

ただ、学習し直してもモデルが改善しない場合の改善への示唆になったり、モデル自体の理解が深まったりと運用に組み込めていたら良いこともあるのは確かだとは思います。

あと、なんか自分 MLOps ちゃんと出来ててかっこいい!偉い!みたいな自己肯定感が少し上がりそうですよね?、、、、、、ね??

参考文献

Discussion