Kaggleの『Learning Equality - Curriculum Recommendations』コンペティションで金メダル(6位/1057チーム)を獲得しました!
はじめに
こんにちは、エムシーデジタルでデータサイエンティストをしている齋藤です。2023/03/15までKaggleで開催されていたLearning Equality - Curriculum Recommendationsに参加し、1057チーム中6位となりました。Kaggleに投稿したSolutionはこちら。
ここでは以下について簡単にご紹介したいと思います。
- コンペ概要
- 私の取り組み
- 上位チームの解法
コンペ概要
コンペホストのLearning Equalityは世界中誰でも質の高い教育用コンテンツへのアクセスができるようになることを目的としている団体です。Learning EqualityはKolibriというプラットフォームを運営しており、本コンペで使われているデータセットはここから取得したものです。
本コンペのタスクは、K-12と呼ばれる米国等で用いられている幼稚園〜高校3年生までの教育用カリキュラムにおいて、“topic"と"content"をマッチングすることです。今回の範囲ではSTEM (Science, Technology, Engineering, Mathematics)領域でのカリキュラムを中心としています。言語は約7割が英語ですが、それ以外にも30程度の言語が出てきます。
データ
Kolibriのユーザ(カリキュラムを作る人あるいは団体)は、それぞれの"channel"を新規作成した後、その中に"topic"とそれに紐づく"content"を登録します。
私のイメージは以下になります。
- channel : 一冊の教科書
- topic : 教科書の目次
- content : 教科書の本文
topic
topicはそれぞれが教科書の目次あるいは単元のようなイメージです。例えば"合同な図形"というtopicがあれば、その中で合同な図形の定義を学べるかもしれません。topicには親子関係があり、“合同な図形"は親topicとして"図形"を、子topicとして"三角形"を持つかもしれません。各channelにはルートtopicが一つだけあり、ルートtopic以外の各topicは親topicを必ず一つ持ちます。
topicの親子関係の例:
算数 → 小学5年生 → 図形 → 合同な図形 → 三角形
topicの親子関係はマッチングにおいて重要です。“三角形"というtopicタイトルだけでは三角形の何を勉強するのかは曖昧です。しかし、親topicの"合同な図形"という情報があれば、“三角形の合同条件"を学ぶのではないかと予想できます。
topics.csvのスキーマ抜粋
カラム名 | 説明 |
---|---|
id | topicのid |
title | topicのタイトル |
description | topicの詳しい説明 |
channel | channelのid |
language | “en”,“fr” などの言語コード |
parent | 親topicのid |
content_ids | このtopicに紐づくcontentのid (実際にはこの情報は別のcsvで与えられます) |
content
contentはそれぞれが教科書の本文を表しているようなものです。contentはテキスト、動画形式、音声形式などがあります。ただし本コンペには実際の動画データは含まれず、テキストに書き起こしたものが与えられます。一つのcontentは複数のtopicから参照されることもあり、複数のchannelのtopicから参照されることもあります。
content.csvのスキーマ抜粋
カラム名 | 説明 |
---|---|
id | contentのid |
title | contentのタイトル |
description | topicの詳しい説明 |
kind | ‘video’, ‘document’, ‘html5’, ‘exercise’, ‘audio’ のいずれか |
text | contentの本文 |
language | “en”,“fr” などの言語コード |
評価指標
テスト用のtopicとcontentが与えられ、各topicに対して紐づくcontentを予測します。正解のcontentの集合と予測したcontentの集合のF2 scoreを計算し、それらを全topicで平均したものが評価値となります。なお、本コンペはCode Competitionであったため、推論コード(Kaggle Notebook)を提出する方式でした。
私の取り組み
1月前半
コンペの問題設定から距離学習をまず思いついたため、この方針で進めることとしました。文章をモデルに入力すると一定長のembeddingsが出力され、このembeddings同士の距離(コサイン類似度、ユークリッド距離など)を2つの文章の類似度とするものです。まずはシンプルにtopicとそれに紐づくcontent群を1クラスとして、BERT(Bidirectional Encoder Representations from Transformers)とArcFaceによる学習を行いました。topicについては、親子関係を活用するためにいわゆるパンくずリスト方式で親topicのtitleも一つのテキストとして連結してから学習しました。
学習したモデルを使い、あるtopicとの類似度が一定以上高いcontentを予測として出力し、LBスコア(LeaderBoard=順位表)で0.47(当時15位)となりました。
1月後半
作ったモデルのエラー分析中に、“別のtopicが同じtitleを持つ場合、それらは全く同じcontentを参照していることが多い"ということに気が付きました。原因としては、新しくchannelを作る団体は既存のchannelを参考に(あるいは完全にコピーして)topicとそれに紐づくcontentを決めていることが多いためだと考えています。
そこで、後処理として、“trainのtopicと同一titleを持つtest topicに対しては、モデルの予測結果は使わずにtrain topicと同一の予測を出力する"ようにしたところ、LBスコアが0.50 → 0.58(当時6位)と大幅に改善しました。この後処理自体は最終的には採用しませんでしたが、後述する二段目モデルの特徴量の一つになりました。
2月前半
過去の類似コンペである、ShopeeやFoursquareの上位解法では二段階モデルが使われていることがありました。今回の問題設定に当てはめ、以下のパイプラインにしました。
- 一段目モデル:BERTによる距離学習を行い、各topicとcontentに対するembeddingsを出力する。各topicに対して、最も類似度が高い上位N(今回は50)個のcontentを出力する。
- 二段目モデル:一段目の出力であるtopic-contentのペアが本当に正解かをGBDT(Gradient Boosting Decision Tree)により0-1で予測する。
GBDTとしてCatBoostを使用することで、LBスコアが0.59 → 0.66(当時3位)程度まで改善しました。
コンペ終了まで
二段階モデルによる全体的な構成はほぼ固まったため、あとは細かい改善を繰り返すことでスコアを少しずつ伸ばしました。
主な改善ポイント
- 一段目モデルの学習epoch増加、チューニング
- 二段目モデルの特徴量追加
- embeddings類似度
- tfidf類似度
- 同じタイトルを持つtopicがこのcontentを参照しているか
- 兄弟topic(親が同じtopic)がいくつ存在しているか
- 兄弟topicがこのcontentを参照しているか
- 他多数
- 後処理
- channelごとに異なるしきい値を採用する
- アンサンブル(モデルを複数作り、その予測値を組み合わせること)
- 一段目モデル:4モデル * 5foldの合計20モデル
- 二段目モデル:16モデル * 5foldの合計80モデル
二段階モデルの構成:
スコア履歴
Kaggleではコンペ期間中に公開されるPublic LeaderBoardと、終了後に公開されるPrivate LeaderBoardがあります。最終的な順位はPrivate LBで決まることから、Privateテストセットで良いスコアを出せるモデルを作ることが重要です。今回のコンペでは手元評価であるCVスコア(Cross Validation score)とPublic LBスコアはよく相関していたことから、大きなshake(Public LBとPrivate LBで大きく順位が変動すること)は無いだろうと予想していました。PublicスコアとPrivateスコアとのそれぞれの履歴を見ても、よく相関していたようです。
public LB scoreの履歴とコンペ終了時の金銀銅メダルのライン
private LB scoreの履歴とコンペ終了時の金銀銅メダルのライン
上位チームの解法
私と同じような多段モデルを採用しているチームが多かったようです。私の場合は一段目モデルはBERT、二段目モデルはGBDTで行いましたが、チームによっては二段目モデルもBERTで学習していました。
上位チームの興味深い解法:
- embeddingsの類似度による候補に加えて、同じタイトルを持つcontent、兄弟topicが持つcontentを候補に加えている(1st)
- 言語を別言語に翻訳することで、学習データを増やす(2nd)
- “topicとそれが参照しているcontent群"ではなく"contentとそれを参照しているtopic群"を1クラスとしたモデルも作る(4th)
- メタ情報(channel, category等)や兄弟topicの情報も文字列として加えた上でBERTモデルへ入力する(5th, 12th)
- 英語用の独立したBERTモデルを作る(5th)
- topicに対する予測contentがN個未満であればN個になるまで足す(多数)
- 私の場合はN=1より大きくするとスコアが下がってしまったため、N=1で最終提出しました。
振り返り
コンペ自体の問題設定は過去に参加したコンペと似ていた部分もあり、当時のコード資産や考え方を流用することができました。上位のソリューションを読むことで、実装が簡単で効果が高そうな特徴量であったり、検証していて然るべき部分などまだまだ至らない点を学ぶことができました。
今回ソロ金メダルを獲得したことで、Grandmasterになることができました。今後もKaggleへは挑戦し続けたいです。
We are hiring!
エムシーデジタルではデータサイエンティストをはじめ様々な職種の方を募集しています。