こんにちは。takapy(@takapy0210)です。
今回はProbSpaceで開催されていた「YouTube動画視聴回数予測」コンペに参加し、その中でMLflow Trackingで実験管理を行ってみましたので、簡単に振り返りをしようと思います。
ちなみに結果はPrublic 13th → Private 10thでした。
コンペの概要
YouTube APIとして公開されているメタデータを用いて動画の視聴回数を予測する、というものでした。
データには
- 動画コンテンツの質的指標となるlike/dislike・コメント数
- SEOとして重要とされているタイトル名・説明文・タグ・投稿時間
といった情報が含まれており、いわゆる"マルチモーダル"なデータセットで、かつ身近なサービスのデータということもあり、分析していてとても楽しかったです。
評価指標はRMSLE(Root Mean Squared Log Error)でした。
開催直後に1subだけしたものの、その後あまり参加できず、最後の10日間くらいでフルコミットしました。
youtubeコンペ1ヶ月振りにsubした pic.twitter.com/kuCVpHzfcA
— takapy | たかぱい (@takapy0210) 2020年6月19日
Solution
簡単にSolutionをまとめておきます。
モデルはLightGBM / Catboostを試しましたが、自分の環境ではLightGBMの方がスコアが良かった(CV / LB共に)ため、最終的にはLightGBM * 5モデルを用いました。
詳細はコードを公開しましたので、こちらを参照ください。
特徴量
日付
- 年, 月, 日に変換
- 曜日, 週末
- それぞれを三角関数を通して変換
- データ収集日と動画公開日の差分
- 1日あたりのlike数 / dislike数 / comment数
など
テキスト(主にtitle, description, tags)
など
BERTを用いてテキストの埋め込みを取得する方法は下記を参照にしました。
集計特徴量
- カテゴリごと
- 動画公開日の「年, 月」ごと
- 動画公開日からデータ収集日までの月数をbin分割したものごと
に sum, mean, std, ,max, min, meanと自身との差分を算出
など
CV
- KFold(k=5)
ここはもっと工夫の余地があったと思います。反省。
その他の工夫
自分の環境では、特徴量を増減させることでカテゴリごとのスコアがかなり変動しました。
そこで、LBのスコアが同等で使用した特徴量が異なる5つのモデルの中から、カテゴリごとに一番良いスコアを出しているモデルを選択し、そのカテゴリの予測値は選択したモデルの予測値を用いる、ということをしました。
結果的にはこれが一番スコアが良かったです。
カテゴリ毎にスコアを出して、それぞれベストなモデルを選択する、といった部分では後述するMLflow Trackingを用いることで比較的低コストで行うことができました。
comments_disabled, ratings_disabledそれぞれのコメント数やlikes/dislikesを予測して欠損値補完する、といった工夫は他の参加者の方も結構やっていたのですが、自分の頭からはすっかり抜け落ちていました。。。
MLflow Trackingによる実験管理
以降で簡単に MLflow*5の使用感などをお伝えします。
使用するにあたり、以下を参考にしました。
また、Podcastでも使用感などを話しましたので、よければ聞いてみてください。
ML flowとは
機械学習ライフサイクル(実験・再現・デプロイ)を支援するためのオープンソースプラットフォームであり、大別して以下3点の機能があります。
- MLflow Tracking
- 実験周りのコードや設定・結果の記録
- MLflow Projects
- どこでも再現できるようにするためのパッケージング
- MLflow Models
- モデルを各環境にデプロイするための方法やフォーマット
クイックスタート
公式のサンプル*6を動かしてみるのが一番手っ取り早いと思います。
以下で公式サンプルを少し改変したコードで簡単にみていきます。
pipでインストール後以下のようなサンプルコードを作成しこれを実行します。
実験のログを残す箇所は
- log_param
- log_metric
- log_artifact
- set_tag
あたりです。
import mlflow from mlflow import log_metric, log_param, log_artifact, set_tag if __name__ == "__main__": tracking_uri = '~/mlflow/mlruns' mlflow.set_tracking_uri(tracking_uri) mlflow.set_experiment("test-experiment") mlflow.start_run(run_name='run_name001') # Log a parameter (key-value pair) log_param('param1', 42) # Log a metric; metrics can be updated throughout the run log_metric('fold1_score', 9.99) log_metric('fold2_score', 9.92) log_metric('fold3_score', 9.78) # Log an artifact (output file) with open("output.txt", "w") as f: f.write("Hello world sample!") log_artifact("output.txt") set_tag('tag1', 'this is tag1') set_tag('tag2', 'this is tag2') mlflow.end_run()
例えば上記をsample.pyというファイルで保存している場合
$ python sample.py
その後、~/mlflow
に移動し下記コマンドでmlflowのダッシュボードが起動します
$ mlflow ui
この状態でブラウザでhttp://localhost:5000
にアクセスすると、上記で実行した実験の結果が表示されます。
コンペでの使用例と所感
今回のコンペでは、今までloggerで出力していたもの(CVのスコアなど)に加えて、モデルのハイパーパラメータなどを保存する形で使用しました。
以下のようにlog_param
にはCVやモデルのパラメータ、各種設定を辞書形式で保存し、
log_metricには、各CVスコアとカテゴリごとのスコア、tagにはLB
というKeyに対して、LBでのスコアを記載するように管理しました。
これにより、どのモデルが「どんなパラメータ, 特徴量, CVで学習させたもの」か、そして「それぞれのCVスコアとLBのスコア」を一覧で確認することができ、とても便利でした。
「その他の工夫」項でも述べましたが、このダッシュボードのおかげて、モデルごとのカテゴリのスコアが管理することができたので、「このカテゴリの予測値は、このモデルのものを使用する」といったことが比較的低コストで実践できました。
また、モデルごとにスコアを比較し簡単なプロットもできたりします。
今回紹介した管理方法(log_paramにどのような値を保存するか、など)はあくまで自分が試してみた方法なので、いくつも改善できる箇所はあると思います。今後も試行錯誤しながらより良い形にしていければと思います。
最後に
参加者及び運営の皆様、楽しいコンペをありがとうございました。
今回は本格的に参加してから締め切りまでの期間が短く、サムネイル(画像)の特徴量はほぼ手付かずでした。また、CVの切り方も特に工夫していなかったのが反省点です。
この辺りは他の参加者の方の解法を参考に勉強しようと思います。