6日目: Ottoコンペの振り返り
11月から参加していたKaggleコンペOTTO – Multi-Objective Recommender System(通称Otto)の期間中にあった出来事について振り返っておく。
全体の感想
一言で感想を言うと、全体的にかなりハードなコンペだった。特に後半は後述するcandidate-rerank modelのゲインが全く得られず、LBで他の参加者がどんどん駆け上っていくのを見たり、ディスカッションで結果が共有されるたびに、彼らと自分の違いがどこにあるのか全く分からないまま苦しむことになった。
ディスカッションを見る限り、おそらくそれなりの数の参加者がcandidate rerank modelと呼ばれていた2-stageのモデルを採用していたと思う。 一方で、コンペ終了前1週間の時点で公開ノートブックのスコアを有意に上回るゲインを得られていたユーザはわずか4.12%と非常に限られており1、このタイプのモデルをきちんと設計するのはそれなりに難しそうに見えた。
残念ながらこの記事を最後まで読んでもこれに対する解答はない。コンペ終了後に共有されるであろう各チームの解法にヒントがあることを祈る。
CVのリークについて
個人的に後半苦しんでいた理由の一つに、CVのリークがあった。 本コンペのデータは時系列なので、未来のイベントがラベルになっており、うっかり学習データに未来のデータを含めてしまうと、CVで本来得られるはずのないゲインが観測できてしまい、モデル選択を誤る危険がある。
自分は最初、学習データへの未来データのリークについてはそこまで厳密に管理していなかった。具体的に言うと、2段目のモデルの学習データの1つ(後述するco-visitation matrix)に、本来学習時点で与えられるはずのない未来のデータを含めてしまっていた。後で調査してわかったことだが、ここには正解データの時系列を直接的に予測するための情報が含まれており、それによってCVで本来得られるはずのないゲインを観測していた。このため「CVではゲインが出るがLBではでない」問題に悩まされていた。
余談だが、後述するデータ設計ではまだ未来データをモデルの学習に使っている部分がある。これは意図的にやった部分もあるが、リークあり・なしの場合の影響について確認せずに用いており、自身の経験不足を露呈する結果となった。「CVを設計する時はリーク対策に細心の注意を払うべき」というのは、頭では分かっていてもきちんと実践するのは難しい...。
データ設計について
このコンペを難しくしているもう一つの理由に、学習・評価・予測データの設計が参加者にある程度委ねられていた点も挙げられると思う。
前述したCVのリークの話とも関連するので、以下では具体的なデータ設計の内容について記載する。振り返りの内容とは逸れるので興味がなければco-visitation matrixのパートまで読み飛ばしてもらって構わない。
共通の設計
- trainデータを1週間ごとの4つのtermに分割する(term 0-3)
- 各termにおけるsession2をランダムに2分割し、前半をquery、後半をlabelと呼び区別する。この命名は、前半のデータが主にモデルの学習に使われ、後半をラベルとして与えることに因んでいる。
testデータはqueryのみ与えられており、test term(term 4)におけるlabelを予測することが本コンペの主な課題である。
学習スキーム(candidate generator; 1段目)
- 2段目学習用の特徴/ラベル生成: term0-2のqueryおよびterm0-1のlabelを使ってco-visitation matrix(後述)を作成する
- 2段目評価用のラベル、および2段目の予測モデルの学習用の特徴/ラベル生成: term0-3のqueryおよびterm0-2のlabelを使ってco-visitation matrixを作成する
- 2段目の予測用の特徴/ラベル生成: term0-4のqueryおよびterm0-3のlabelを使ってco-visitation matrixを作成する
学習スキーム(candidate reranker; 2段目)
- 評価用モデルの学習: term2-3のqueryを特徴量抽出に用い、term2のlabelで学習する
- 評価: term2-3のqueryを特徴量とし、term3のlabelを予測する
- 予測用モデルの学習: term3-4のqueryを特徴量抽出に用い、term3のlabelで学習する
- 予測: term3-4のqueryを特徴量とし、term4のlabelを予測する
1, 3では2段目のモデルの学習を2回行っているが、これらは一般的な機械学習タスクにおけるcross fold学習と全データ学習にそれぞれ対応するものである。すなわち、1はモデルのハイパーパラメータ選択のための学習であり、3は課題ラベルの予測用の学習である。一般的に、時系列モデルは予測対象のデータと学習に使用したデータの時系列が近い方がドメインシフトの影響が小さいと考えられるためこのようなアプローチを用いた。
なお、前述したように1, 3において特徴量抽出に未来のデータを使っているが、これは本来望ましい方法ではない。「学習時と予測時で特徴量の意味を同じにしたい(変にドメインシフトさせたくない)」ということを意図してやったことでもあるが、コンペ終盤にサブミッション数も足りなかったこともあってリークのあり・なしの影響についてはは未確認であった。このように論理的に間違った手法を効果の確認できないまま実験で使用するのはただのギャンブルなのでやめておいた方が良い。
Co-visitation matrixについて
1段目のモデルにおけるco-visitation matrixについて説明する。この手法は[Vladimir Slaykovskiy]で提案されたもので、「あるユーザが期間Tの間に2つの商品を同時に参照・購入される頻度」をカウントしたものである。形式的には条件付き確率P(j | i; abs(ts(j) - ts(i)) < T)
をモデル化したものとみなすことができる。これは言語モデリングでいうバイグラムに似た概念である。バイグラムが隣接する2単語の出現頻度をカウントするのに対し、co-visitation matrixは一定期間の間に同時に参照・購入した頻度をカウントする。このco-visitation matrixが非常に強力で、[Chris Deotte]ではこれを使った予測モデルでLB0.575のスコアを出しており、コンペ中盤〜終盤において多くの参加者のモデル設計の手本となった。
この手法は時系列におけるイベント間の関連を単純にモデル化したものであるが、Ottoコンペのような大規模なテーブルデータの分析タスクにおいて「計算コストが小さい割にそこそこ有効な手法」として効果が実証された。同様の時系列を予測するタイプのタスクで試す「最初の一手」の一つに加えて良いだろう。
プライベートシェアによるチート疑惑
一部のTwitterユーザはタイムラインの祭り状態で認知されたかもしれないが、本コンペではあるユーザが所属する複数のチームから「特定のチームメイトが不正に関与している疑いがある」という報告があった3, 4, 5。
これらの報告から明らかになった不正行為の実態は以下のようなもと推察する。
- 一部のチーター同士で協定が結ばれており、それぞれが別々に一般のユーザによるチームに紛れ込んで所属している
- チーター自身は何もせずに、チームメイトの作ったコードや提出ファイルをチーター仲間からシェアしてもらい、所属するチームにはあたかも自分で作ったものであるかのように振る舞う。またチームメイトの作成したコードや提出データをこっそり他のチーター仲間に横流しする。
- チーターは場合によっては単独でコンペに参加し、チーター仲間からシェアされたコードや提出ファイルを使ってソロメダルを獲得する
- 上記の行動を各コンペごとに行い、メダルや賞金を荒稼ぎする
今回不正の疑惑がかけられた2名のユーザはそれぞれmasterとgrand masterの称号を有しており、特に後者は最高総合順位が11位という上位ユーザである。不正の報告が事実だとすると、これらのユーザは数年間にわたって不正を繰り返してきた可能性が高く、不正が行われていた期間と不正に(意図的、無視式的に)関わったユーザの数からしておそらくKaggle史上最悪のものになる可能性が高い。
その他のトピック
他にもコンペ開催期間中に個人的に以下のようなトピックがあったが詳細は省く。それぞれTweetのリンクになっているので、興味のある方は参照していただければ幸いである(といっても大したことは呟いていないので恐縮だが...)。
最後に近況として、Twitterでも呟いたが、チート行為に関わる一連のコメントとディスカッションでメダルを貰えたこともありdiscussion masterになった。一方、コンペではmasterにはなれない見込みなのでこのブログのタイトルはそのままになる予定である。
それでは、Happy Kaggling!
- https://www.kaggle.com/competitions/otto-recommender-system/discussion/377149↩
- このコンペにおいてsessionとはいわゆる通常の意味でのセッション(webブラウザのセッション)ではなく、ユーザIDを表す。↩
- https://www.kaggle.com/competitions/otto-recommender-system/discussion/381318↩
- https://www.kaggle.com/competitions/otto-recommender-system/discussion/381321↩
- https://www.kaggle.com/competitions/otto-recommender-system/discussion/381360↩