2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
SageMakerで試行錯誤する推論パイプライン(全1記事)
リンクをコピー
記事をブックマーク
大谷拓海氏(以下、大谷):では「SageMakerで試行錯誤する推論パイプライン」という話をします。たぶん界隈だとGCPのほうが流行っているので、AWS使っている人は少ないのかなという気もしますが、AWSサービスの「SageMaker」を使って、推論パイプラインをいい感じに作る試行錯誤をした話をしていきたいと思います。
自己紹介です。moajoというハンドルネームでやっています。新卒2年目で、DeNAのAIシステム部のMLエンジニアリンググループで、ふだんはMLOps的なことをいろいろしています。趣味はクライミングで、これは断崖絶壁を登ったときの写真です。
今日お話しする内容ですが、何のプロジェクトかは具体的には言えないんですけども、DeNAの“試合“の動画を撮影して、その“試合“の動画をいい感じに解析して、チームにそれをフィードバックすることでチームを強化していきましょう、というプロジェクトになっています。
このプロジェクトはけっこう前からやっているプロジェクトですが、初期段階はPoCというかたちで、かなり少人数で進められていました。そのため、モデルの開発自体は普通にEC2インスタンスを生で立てて、そこの中でローカルのファイルシステムを使いながら、モデルを作って検証して、みたいなことをしていました。
徐々にそれが運用フェーズに乗ってきて、推論パイプラインを作りましょう、運用しましょう、というような話になっていきます。当初の実装では、推論JobがSQS(Amazon Simple Queue Service)にキューイングされるので、そのSQSのキューに対して設定されたオートスケールによってカスタムAMIを指定したEC2インスタンスが起動して、SQSからメッセージを取り出して処理するだけの、非常にシンプルな構成になっていました。
もちろん最初のうちはこれでぜんぜん動いていましたが、これだけシンプルな構成だと、徐々にいろいろと限界が出てきました。どういう限界かというと、“パイプラインのステップの密結合”というのは、推論のパイプライン全体が1つのAMIのエントリーポイントに指定されていて、1個の巨大なPythonスクリプトで実装されているような状態だったので、当然その各推論ステップを個別にバージョン管理したりとか、個別に入れ替えたりがけっこう難しい、バージョン管理が難しかったというのがあります。
さらにけっこうクリティカルな問題で、インスタンス選択もリソースを最適化することができない。というのは、パイプラインが1つのプロセスで動くので、各ステップに応じて適切なインスタンスタイプを割り当てることができないわけです。なので当然、一番重い処理に合わせてインスタンスタイプを選ぶ必要があります。
ステップによっては、GPUを使うものと使わないものがあります。GPUがあるインスタンスを使わなければいけませんが、そうするとGPUを使わない処理をしているときはまったくGPUが無駄になってしまう、ということもありました。
さらに、1つのそのPythonのプロセスで動くので、そのPython環境の中のライブラリのバージョンも全部共通にせざるを得なくて、そのあたりにつらみがありました。
このいろいろつらみのあるパイプラインを、SageMakerを使っていい感じにしていきましょう、ということが今日お話しする内容になります。GCPだとたぶんみなさん「AI platform」などを使っていると思いますが、それのAWSにあるやつだと思ってください。
SageMakerを導入してみました。まずとりあえず作ってみた構成が、こんな感じになっています。SageMakerの中に「Batch Transform」というサービスがあります。名前のとおりこれはバッチで推論Jobを走らせるものですが、これを使って構成しました。
バッチ推論によって、そのパイプラインの各推論ステップを1つのJobとして定義します。そのJobを別途立てたAirflowからキックする感じ。依存関係やリトライなどの処理はAirflow側で管理して、一つひとつの処理をBatch Transformにする感じの構成にしています。
GCPだとAirflow、マネージドでComposerなどがあると思いますが、AWSの場合はないので、自前でECS上にAirflowのインスタンスを立てて使っています。
この構成をいろいろ使ってみた感じどうだったか、という感想になります。まず1つは、Airflowの管理がけっこう面倒くさい。まあそれはそうなんですが、わざわざ管理のためだけにAirflowをECSに定義して運用するというのはちょっと面倒くさかったです。このあたりGCPだと、けっこう簡単にできると思うので、GCPいいなあ、という感想です。
あともう1つは細かいところですが、書き出し先のpathが分散していたという話で。書き出し先はS3上に出力していくんですが、model_nameの後にtimestampみたいなpathを切ってそこに書き込んでいましたが、そうすると1回のワークフローで書き出されたオブジェクトがいろいろなところに分散してしまうことになってしまって、それを一覧できないのが辛かったという話です。これは言われてみればそれはそうだ、という話ですが。
一番大きかったのは、Batch Transformへの書き換えが辛い問題があって。このBatch TransformはPythonのスクリプトで書きますが、model_fnやpredict_fnみたいな特殊な名前の関数を定義すると、SageMakerがそれをいい感じに呼び出してくれるというような仕組みになっています。なのでその形式に書き換えなければいけないんですが、今までベタ書きで書いていたスクリプトをその形式に書き換えるのはけっこう面倒くさくて、辛いという問題がありました。
Batch Transform自体も意外とイケてない部分がいっぱいありました。まず1つに「SageMaker Endpoint」という別のサービスがあって、(別の登壇者の発表で)SavedModel Predictionみたいな話がありましたが、それと似たようなサービスで、httpのAPIとしてモデルをサービングしてくれる機能です。実はこのBatch Transformは、(SageMaker)Endpointと同一のコードで利用できるようなサービスになっています。
このBatch Transformは内部的にはEndpointを建てて、そこにhttp経由でひたすらバッチでデータを飛ばして推論するような仕組みになっています。本来必要ないはずのhttpレイヤーが中に存在しているので、そこからエラーが出てきたりするわけですね。これがちょっと面倒くさいところの1つです。
たぶんこのあたりの仕様から察するに、ふだんEndpointを使うけれど、たまにバッチ推論したいときにコードを使い回せるようなユースケースを想定しているんじゃないかと思いました。
今回のケースの場合はそもそもEndpoint建てなくて、完全にバッチ推論しかしないので、実はユースケースとしてはあまりハマってないんじゃないかな、というのが感想です。
そこで、Batch Transformの代わりにProcessingという別のサービスを使いました。これは「SageMaker Processing」と言いますが、前処理、後処理みたいなのをするためのサービスです。任意のコードを任意のDockerコンテナ上で実行できるような、非常に汎用性の高い、シンプルなサービスになっています。
このサービスは前処理、後処理はモデルを使わない処理なので、そのモデル管理などがマネージドではなくなりますが、その代わり汎用的な任意のコードが書けます。
あと、書き出し先は変えたら快適になりました。1回のトリガーで走ったパイプラインの書き出し先は1箇所にまとめるといいです。これは当たり前ですね。
Processingを使うことで任意のコードが動かせるようになったので、今まで使っていたコードをほとんど修正せず、そのまま走らせられるようになりました。書き換えとか移行コストがかなり少なくて済んだので、非常によかったなという感じになっています。
これによって既存のパイプラインからの移行はかなり簡単にできていい感じになったんですが、また別の問題としてコスト的な問題がありました。Processingがスポットインスタンスに対応していないので普通にGPUインスタンスを立ち上げないといけないので、けっこうお金がかかってしまうという問題です。
そのあたりを改善することをさらにやっていきました。次の最適化はいくつか選択肢があると思いますが、まずAWS Batchというものを検討しました。これはECS上でバッチ処理するという、これはもうSageMakerではないんですが、こういうサービスもありました。これはスポットインスタンスも使えるので、今回のユースケースだと普通に使えるものになります。
もう1つはSageMaker Training job、TrainJobです。これは名前のとおり学習Jobを回すやつで、学習 Jobの中で推論してしまう使い方をします。これはどう考えても想定されている使い方じゃないんですが、意外といい感じに動いていて(笑)。スポットインスタンスも使えるし、インスタンスタイプも他のサービスより使えるタイプが多いです。そのため、汎用計算環境としてはかなり使い勝手がいいものになってます。
いろいろ検討して試しましたが、一番よかったのがTrainJobでした。TrainJobですが、いくつかクセがあって、出力が強制的に圧縮されてしまいます。圧縮ファイルに圧縮されてしまい、その設定が変更できないのがすごい使いにくいところです。そのため、マネージドな出力として出力するのではなく、その推論プロセスの中に自前でアップロード処理を書くみたいなことをしています。ちょっとダーティハックな感じがしてしまいますが、そういうことをしています。スポットインスタンスが使えるので、7割引きとかになって非常にお得感があります。
あと最後、データ入力です。プロセス走らすときにS3のオブジェクトをファイルシステムにマウントできる仕組みがあり、それをmanifest fileという形式のファイルで定義しますが、それに関してはProcessingと同じものが使い回せたので、ProcessingとTrainJobの移行コストはそんなに多くなかったと思います。
最後にまだ残っている辛さがあるので、ここだけ話させてもらうとmanifest fileが、実はローカルモードに対応してないという問題があります。ローカルモードというTrainJobをAWS上ではなくローカルで動かす機能が一応あるんですが、これがけっこうまだ不完全で、いろいろ対応していない機能があるので実はあんまり動かないみたいなことがあって。ローカルデバッグがしにくい問題があります。圧縮のオプションもどうにかしてほしいです。
ということで、まとめです。SageMaker、いろいろ使ってパイプラインを作ってみました。Batch Transformは実はバッチ推論にはあまり適していない場合があるので、気をつけてください。Processingは汎用的な計算環境としては使い勝手がいいです。
Training jobはある程度制約がつく代わり、スポットインスタンスが使えて実際は便利です。
結果的に、全部従量課金でマネージドにできたので、いい感じに動いています。発表内容は、以上になります。ありがとうございました。
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05