見出し画像

調理時間を機械学習で推定するようにした

こんにちは、 @yagitatsu です。Chompyでビールを頼むなら factory です。何気に餃子も売ってます。

最近調理時間を機械学習で推定するようになった話をしようと思います。 @metalunk にやってもらったやつをキャッチアップしながら( 社内wikiをおおむねコピペしながら。なんならがっつり加筆入りましたw) 書こうと思います。

なんで調理時間を推定するの?

元々は手動で調理時間を店舗ごとに設定できるようにしていて、それを信じていたのですが、以下のような課題がありました。

・予想注文時間が大きすぎると、早く料理ができていても、冷めてしまう可能性がある
・予想注文時間が短すぎると、クルーが早く到着して、料理ができるまで待たなければいけない

また、調理時間など、配達の各フェーズの予想時間の精度が上がると、今後まとめて配達するような機能を作る上で役立つのでは、という目論見もありました。そこで、「 配達効率を最適化する」 というテーマの第一歩として取り組み始めています。

昔書いたnoteの中だと以下のテーマの1つです。

3. サービスを持続的に運用できるように需給バランス・配達システムを最適化する

どうやったか① 分析・調査編

まずは、思いついた特徴量が調理時間と相関があるのか分析してみました。

・店舗
・時間帯 (ピーク/オフピークの違い)
・商品数
・料理の種類
・曜日

例えば、とある店舗の時間帯別で商品数をプロットしたバブルチャートがこちら。商品数がふえるとなんとなく調理時間がかかっている傾向があります

画像1

と、こんなかんじで分析と並行して、他社事例の調査をちょこっとやりました。以下が記事へのリンクですが、内容は割愛します。

■ Uber Eats
記事
スライド

■ Swiggy
記事

どうやったか② 実装編

前処理

まずは前処理として、調理時間が極端に短いものと、極端に長いものを外れ値として除外しました。

極端に短いものについては、忙しい時とかにパートナー(飲食店)のタブレットアプリで調理開始と調理完了を連続でタップしてるケースがあるため、除外する必要があります。

特徴量

以下の特徴量を実装しました。

・注文店舗の one hot encoding
・注文の値段
・注文時刻(e.g. 13.4時)
・注文に含まれる品数
・店舗の平均調理時間
・メニューの平均調理時間

特徴量として使うには、学習させる時も 推論させる時も参照できる必要があり、上の特徴量の中では「店舗の平均調理時間」と「メニューの平均調理時間」はその場で計算できないので、 どこか(Feature store)に保存されている必要があります。そのため,定期的に直近数週間の平均調理時間を計算し、Feature store (今回はFirestore) に保存する仕組みを作りました。

また、平均調理時間は Historical feature と呼ばれるような、長期間の集計の特徴量ですが、例えば直近30分間の平均調理時間のような特徴量も使うと精度が向上できるかもしれません。しかし今回は最低限の工数で、本番で使えるレベルの推論器を実現したいという思いで働いたので、手間のかかる特徴量は採用しませんでした。

モデル

GradientBoostingRegressor を使用しました。

採用した理由は

・実装が楽
・たぶんいい精度が出る
・Feature importance が見れて何が効いているのかわかりやすい
・Uber Eats の調理時間推定でも使われているらしい

「最初にサクッと実装するときにパッと選んだだけですが、結果的に十分な精度が出たのでよしとした」そうです。

評価

BigQuery を使ってデータセットを生成し、トレーニング、評価をしました。評価指標は以下です。

・Mean Absolute Error
 ー `|推定された調理時間 - 実際の調理時間|`
 ー 推定値と実際の値の誤差
 ー 単位は '分' だから、人間が理解できる値になる
・Mean Squared Error
 ー `|推定された調理時間 - 実際の調理時間|^2`
 ー Mean Absolute Error の二乗だから、大きく外すと値が悪くなる

比較対象は、これまで使っていた、DB に手動で設定した店舗ごとの平均調理時間を使った手法(Mean model)です。大きな改善が見られました。しかし 「@metalunk は機械学習の専門家ではないため、もっといいモデルを作れる人に改善してもらいたい」とのことでしたw

スクリーンショット 2020-11-26 14.01.44

特徴量の重要度である Feature Importance はこんな感じです。

画像3

システム構成 by @metalunk

これまで手作業で設定していた平均調理時間を機械学習で推定するにあたり、機械学習システムとしてはできるだけ小さく、複雑でないものにしたい、早く作りたい,ただし最低限の品質を達成したい思いがありました。

そのとき参考にしたのが以下の記事です。まずはこの記事における MLOps level 1 を達成することを目標にシステム設計をしました。

ML プラットフォームの利用を検討しましたが、Kubeflow 等の多くのプラットフォームは Kubernetes の上で動くものであり、Kubernetes を使っていない Chompy で ML システムだけを Kubernetes に載せるのはコストが大きいと判断し、使いませんでした。

それ以外にも、機械学習エンジニアがまだほとんどいないことから、できるだけ他のエンジニアたちに前提知識を要求しない、簡単で小さい仕組みにしたかったという理由で、ML プラットフォームを使っていません。

そして、以下の要件を満たすような仕組みを作りました

- dev と prod それぞれの Training pipeline があること
- Continuous training が実現されていること
- モデル、image がバージョン管理されていること

これらは CicleCI, GCS, GCR, CloudRun を組み合わせて、とても簡単な仕組みで実現されています。

やってみた結果

調理時間の予実差を何段階かに分けて色分けしたのがこちら。早いものが青、正常が緑、遅延が赤、というかんじ。

画像4

2020/10/21にリリースしてから、±5分以内の「正常」の割合がそれなりに増え、特に注文予想時間が長すぎて早く調理完了したもの(青い部分)が減ったように見えます。

逆に、注文時間が短すぎてクルーが待機になってしまうケースはまだまだあるので、要改善。

おわりに

最近やった調理時間の推定について紹介してみました。

配達をできるだけ効率的に行いたいから数理最適化を使って配送計画を立てたいが、まずは調理時間がわからないと始まらないということで、調理時間を機械学習で推論する仕組みを作りました。まだ他にも推論しなきゃいけないものがまだまだあります。

ということで、面白そうと思った方いたらぜひ話しましょう。


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