MLOpsとはについての自分なりの理解

タイトルの通り自分なりのMLOpsについてのまとめです。ここでは、WebアプリなどでMLを利用することを想定しており、Edgeデバイス上で推論することは一旦除外しております。

MLOpsとは

MLOpsとは $${MLOps=ML+DevOps}$$というのが、私の理解になります。この理解に則るとMLOpsというのは二つの構成要素でできています。
一つは、MLでもう一つがDevOpsです。
これについても自分の理解を書いてみます。

ここでいうMLというのは、機械学習モデルではなく、機械学習モデルを含んだアプリケーションの機能を指しているのだと思います。なので、モデル単体というよりもモデルを利用する一連のシステムがMLOpsの担当範囲ではないかというのが私の意見です。

さて、厄介なのがDevOpsの方です。DevOpsというと真っ先に思い浮かぶのがCI/CDやそのツール群の方もいるとは思うのですが、個人的にはもう少し広い意味を持っているのだと思います。
わたしなりのDevOpsは、文化や働き方の一種で自動化を方法論として取り入れたものというとのです。
ここでいう文化は、困難な状況下や締切が差し迫っていても自然と選択できる無意識の選択基準という意味で使っています。つまり、殆どのどんな状況下でも選択できる優先順位として機能するものです。

まとめると、私の中のMLOpsはMLアプリケーションの開発によって価値提供するために、自動化というものを優先する文化や働き方というものです。
これは、厳しい制約でもあり、実現がなかなか難しいなと思いますが、価値ある取り組みだとも思います。

MLOpsの成熟度レベルについて

文化にも成熟度があります。私の中のDevOpsは文化の一種でもあるため、MLOpsにも成熟度があると考えています。基本的にはGoogleの影響を受けているので、こちらの考え方に近いと思います。

ここではあまり要素技術に焦点を当てないようにしつつ、自分なりにまとめてみます。私の中のMLOpsの成熟の変遷イメージは以下のようになっています。

  • level0: コード化

  • level1: モデルデプロイの自動化

  • level2: モデル訓練のスケジュール化

  • level3: モデル訓練とデプロイの自動化

level0: モデル訓練とデプロイのコード化

なぜやるのか

個人的には割と最難関の一つでは思っています。というのも、多くのMLエンジニアはJupyter  Notebook(Jupyter lab)のようなインタラクティブに操作でき、様々な状態管理を意識しなくても使えるものを開発の道具として利用してると思います。
自分もMLに関わる人間として、Jupyterがいかに便利かというのは理解していますが、自動化という観点で考えるとJupyterだけでやるのはまだまだ厳しいのではと思います。

多くの開発現場ではこれまで培ってきたソフトウェア開発の技術やお作法などを取り入れて、より早く開発できるように開発体制が培われてきていると思います。それまで培われてきた資産を活かそうとしたときに、Jupyterというのはまだまだ適応させるのが難しいというのが自分の解釈です。Jupyterは言ってしまえばGUIで操作可能なREPL開発環境なので、既存の自動化とは相性が悪く、多くのところで様々なものを自作していく必要が出てきます。

どう変えるのか

Jupyterに記載されている処理を適切にパッケージングしなおして、テストコードを追加しましょう。Pythonのプロジェクト管理が面倒な場合は Poetryryeなどを使って、その辺りの管理を任せましょう。ryeの方がPythonのバージョン管理まで含めて可能なので、個人的にはryeの方が好きです。
とりあえず、設計とかは後回しにしてでもいいので、Pythonプロジェクトとして扱えるようにした方がいいと思います。

コードを移植したら、テストコードを書きましょう。scikit learnには人工のデータセットを作るための様々な関数が用意されています。

from sklearn.datasets import make_classification
import numpy as np

X: np.ndarray
y: np.ndarray
X, y = make_classification(n_samples=10, n_features=10, n_classes=2)

例えば、上記のコードは2クラス分類のダミーデータを作る処理です。タイプヒントがあると尚良いとは思います。

ここで大事なのは、モデルが正しく訓練されているかどうかを確かめるのではなく、自分の書いた処理が同じデータ構造を与えたときにend-to-endで実行できるかどうかだと思います。モデルの訓練結果の正しさはJupyterで実装した時に確かめたり、処理を実行するときにW&Bなどの実験管理ツールなどで目視確認で十分だと思います。

level1: モデルデプロイの自動化

なぜやるのか

ここでは、モデルのデプロイを自動化する方法について考えます。訓練されたモデルは、バッチジョブのようにスケジューリングされたジョブとして実行されるか、APIのエンドポイントとしてデプロイされるかの2択であることが多いと思います。手動デプロイという方法ももちろんありますが、モデルを含めてコードや設定の変更したいケースはたくさんあると思います。
MLを利用したアプリケーションは、様々な要因で想定外の処理が起きえます。コードのバグはもちろんのこと、データの分布の変化や、推論のデータが作れなかったなどのデータに関する要因もあります。
想定外の何かが起こった時に、考慮する事項をなるべく減らしておくことで適切に対処できる可能性が高まると考えています。

どう変えるのか

まず、一番大事なのはそのモデルの価値提供がうまくいっているのか、うまくいっていないのかを見極めることです。
なので、モデルの提供する価値を計測可能にするところから始めるのが改善のサイクルを回せるのではと思っています。もちろん、システムメトリクスも同時に取っておくのが望ましいです。

基本的には、いわゆるMLの精度はビジネスKPIと相関しないことを前提に考えるのがいいと思っています。
相関していればKaggleのように精度を高めることを目指していけばいいですが、そうでないなら精度を高める努力が空回りになってしまうことがあります。

さて、ビジネスKPIを定めることができたら、それをSREの文脈のSLO的に使うのがいいと思います。KPIを含めて全ての指標はハック可能であり、それを伸ばすことだけに囚われるとハックする方向にどうしても寄りがちになってしまうこともありえます。
「これを下回ってしまったら新しいモデルをデプロイする」のように考える方が建設的にKPIを利用できるのではと思います。

LEVEL0でコード化しているはずなので、実行してモデルを構築しどこかに保存するようにします。新しく保存したモデルを自動でA/Bテストやデプロイできるようにすることで、運用を楽できるようにしていきましょう。
ここで大事なことは、新しいモデルがいつでもいい価値を生み出すということではないということです。そのため、エンジニアと協力して新しいモデルがうまく機能しなかった場合に古いモデルに簡単に切り戻せるように、モデルのデプロイフローを整備するのが良いと思います。

level2: モデル訓練のスケジュール化

なぜやるのか
さて、Level1でビジネス価値を元に手動でモデルを更新し、その結果を自動でA/Bテストしたりデプロイしたりできるようになったとします。
モデルは徐々に劣化していくものなので、どの程度の期間で許容できないくらい劣化するのかという経験値が溜まってくると思います。
毎日KPIを監視して、それを元に変更を加えるというのは結構な重労働だと考えています。専属でそのモデルを利用している機能だけを見ることができる環境なら、その運用負荷にも耐えられると思うますが、多くの場合は複数のプロジェクトが並行していると思います。

複数のプロジェクトを同時にやるというのは賛否両論あると思いますが、MLエンジニアの数が少ないのでどうしてもそうなりがちです。
そのため、運用負荷を下げていくのがここでの目的となります。

どうやるのか
ここでは、Level0で作成したコードの訓練部分をスケジュール実行するようにしましょう。Github Actionsなどを利用しても良いですし、Vertex AI Pipeline + Cloud SchedulerやSagemaker + CodeBuildのようなクラウドサービスを連携させてもいいです。
重要なのは、A/Bテストやデプロイまでの処理と訓練の処理が連携され定自動化されていることだと思います。

level3: モデル訓練の自動化

まず、自分の経験ですがここまでの自動化ができたことはほぼないです。
大抵は、スケジューリングで自動訓練まで行くのも大変ですが、ここまでいくとデータ・ドリブンな自動化ができていることにもなります。

なぜやるのか 
MLは徐々に劣化するという話をしましたが、劣化には様々な要因があります。よくTraining/Serving Skewという言葉で表現されると思いますが、訓練した時のデータの傾向と、現在のデータの傾向が変わるとモデルは劣化します。
以下に良いまとめがあるので、そちらを参照するといいと思います。

基本的にはMLはかなりの運用負荷があり、MLの性質上壊れていても動き続けるというのがかなり厄介だと個人的には考えています。
そのため、なるべく自動で壊れていることを検知できるようにし、それをトリガーに新しいモデルが構築される状況を目指して、なるべく手放しの運用ができるようになることが望ましいです。

どうやるのか
ここまでくると、個別具体の話が多くなるのでこれといった解決策はないというのが個人的な見解です。ただし、モデルの予測値の分布を監視するというのを目指すのが良いと思っています。
特に、重要なセグメントに対してモデルの予測の傾向を確認して、それが想定と異なっていないかなどは確認するなどがいいと思います。以下の論文やブログがかなり詳しく書かれており、一読すると良いと思います。

また、モデルの監視という観点でevidently.aiという会社がモデルの監視のフリーコースとライブラリを提供しています。自分たちのユースケースに合わせて利用してみるのがいいと思います。


終わりに

MLOpsでやらないといけないことは幅広くあります。
例えば、The ML Test Scoreという論文では以下のようなことを挙げています。

  • バージョン管理

  • テスト

  • 自動化

  • 再現性

  • デプロイ

  • モニタリング

ここで挙げたものでも一部を満たしていますが、挙げられている全てをカバーしているわけではありません。
MLOps含めてMLというのはチーム戦です。MLエンジニアだけで全てをやろうとする必要はなくチームで自分たちが足りていないところを見極めて、現状と照らし合わせつつチームで解決し改善していくことが大事だと思います。

他社事例というのも参考になります。
evidently.aiがMLSystem Designというブログ記事でかなり綺麗にまとめてあります。適宜読み合わせなんかをチームでできると、メンバーの理解も深まり自分たちとの比較もできるようになるので、適宜参照するのがいいと思います。

機械学習システムデザインといOreillyから出ている本もとても良い本です。一読することをお勧めします。


この記事が気に入ったらサポートをしてみませんか?