この間はMetaflowを使ってみました。
ワークフロー管理+実験管理が可能なように、Metaflow + MLFlowを使ってコードを書いてみたいと思います。 多分、これだけでもMLOpsのごくごく一部は対応できていると思うので、今回はそのメモです。
参考
下記の記事で、小さく始めて大きく育てるMLOpsという内容が紹介されていました。
こちらの記事では、「Hydra、MLflow Tracking、Kedro、Optunaを導入するところから始めてみては?」といった趣旨になっていました。
Hydraを使ってハイパーパラメータの管理、Optunaを使ってハイパーパラメータの探索を行うという事になっています。 ハイパーパラメータの管理は、規模が大きくなるに連れて管理の重要度が上がってきますので、ということなんでしょう。 Optunaも、使えるなら使ったほうが良いと思います。
今回は、めんどくさかったので最低限でいいと思ったので使っていませんが、これを読んでいる方は上の記事に習うのが良いと思います。
三流エンジニアの私より、その道のプロが言っていることの方が正しいと思いますので。
今回は上の記事を読んで、実際に自分でガチャガチャいじっててみようと思ったのがこの記事を書くモチベーションになります。
お題
文書生成
最近文書生成を題材に遊んでみていたので、今回もそちらを題材にやってみたいと思います。
こちらをベースに色々作っていきたいと思います。
今回の主な技術要素
本当はハイパーパラメータ管理や自動チューニングなども導入したほうが良いということは重々承知しつつ、簡単のため今回はワークフロー管理と実験管理に絞って導入することを考えます。
ワークフロー管理:MetaFlow
ワークフローライブラリについてはそれぞれ特徴がありますので、正直人それぞれ好みのものを使ったら良いと思っています。 今回はたまたま最近調べたMetaflowをそのまま使おうと思います。
実験管理:MLFlow
時々議論になっていたりするんですが、Metaflowでも実験管理はできないことはなく、「MLFlow v.s. Metaflow」という構図の記事をたまに見かけます。
Metaflowでも、一応実行時の結果などを保存しており、それをJupyter-notebookなどで参照することで実験管理ができます。 ただ、個人的には、SaaS以外で実験管理するならMLFlow一択だと思っているので、ここについては特に選定理由はそんなもんです。
「餅は餅屋」、それぞれの特色をうまく組み合わせて使ったらいいと思うので、MetaflowとMLFlowを共存して使うのも良いと思います。 MLFlow自体、特に使用が難しいものでもないのですんなり使えるかと思いますし、ダッシュボードなどもデフォルトで使えるのでその点でも良いかと思います。
やってみる
Metaflow
Metaflowを導入すること自体はそこまで難しくないです。 処理の流れごとにメソッドを切って上げるだけなので、main.pyの記述を変更します。
# -*- coding: utf-8 -*- from metaflow import FlowSpec, step from readfile import readfile, prepareData from encoder import EncoderRNN from attnDecoderRNN import AttnDecoderRNN from trainer import Trainer INPUT = "INPUT" OUTPUT = "OUTPUT" class TextGenFlow(FlowSpec): @step def start(self): print("Reading File...") text_df = readfile("data/entail_evaluation_set.txt") self.src, self.target, self.pairs = prepareData(INPUT, OUTPUT, text_df) self.next(self.init_network) @step def init_network(self): print("Initializing Network...") hidden_size = 256 self.encoder = EncoderRNN(self.src.n_words, hidden_size) self.attn_decoder = AttnDecoderRNN(hidden_size, self.target.n_words, dropout_p=0.1) self.next(self.train) @step def train(self): print("Training...") self.trainer = Trainer(src=self.src, target=self.target, pairs=self.pairs) self.encoder, self.decoder = self.trainer.trainIters(encoder=self.encoder, decoder=self.attn_decoder, n_iters=75000) self.next(self.end) @step def end(self): print("Evaluation...") self.trainer.evaluateRandomly(encoder=self.encoder, decoder=self.attn_decoder) if __name__ == '__main__': TextGenFlow()
ちょこちょこっと書き直しただけですが、大筋は前回とそこまで変わりません。
これだけで、
- ワークフローを途中から再実行
- 過去の実行のときの値を確認
などができるようになります。
MLFlow
MLFlowに関しては、使用するライブラリよって使い方が異なるようですので、ドキュメントを確認しながらやります。
今回はPytorchを使用しているので、
- pytorchのモデルを保存
- 学習時のメトリックを記録
- 学習時のハイパーパラメータを保存
くらいを実施していきたいと思います。
ドキュメントを見る限りでは、mlflow.pytorchってのでモデルの保存、その他はlog_param、log_metricでいけそうでした。
最後にgithubつけましたが、10行前後追加しただけです。 こんな感じにトラッキングできます。
mlflow ui
考察
さて、こんな感じでちょっとした書き直しだけで、結構色々できるようになりました。
- ワークフロー管理(Metaflow)
- 特徴量管理(一部、Metaflow)
- 実験管理(MLFlow)
- 配信(MLFlow)
MLOpsと言っても欲しい機能を挙げたらキリがないですし、全部入りが欲しいとなったらMLOpsのSaaS使うのが手っ取り早いと思います。 一方で簡単に書くだけでも色々便利になりますし、ちょっとの努力で結構いろんなことができるようになるので、もし余力があればこの辺もやってみるのが良いかと思います。
書いたもの
適当に書いた残骸はこちら。
感想
今回は、MetaflowとMLFlowを実際のコードに使ってみようと思ったので、やってみた次第です。 個人的にはMetaflowは簡単に使えると思いますし、MLFlowもSaaSを使用しないのであれば実験管理ライブラリとしては筆頭だと思っています。
MLOpsはなかなか範囲は広いですが、これだけやるだけでも使い勝手はだいぶ良くなると思います。 これくらいの小規模からやるのが、敷居が低くて良いのかなとか思いました。