オレシカナイトデータコンペティションで優勝しました!
はじめに
サイバーエージェント主催の『オレシカナイト』データ分析コンペティションに参加し、優勝しました!
実際の分析時間はトータルで6時間程度でしたので初期の戦略で大きく結果が左右されるコンペでしたが、Kaggleエキスパートも数人参加する中で 非常にいい経験となりました。本記事では、運営の確認の上で、問題のない範囲でコンペの概要や解法を紹介します。
なお、今回のコンペで二位に輝いたupuraさんもこのコンペについて記事を書いております。
コンペの概要
オレシカナイトについて
オレシカナイトとは、AbemaTVなどを運営するサイバーエージェントのアドテクノロジー開発を行う部門主催の技術者向けの勉強会だそうです。機械学習に限らずアドテクに関連する様々なテクノロジーについての講演、LTなどが過去にも開催されているようで今回のコンペはそのスピンオフとのことでした。
ちなみにこの「オレシカナイト」の由来はコンペ開催前から気になっていたのですが、ゲーム「俺の屍を越えてゆけ」が元になっているようで「自分や他の人の失敗を糧にみんなに成長してもらえるよう共有する」ということが目的となっているとのことでした。
コンペについて
今回のコンペは実は全く同じデータ・問題設定の学生向けイベントが以前に開催されていたとのことで、その時の上位3名のスコアがリーダーボードに表示されているなど若干の緊張感を煽られるコンペでした。上位3名のスコアはかなり高く正直抜くのにかなり苦労しました。運営の方も、学生のレベルが上がっていると言っており、同世代の人間がデータ分析という世界でも活躍し始めていることを実感させられました。
本コンペの参加者は15名で、うち自分を含めた3人が学生でした。
本コンペではAbemaTVのデータを用いて、そこに配信される広告が実際にどの程度閲覧されるかを予測しました。
学習データは2ヶ月分与えられており、それを用いて直後の1週間分のデータに対して予測を行うというもので、時系列性を考慮することが一つの鍵となっていることが特徴的でした。
個人的には時系列性を考慮するまでには至らず、一般的なテーブルデータに対して行われるようなモデル作成を最後まで行なっていましたが、後から考えると時系列性を考慮した特徴を作れていればさらにいい結果が得られていたかもしれません。
データの内容としては、
- チャンネル内での広告の配信位置などを示す広告枠に関する情報
- CMの開始時刻などの配信タイミングに関する情報
など、時間に関する情報とターゲットを除いてカテゴリ変数のみで構成されたもので、カテゴリ変数の扱い方が問われたコンペティションでもありました。また、ほとんどの情報は匿名化、符号化されている点も特徴的でした。
データ数はtrainが543万レコード、testが59万レコードで全体としては300MBほどでしたが、全てがカテゴリ変数なため密行列表現でone-hot化すると自分の16GBメモリPCがメモリエラーを起こすくらいの大きさに膨れ上がります。そのためか、メモリ不足との戦いで苦慮している方も散見されました。
なお、このデータは実際のデータを間引いたりして、(おそらく)各カテゴリの間の偏りをならすなどの整形がされており実際の業務で触る際はさらに様々な困難があることが伺えるデータでした。普段のデータハンドリングはSQL(BigQuery)を用いているとのことで巨大データとの格闘というアドテクらしい話も垣間みえていました。
精度評価は広告配信という分野の性質から下記のような独特なものが用いられていました。
- ユーザをあるまとまりで分類し
- まとまりの中での予測閲覧数と実際の閲覧数との比をとり
- 比が0.9より大きく1.1未満であった時にそのまとまりの得点がえられるとして
- 全てのまとまりに対する、得点が得られたまとまりの比を最終的なスコアとする
という指標でした。この指標が使われる理由として、予測値が実際の値よりも大きすぎても小さすぎてもいけないというビジネス上の制約があるというものが挙げられていました。すなわち、
- 大きすぎた場合、本来の料金より低い料金で広告枠を提供してしまったことになり割引に当たる、またその広告枠を他の広告に提供できたはずなので機会損失と捉えることもできる。
- 小さすぎた場合、一定の閲覧数以上を提供するという契約に違反したことになり違約金が生じる
という不都合があるとのことで、閲覧数予測はビジネス的にも大きな価値を持ったタスクであることが伺えました。
このスコアを大きくすることが今回のコンペの目的で、最終的な優勝もこのスコアを元に決められていましたが、参考値としてMSEも計算されてリーダーボードに表示されるようになっており、これを一番低くした3名にも商品があるということでした。僕は欲張りなのでスコアの最大化とMSEの最小化を同時に行なって両方で同時優勝を目指していましたが、このスコアをあげるとしばしばMSEも上がるといった逆転現象が起きることも今回のコンペの特徴で、参加者を大いに悩ませた一因でもありました。
また、リーダーボードのスコアはそのまま最終的なスコアに用いられるものでしたのでLBプロービングなどが行えるというやや不健全なものでしたが、ルールの範囲内でしたので有効活用させていただきました。
自分の取り組み
解法
自分の取り組みはかなりオーソドックスなテーブルデータに対する手順を踏んでいたかと思っています。
特徴は、
- カテゴリカルな特徴はそのまま用い、時間に関する情報のみ曜日・時間(hour/min)のカテゴリ特徴に直したもの
- それらカテゴリ特徴をTarget Encodingしたもの
の二種類を用意しました。upuraさんの解法にあるような時間の循環性を意識したエンコード手法には思い至らなかったため時間に関しては非常にシンプルにカテゴリ化しています。
やや特徴的な点があるとすれば、Target Encodingではmeanだけではなくmax、std、median、skewも計算していたことと、これは主に時間的な制約が厳しくて手が回らなかったためですがTarget Encoding時に弱リークが発生しないようにCVで計算するなどの工夫は行なっていないことが挙げられます。
また、この二種類の計算方法を、
- 与えられた2ヵ月分のデータ全てに対して計算したもの
- テストデータに近い1ヵ月分のデータのみに対して計算したもの
の二種類を用意しています。すなわち2×2の計4種類のデータセットを使っています。
これらのデータをLightGBMに5fold CVで流し、出てきた結果をブレンデッドアンサンブルしたものが最終的な提出ファイルとなりました。LightGBMのハイパラチューニングなどは手作業で少し行なったのみで概ね、Kaggleのメルカリコンペに参加した際に用いていた値を流用しました。
結果として、最終的には性質の異なるデータセットを複数用意できたことが勝因と考えています。
戦略
upuraさんは実応用の観点も持ってシングルモデルにこだわっていらっしゃったとのことでしたが、自分はのっけからアンサンブルする気満々でしたのでいかに多種の性質の違うモデルを作れるかどうか、という一点にかけた戦略をとりました。このためには実験量がある程度ものをいうと考えていたため、自分のローカルPC(MacBook Pro) + Google Colaboratory4枚(自分の個人のアカウントと大学での個人アカウントでそれぞれCPUとGPUの2枚ずつ)の5環境での並列実験を行いました。
具体的には、ローカルでは一番勝率が高そうな取り組みを計算しつつ、ColaboratoryではMLPや線形モデル、CatBoostなどJust Ideaだけどモデルの多様性に寄与しそうなアイデアを試していくということを行いました。Colaboratoryで計算した結果で最終的なモデルに寄与したものは実はなかったのですが、時間がかかりそうなアイデアも他の環境に投げれば手元で他のことができるという安心感から試したいことを思いっきり試せたのも優勝の遠因かと思います。
なお最終的にはLightGBM一本に絞ったものの一番最初は非常に素朴にone-hot表現+Ridge回帰からはじめ、多項式ベースの手法もいくつか試していましたがどれもうまくいきませんでした。これは、ほとんどすべてがカテゴリ特徴だったからと考えられますが、単純な線形モデルでもある程度の精度を出せるだろうと考えていたので結構面食らいました。
所感
自分はこうしたオフラインコンペに参加するのは初めてでしたが、新たな楽しみを覚えてしまいました。Kaggleとはまた少し違った能力が問われるため新鮮な気分で臨むことができたのですが、ちょうど手の速さを強みにしていきたいと考えていたところでしたので自分の現状を評価する上でも非常にいい機会となりました。
個人的には、今回のように限られた時間の中で競いながら精度を高め合うというのはかなりうまく自分にハマっていると感じたので、今後もKaggleなどのコンペでも同じチームの人と1日かけて競い合いながら精度を向上させるようなハッカソン的な枠組みを取り入れていけたらと感じています。
運営の方々のサポートも素晴らしく、1日を快適に過ごすことができました。
個人的にはSlackのtimesチャンネルで騒ぎながら競技に臨めたのが非常に楽しかったです。このような場を提供してくださった運営の皆様方、そして競技を盛り上げてくださった参加者の皆様、ありがとうございました。