はじめに
- Kedro + MLflow + Github Actions でデータ分析環境を構築したので、感想を書いてみました。
背景
=「ローカル環境で、1ファイルに全て突っ込んだノートブックを実験ごとに作っていた(lightgbm_02_YYYYMMDD.ipynbなど)ときの課題」
- 巨大で複雑なノートブックが出来上がってしまう
- 前処理、モデル学習、モデル評価...
- 担当分けが難しい(全部一人でやる場合も多いだろうが)
- メンテが辛い
- → 処理ごとに分けると、今度は依存関係が良く分からなくなる
- コードのレビューが辛い
- ノートブックはdiffが取りにくい
- ノートブックだとコードフォーマッタやチェッカーをかけられなかったり
- 実験管理が辛い
- 一覧化したくなる(一々ノートブックを開いて思い出すのは辛い)
- → 一覧を手動でメンテするのはめんどくさい(試行が多くなればなるほど)
- 他人の環境で(まっさらな環境から作り直すと)動かなかったり結果が変わったりする
- 人から案件を引き継いで、masterをcloneしたら動かなかったり
- ローカルにあるコミットしていないデータに結果が依存していたり
やったこと
パイプラインツールとしてKedroを導入した
![icon_kedro.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F92368%2F4e6f0d85-d2a9-d1f0-8907-e13a53916908.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=39bf0631a4e952961962d30c9efc44e0)
よかったこと
- 最初にノード(、データのIn/Out)・パイプラインを定義することで、担当分けがしやすい+メンテがしやすかった
- 処理ごとのIn/Outの認識合わせを最初にさせられるのが良かった
- 命名規則も最初に決めて周知できた
- ノートブックと連携させやすかった
$ kedro jupyter notebook --allow-root --port=8888 --ip=0.0.0.0 &
from kedro.framework.context import load_context
proj_path = '../../../'
context = load_context(proj_path)
# df = catalog.load("XXX")
parameters = context.params
- kedor-vizを使えばパイプラインを可視化できた
- credential.yamlでクレデンシャル情報を管理できた
残課題
- いつパイプライン化するか(スクリプト化するか)が悩ましい
- データサイエンティストがノートブックでどんどん試行錯誤 → データエンジニアが随時パイプライン化、をしていたが、修正回数が多く負担だった
- パイプラインを途中から再実行したい(できそうだが調べられていない)
- kedro-vizが自動で更新されない(再起動すれば読み込む)
- libをどこかに切り出したい(src側だけでなく、notebook側からの読み込みも想定する)
- ジョブの並列実行をしたい
- パラメータサーチで、optunaと連携したり
実験管理ツールとしてMLflowを導入した
![icon_mlflow.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F92368%2F3b53beb1-c62f-17eb-5f1c-11898ce9a54f.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=1966e4e70ba9fa824320c37ba72ff61c)
よかったこと
- 上記リンク参照
- せっかくMLflowに飛ばすように書いても、ノートブックごとボツになることがあった
- → 最初の最初の混沌としているときはスプレッドシート(、excel)で管理して、ある程度固まってきたらMLflowに移行、が良いかもしれない
残課題
- Kedroとの連携
- Kedroのparameters.yamlやpipeline.pyの情報を自動で連携したい
- journal versioningを利用とか?
CIツールとしてGithub Actionsを導入した
![icon_githubaction.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F92368%2Fbaf64d91-781a-ca0c-b8bc-682a91fe5b02.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=d7767a2aad7e2c0e1ea44666d4a8a19d)
よかったこと
- master(main)ブランチの動作担保ができた
- (毎回綺麗な環境で、コミットidも明確な断面で動くので)再現性のあるモデル作成ができた
残課題
- 毎回のビルドが重い。キャッシュをうまく利用すれば良い?
- 学習が重い・GPUを使う場合の構成は要検討
その他
- コードフォーマッタとチェッカーを導入した
- (参考)pre-commit時にformatterを実行する
- commitするタイミングでチェックが走るので、はじめから導入することが大事
- コンテナを利用している場合、コンテナの中にGitと共に入れる(Pythonが必要なため)
- CI側でのチェックとの使い分けを考える
- AWS Elastic BeanstalkでWebアプリ化した
- サーバーレスが良かったので、S3 + API Gateway + Lambdaで組みたかったが、ファイルサイズ制限で諦めた
- EFSを使えばいいが、VPC環境にしないといけないとかでちょっと...。
- 「サーバーレス(というか、リクエストがないときは寝てて欲しいだけ)でコンテナ」なら、GCPでCloud RunとかGAE?
- サーバーレスが良かったので、S3 + API Gateway + Lambdaで組みたかったが、ファイルサイズ制限で諦めた
おわりに
- 課題がまだまだ多いですが、データサイエンティストと伴走しながら早く確実に機械学習のサイクルを回すために、引き続き色々試していきたいと思います。
- ちなみに、この記事の内容は、友達と遊びで競馬のレース結果予測のモデルを開発してみたときについでに試して見たものです。コードは、もう少し綺麗にしたらたぶん公開します。(Kedroのデフォルトのディレクトリ構成からちょっと変えていたり。)