画像検索のワークフローの流れ

渡辺慎二郎氏:というところの話になってきて、これがワークフロー、それを毎日のように準備するという仕組みになります。先ほど見せた図で言うと、この部分ですね。

このワークフロー、今回ではComposerというGKEのマネージドサービスを使っています。これの中身、具体的な仕組みは置いておいて、流れをご紹介します。

まずBigQueryから、本日今時点で有効になっている、使える、発売になっている商品情報をダーッと取ってきます。だいたいこれが300万画像ぐらい。その日によって違ったりもしますが、だいたいざっくり300万だと思ってください。

その300万画像から物体を検出し、特徴量を抽出し……「AnnoyをBuild」って書いていますが、これは近似最近傍探索のインデックスを作るということですね、を行ないます。これら一連の流れを行ないます。

あとで紹介しますが、この流れはすべてGKEを使っています。できあがったインデックスをGCSにアップロードし、推論APIで動かすという流れ。今のこの流れがワークフローの流れになります。

おさらいです。BigQueryから情報を取ってダウンロード。商品画像をZOZOTOWNから……ストレージから取得し、その画像に対して物体検出・特徴量を抽出し、ここから近似最近傍探索のインデックスを作り、インデックスをGCSに保存し、推論APIで使用すると。

こういう流れで書くとなんか「こんな感じか」みたいな感じするんですが、作ってみるとなかなか大変でした。画像が100とかぐらいだったらわりとすぐできたとは思うんですが、300万になってくるとちょっと次元が変わってきます。やることやいろいろな考慮することが増えてきて大変でした。

Compser(AirFlowの特徴)

今回このワークフロー、まぁバッチみたいなものなんですが、選んだのはComposerというGCPのサービスです。中身はワークフロー系を触ったことある方はご存じだと思うんですが、Airflowを使っています。

これの特徴として、タスクを依存関係で構築できるというものがあります。「Aが終わったらBをする。CはAとBが終わったら動かす」みたいな感じで依存関係が作れます。Pythonで書けるのでMLエンジニアにとっても馴染み深いというのもあります。

その他の特徴は、スケジュールができて、監視も最初から入ったり、一応スケーラブルであること。処理が多ければたくさんインスタンスを増やしたりとかできるところ。管理UIがあるので今の状況がすぐ目で見てわかるというのがあります。

(スライドを示し)これが本邦初公開、画像検索が動いているAirflowの、まぁComposerの、そのDAG、依存関係ですね。

あまりにも小さいのでよくわからないかもしれませんが、ここらへんできっとBigQueryを動かして、ダウンロードをここらへんでして、ここらへんで物体検出をして、全部終わったら特徴量抽出をしてって感じですね。インデックスをビルドして、全部終われば推論APIに展開みたいな、そのような感じで一目瞭然という感じになります。

どこかエラーが出ていれば赤くなります。これはうちのメンバーが一生懸命作ったので、すべてグリーンに表示されてうまく動いているところです。1個だけここ黄緑ですが、これは今現在実行中という感じですね。こんな感じで見ることができます。

これは公式サイトに載っているAirflowのDAGの図です。こんなに複雑でも依存関係を作れるよということを言いたいんでしょうが、実際こんな依存関係があるとものすごく大変だと思うので、オススメはしません。こんなこともできるという感じですね。

ワークフロー開発のコツ

今回このZOZOTOWNの類似アイテム検索、画像検索のワークフロー開発は、すべて1人でやったわけではもちろんなくて、最初は初期メンバーがいて、途中から僕も入り、さらにそのあとMLOpsメンバーも参加してくれてリリースに至ったという流れがあります。そのなかで、API開発は似ているところもあるんですが、違うところもあって、そのコツみたいなものがあります。

その最初に出てくるコツなんですが、1つのサイクルをなるべく早くする。

現在、300万画像を今の一連の流れを動かすと、たぶん30時間ぐらいかかります。「ちょっとバグがあって修正します。また最初から実行します」というと、結果を確認するのにすごく時間がかかってしまいますので、なるべく早く、API開発でデバッグサーバーを動かして、そこですぐ確認できるように、ワークフローも同じようにする必要があります。

そのためには、インスタンスの性能を上げたり並列化したりだとか、開発時だけ少ないデータを使ってみるだとか、重い処理はGKEへ逃す。今回やっているんですが、GPUを使ったりして、GPUを使っている都合上GKEにしなきゃいけなかったんですが、GKEで自由にインスタンスを使うことで高速化をしたりしています。

あと差分とかですね。毎回300万画像を計算しないようにするとかというところがあります。あとSlack通知など。開発中でも、何か失敗したり遅かったりしたらSlackに流して、すぐ気づけるようにするのが大事なところになります。

ワークフローの難しいところ

実行にかかる時間。ワークフローの難しいところなんですが、当初よりもものすごく大変でした。気持ち的には思っていたよりも5〜10倍ぐらい大変な印象でした。それは、さきほども言ったのですが、実行に時間がかかるということもあります。

あとはスケールしすぎると、「スケールいっぱいさせて、いっぱい動かせばいいじゃん?」ってなるんですが、どこか1つ外部サービスとかに依存していたりするとそこに負荷がかかって動かないみたいなことがあります。外部サービスとか使っているところには、慎重に実行する必要があります。

外部サービス起因で止まるみたいなこともありますので。例えば、1回あったのがPythonの依存関係のライブラリをダウンロードするところでエラーになっているとかですね、それで全部止まってしまうことがあったりしたので、注意する必要があります。

あと、データは日々変わります。例えば300万画像と一言で言っていますが、ちょっと増えたりだとか減ったりだとかいうこともあるので、「今まで動いていたのに……」みたいなことが起こりがちです。毎日とは言わないですが、定期的にワークフローがちゃんと動いているかというのは確認していく必要があります。

今回はAirflowで説明しているんですが、AirflowがいいのかDigdagがいいのか、Digdagとかほかのワークフローもありまして、そこの良し悪しはいろいろ動かしてみて見極めるのがいいかなと思います。

監視の仕組みがすごく重要

まとめですが、MLサービス、MLを使ったサービスはだいたい対象データがものすごく多くなります。そうするとワークフローが必然的に必要になってくるので、これからやっていく人はぜひいろいろ触ってみてください。AirflowとかComposerですね。

実装コストは想像したよりも重くなると思いますので、API作りだしたのと同時ぐらいに、早い段階でワークフローも着手するのがすごく大事になってきます。すると、MLエンジニアもワークフローが動いていると安心して開発を進めることができるんじゃないかなと思います。

あと、監視の仕組みがすごく重要です。1回動かして1〜2時間待つというのは、忘れてしまって気がついたら次の日になったりしてしまうので、監視の仕組み、Slackと連携とかを早めにやって、迅速に開発できるようにするのがよいと思います。

最後ちょっと早口になってしまいましたが、ざっくりこんな感じになっています。一応、登壇は以上になります。

バージョン管理と実験の管理が課題

……からの、セルフで質疑応答に答えていきたいと思います。

「ワタナベって誰よ?」というのがあるのですが、僕です。あと「きゃー、しかじろーさん!」。ありがとうございます。shikajiroです。「@shikajiroの話おもしろいなー」ってつぶやいてくれた人が2人ですね。もっとしてください。「好きなシカは何鹿ですか?」。ニホンジカですね。あとは、ちょっと待ってくださいね(笑)、「ファッションを数値化する、かっこいい」。うん、かっこいいと思います。

「ファッション系だと画像は必須だろうなぁ」。うん、そうですね。むしろ画像しか触っていないぐらい。それは言い過ぎですが、画像を触る機会はすごく多いです。すると、必然的になんかインスタンス性能は求められますね。そしてお金がかかってくるというなかなか大変なところで、バランスとかはすごく大事ですね。

モデルのバージョン管理と実験の管理というものすごくいい質問が来ているんですが、Aki Arigaさん、「モデルのバージョン管理と実験の管理をどうしているんだろう」というのは、今回発表した内容はたぶんそのあとの話になっていて、モデルをしっかり管理したあとに、それを引き継いで我々研究開発エンジニアがちゃんとAPIにして出すみたいなところになってはいます。

だから、知らんわという話ではなく、ここはすごく課題になっていまして、とりあえずモデルのバージョン管理とかは命名規則とかでなんとかカバーしているんですが、今のテーマとしてバージョン管理と実験の管理に取り組んでいます。

具体的には、プロダクションではぜんぜん使っていませんが、KubeflowとかAI Platformあたりだとかをいろいろ試して触って、MLエンジニアと僕ら研究開発エンジニアが一緒に触っていろいろディスカッションして、「ここをこうしてほしい、ああしてほしい」「こうなったら使いやすい、開発しやすい」みたいなのをやりとりし合って、今試しているところです。今年中には動いたらいいなという気持ちですね。

データは毎回変わる

あとはですね……おっ、来た! Aki Arigaさん、いいですね。「データに依存するワークフローのデバッグやテストを書くのどうしていますか?」。これすごく難しくて、データって毎回変わるので、変わるというか要は発売する商品が変わってくるので、そのデータが必ずあることというのを確認できないです。「インデックスの中にこれがあること」みたいな。

なので、今のところ、あまりインデックスに入っている画像、特徴量の精度までは見てはなくて、例えばそのインデックスが正しく生成されているかという当たり前のところから、想定した量のインデックスになっているかとかっていうのを、ワークフローの中で一緒に動かしています。

ワークフローがインデックスを作った直後にテストも動かし、このインデックスはある程度妥当かを確認しています。将来的にはどんどん性能上げてテストの品質を上げていきたんですが、現状はそんなところですね。

あと、ワークフロー自体のデバッグとかは、さっき言った開発のデータの量をすごく少なくしてパパっと動かしたりしています。

「次の質問を最後にしろ」というのが来ました。やったね。これかな。Paraguasさん。「GKEはほかと比べてよかったと言っていたが、具体的にどのあたりだろう?」。

これは決めたのが開発当初あたりだったのであまり正確な情報ではないんですが、その当時一般的にGKEがKubernetes一番落ち着いているという情報だったから、ぐらいになります。

実際すべて、Azure、AWS、GCP、すべてでKubernetesを動かして安定したかどうかを確認したまではやっていなくて、「BigQueryもあるし、GKE安定しているらしいし」みたいなところからまずは始めていき、「もしよくなければ、ほかのも触っていこう」みたいな感じでいきました。最終的にはそのままどんどん突っ込んでいったというところは、正直なところあったりはします。

そういう感じでお時間が来ましたので、僕のお話はこれぐらいにしたいと思います。もしまた何かあれば、Twitterとかメンションいただけると反応したりしなかったりすると思います。ありがとうございました。