every Tech Blog

株式会社エブリーのTech Blogです。

MLflowとOptunaを使ってMLOps環境を構築してみた

はじめまして。2020年4月からエブリーに新卒で入社した伊藤です。 データエンジニア・データサイエンティストとしてデータ関連部門に所属し、日々データ業務に関わっています。

データ業務の1つである機械学習モデルの開発は、実験環境でモデルの精度を確認した上で本番環境に適用するプロセスを経ます。

今回は機械学習の実装で利用したMLflowとOptunaを組み合わせが、モデルの開発・運用・レビューで高いアジリティを提供できると分かり、導入事例として紹介できたらと思います。

取り組んだ問題

最近のデータ業務で、DELISH KITCHENユーザの過去の行動を分析し、ある特定のアクションが将来どの程度の確率で行われるかを機械学習で予測する、という問題に取り組みました。

ユーザがDELISH KITCHENをどのように使っているのか(レシピのお気に入り登録など)という情報は、集計された状態でデータウェアハウスに蓄積されています1

まずはそれらを抽出し、予測を行うための特徴量データセットとして用意した後、パラメータの調整や特徴量の取り方などを試行錯誤しつつ、実験環境で機械学習モデルを構築しました。

大学の研究やデータコンペティションでは、多くの場合高い精度のモデルができたら一旦区切りとなりますが、企業で開発を行う場合にはこれを実際のビジネス施策でも使う必要があります。

そのためには、実験環境で行った「特徴量の抽出」→「モデルの学習」→「モデルの予測」→「最終結果の出力」という4つの段階が本番環境で1つのパイプラインとして自動化されており、かつ持続的に運用できる状態でなければなりません。

MLOps

ここでMLOpsという概念を紹介したいと思います。

MLOpsとは機械学習のライフサイクルの管理やその環境を指す考え方で、機械学習(Machine Learning)と運用(Operations)を組み合わせた言葉です。

MLOpsの考え方に基づくと、上に挙げた4段階それぞれの品質を持続的に維持・改善しており、かつ全体としても1つのパイプラインとして運用できる環境の構築が重要になります2

特に、ユーザ行動を使う今回のようなケースでは、予測したい行動データが日々更新され、実験では良い結果が出ていたモデルも時間が経つと「古い」モデルとなってしまうため、新しいデータを使ってモデルを定期的に更新していかなければなりません。

さらに、将来の研究でさらに良さそうなモデルが見つかった場合は過去のモデルと比較してより良いものをパイプラインに組み込めるような設計になっていると、より効果的な運用が可能になります。

このようなMLOps環境を実現するため、今回はMLflowとOptunaという2つのツールを組み合わせて活用しました。

MLflow

MLflow3とはDatabricks社が開発した機械学習のライフサイクルを管理するためのプラットフォームです。

MLflowを使うと、学習結果の保存や過去の学習結果との比較が簡単に行えるようになります。

簡単な例としてロジスティック回帰によるアイリスデータセットの分類問題を考えると、実行環境によって設定は多少異なりますが、「ハイパーパラメータ」「予測精度」「学習モデル」の3つが対応した学習結果をおおよそ次のように登録できます。

from sklearn.linear_model import LogisticRegression
import mlflow
import mlflow.sklearn

with mlflow.start_run():
    lr_c = 0.1
    model = LogisticRegression(C=lr_c).fit(x_train, y_train)    
    score = model.score(x_test, y_test)
    
    mlflow.log_param('C', lr_c)
    mlflow.log_metric('Mean Accuracy', score)
    mlflow.sklearn.log_model(
        sk_model=model, 
        artifact_path='mlflow_demo', 
        registered_model_name='lr_iris'
    )

登録された学習モデルはMLflowを通してバージョン管理され、バージョンを指定したロードもできるため、新しいモデルと古いモデルとの性能比較を行ったり、時期や状況に応じたモデルの入れ替えも可能です。

No Image

それぞれのバージョンに対して、パラメータと予測精度が保存されています。

No Image

Optuna

Optuna4は、Preferred Networks社が開発したハイパーパラメータチューニングのためのフレームワークです。

本来ハイパーパラメータチューニングは、パラメータの値を変更した学習結果を確認しながら最適値を見つける、非常に手間の掛かる作業です。

そのため、パラメータそれぞれに候補となる値を用意し、それらの組み合わせを全て試して最適なものを見つける、グリッドサーチと呼ばれる方法が主に使われていました。 しかし、グリッドサーチでチューニングの工程は自動化できるものの、パラメータの種類・候補が多いほど組み合わせが爆発的に増加するため探索に時間がかかってしまう、そもそも候補に含まれない値は探索できない、といった問題がありました。

Optunaでは、探索する値の候補を探索範囲として渡すことが可能です。 また、過去の探索結果に基づいて次に探索すべき範囲を判断するようなアルゴリズムが実装されているため、指定された範囲に含まれる値全てを試さずに、より確からしい最適解を導き出すことができます。 これにより、Optunaを使うとグリッドサーチよりも柔軟で効率的なハイパーパラメータチューニングが実現できます。

もう一度ロジスティック回帰によるアイリスデータセットの分類問題を考えます。 先ほどの例ではハイパーパラメータ C を決め打ちで設定していましたが、ここではOptunaを使い交差検証によるチューニングをしてみます。

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
import optuna

def objective(trial):
    lr_c = trial.suggest_loguniform('C', 1e-4, 1e2)
    model = LogisticRegression(C=lr_c)
    score = cross_val_score(model, x_train, y_train, cv=3)
    accuracy = score.mean()
    
    return accuracy
  
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=10)

best_params = study.best_params

最適なパラメータは best_params として辞書形式で得られるので、その後は最適なパラメータでモデルを学習 → MLflowで結果を保存、という流れになります。

今回モデルの学習に用いるユーザ行動は時間的に変化するデータであるため、モデルの品質を持続させるには定期的に新しいデータで再学習する必要があります。 Optunaを使うとデータに応じて適切なハイパーパラメータを自動的に探索・決定できるようになり、 手動による介入を行わずに一定レベルの品質でモデルの再学習を行えます5

MLOps環境の構築

それでは、MLOps環境をどのように構築したのかを紹介したいと思います。 エブリーではデータ分析基盤としてDatabricksを使っているため、Databricks notebookをベースに環境構築を行いました。

tech.every.tv

まず、一連のパイプラインを「特徴量の抽出」「モデルの学習」「モデルの推論」「最終結果の出力」という4つのステップに分け、それぞれを順番に実行できるようなジョブを作成しました。

肝となるのが「モデルの学習」と「モデルの推論」のステップで、ここでMLflowとOptunaを活用します。

「モデルの学習」では、MLflowに登録されている最新の前処理モデルと予測モデルの2種類をロードし、検証用のデータを使ってこれらのモデル性能の検証を行います。 検証結果が良ければそのまま次のステップへ進みますが、もし検証結果が悪いようなら、再学習するためのタスクを呼び出してこれらのモデルをアップデートします。

モデルの再学習では、実験環境には存在しない本番環境の最新のデータを利用したハイパーパラメータチューニング、モデルの学習を行います。

チューニングするパラメータはOptunaに登録されており、探索はOptunaに実装されているアルゴリズムに従って行われるため、データに合わせた柔軟なチューニングが自動で行われます。 これにより、データが更新される度に必要となるハイパーパラメータの検証工程が減り、パイプラインの維持・改良をスムーズにできるようになります。

再学習後に得られたモデルはMLflowでバージョン管理し、必要に応じて過去のモデルとの比較もできるようにしました。

「モデルの推論」ではMLflowを通して最新のモデルをロードし、最新の行動データに対する予測を行います。 1つ前のステップでモデルの性能に関する検証を行っているため、ここで得られる予測は(完全ではないかもしれませんが)ある程度品質が保証されたものになります。

まとめ

以上、実験環境で機械学習モデルを作成するところからMLOps環境に昇華させるまでを、簡単に紹介させていただきました。

ここで紹介したパイプラインは現在バッチとして登録されており、定期的にモデルの更新とユーザ行動の予測が行われています。

現時点で運用を始めて数ヶ月が経ちましたが、現在も当初の予測精度付近で安定しており、構築した環境がモデルの品質維持に役立っているのでは、と考えています。

今回の業務を通して、MLflowとOptunaの有効性を改めて確認できたとともに、エブリーに入社するまではあまり経験してこなかった実運用環境の構築について新しく学べました。

今後は、MLOps環境を運用しつつ、新たなビジネス施策にも貢献できれば嬉しく思います。

ここまで読んでいただきありがとうございました。

データ分析が捗るDatabricksのススメ

はじめに

はじめまして。2020年4月にエブリーに新卒で入社した吉田です。
私はデータエンジニア・データサイエンティストとして入社し、データ関連部門に配属して日々データ業務に関わっています。
私達のチームでは、巨大なデータを集計・分析するための基盤としてDatabricks社のDatabricks を使用しています。
今回の記事では、私達の業務におけるユースケースを交えながら、Databricksの利点や、活用方法を紹介できたらと思います。

Databricksとは

DatabricksはApache Sparkベースの分析プラットフォームであり、データ分析の際に行う

  1. Data Sourceからデータを集約
  2. 分散処理によって高速にデータを整形
  3. 分析
  4. 可視化や集計したデータをData Lakeに保存

といった流れをDatabricks notebookを用いて記述し、Spark clusterを用いた高速な分散処理が可能です。 データ分析によく使われているツールであるJupyter notebookと同じような感覚でビックデータを扱え、インラインでの図表表示などにも対応しています。

またSpark clusterの設定やワークスペース、学習済み機械学習モデル、Jobの管理をWebUIを用いて行え、非常に扱いやすい分析プラットフォームです。

エブリーでDatabricksをどう使ってるか

私達のチームではデータ分析をする際に

  1. Arm Treasure DataやS3、BigQuery、Deltaからデータを抽出
  2. データを加工し、Deltaに保存
  3. Deltaから加工済みデータをTreasureDataに保存
  4. TreasureDataをRedashから読み込み可視化

という流れを行っています。
この2の工程でDatabricksのnotebookを用いています。
No Image

SQLでは複雑なクエリになってしまう処理をDataFrameとして処理すると、コードを簡潔にでき可読性が上がります。

なぜDatabricksなのか

Databricksを扱うにあたり便利な機能を紹介していきます。

豊富なData source

DatabricksではS3上のcsvファイルやBigQuery、TreasureDataのデータ等をSparkを用いて高速に取り込めます。

特にDatabricks社が公開しているオープンソースのストレージレイヤーであるDelta Lakeを用いると、データへの信頼性とパフォーマンスが高まります。 Delta Lakeには

  • ACIDトランザクションによりデータの整合性を確保
  • スキーマの適用によりデータの過不足や不正を検知
  • スナップショット作成によるロールバックや過去データの参照
  • Sparkの分散処理による高速な読みこみ

といった機能が存在します。 これらの利点を、Spark Dataframeへの簡単なAPIによって使用できます。

// 書き込み
sparkDataframe
.write
.format("delta")
.save("delta/path")
// 読み込み
val sparkDataframe = spark.sql("""
select * from delta.`delta/path`
""")

ひとつのnotebook上でscala,python,sql等を混ぜて実行できる

Databricksのnotebookではセルの先頭で%python%scalaといったマジックコマンドを記載すると、notebookに指定した言語とは別に、セル単位で使用する言語を選択できます。
pythonはデータを柔軟に扱え、データ分析において強力な言語ですが、型安全でない、scala等に比べて処理速度に劣るといった欠点が存在します。
そこでノートブック中で高速にしたい処理をscalaで処理し、分析部分をpythonで扱うといった運用が可能です。

履歴管理機能や同時編集機能が便利

Databricksにはnotebookの履歴を管理する機能や、複数人で同時に1つのnotebookを編集する機能が備えられています。
履歴の管理機能ですが、例えば

  • notebookをリファクタリングしていたら重要なセルをまるごと消去してしまった
  • データをいじくり回していたらnotebookがわけわからなくなった

といった場合に、自動的に保存されている履歴から任意の履歴の復元が可能な機能です。
この機能はgitでの管理に関係なく履歴を保存してくれるため、わざわざgitで管理するほどでもない簡単な分析でも気軽に利用できるのが利点です。

次に複数人でのnotebook編集機能ですが、Databricksでは自分が見ているnotebookを他の人が閲覧している場合、閲覧しているユーザ名とそのユーザがどのセルを見ているかがセルに色がつき、わかるようになっています。
この機能を活用すると、複数人でnotebookを見ながら分析方法についての議論等が簡単に行なえます。

Gitによってバージョン管理が可能

DatabricksのnotebookではIpython notebookとは異なりセルの出力結果等がファイルに記載されないため、gitを用いたコードのバージョン管理が可能です。
これにより、一般的なコード開発と同じような

  1. コーディング
  2. P/Rを送る
  3. レビューしてもらう
  4. 修正
  5. 取り込み
  6. 運用

といった流れをデータ分析にも適用可能です。
そのため、クエリミスや不適切なデータ処理を可能な限りなくせ、また、より良い分析方法を協議できます。 それにより、信頼性の高いデータ分析を行えます。 No Image

また、gitホスティングサービスに連携したCircleCIを用いると、notebookのP/Rマージ時に本番環境への自動デプロイや、Job作成が行えます。 No Image

notebookをバッチスクリプトとして扱える

Databricksで作成したnotebookはそのままDatabricks上でバッチJobとして登録できます。

使用するクラスタ構成や、実行するnotebook、スケジュールやリトライ回数等を簡単に設定できます。

notebookをバッチとして登録する利点として、 - 過去の実行結果がnotebookの出力としてセル単位で残る - セル単位で実行され結果が残るため修正が容易

というものがあります。

実行結果がセル単位で残るため、各セルごとの実行時間を比較してパフォーマンスが悪い処理を容易に特定可能で、パフォーマンス改善中の比較データとして過去の実装の結果を参照できます。
私達のチームでは、バッチのアラートをSlackに通知しており、アラート発生 -> セル単位の処理結果を見てエラー箇所を特定しリカバリという流れで安定したバッチ処理の管理を行えています。 No Image

まとめ

以上、エブリーでのDatabricksのユースケースと利点を簡単に紹介させていただきました。 Databricksを使用すると

  • Spark clusterによるスケーラブルな計算基盤
  • Delta lakeによるデータの安全性
  • データ分析の信頼性

を確保できます。
こちらはあくまで一例ですが、Databricksの利点等を知っていただけたのであれば幸いです。

テックブログ始めます

 皆さん、こんにちは。株式会社エブリーは、『動画を通じてもっと楽しく、もっと充実した毎日に』をミッションに掲げた、『動画』『リアルデータ』『AI』のメディア企業です。 株式会社エブリーのエンジニア文化を紹介するために、技術ブログを発信していくことになりました。

はじめに

 動画配信と言っても、動画編集サポートツール、動画エンコーディングインフラ、機械学習、ビッグデータ処理基盤、メディア運営をサポートする管理画面など、利用している技術は多岐に渡り『技術のるつぼ』と言っても過言ではありません。

採用技術

  • サーバサイド:Golang
  • フロントエンド:Swift、Kotlin
  • Webフロント:Nuxt、React、Angular
  • データ基盤:Arm Treasure Data、BigQuery、Databricks
  • インフラ:AWS、GCP
  • プロジェクト管理:Asana、Confluence

対象ドメイン

  • 料理、育児・子育て、ニュースエンタメ

エブリーに在籍するエンジニア

 これまであまり外部に公開していなかったのですが、エブリーには個性的なキャリアを持つエンジニアが在籍しています。

  • AR黎明期にセカイカメラを作っていた人
  • 金融系企業や教育系企業でCTOをやっていた人
  • ソーシャルゲーム企業の事業責任者をやっていた人
  • アドテク企業で爆速な配信サーバーを作っていた人
  • GAN(機械学習)でリンゴの画像生成をひたすら創っている人

 エンジニアが『動画を通じてもっと楽しく、もっと充実した毎日に』を目指して、会社のミッションをどのように支えているか、紹介していきますのでぜひお楽しみに!