Kaggle - CommonLit Readability Prize 参加記
概要
先日までKaggleのCommonLit Readability Prizeに参加しており、若干のshakedownをしてしまったものの最終的に132位で銀メダルを獲得することができました。

簡単にいうと、本コンペの目的は与えられた文章の「読みやすさ(Readability)」を予測することです。目的変数は連続値で、人間(現役教師)に2つの文章の比較を行ってもらった結果を元にこちらのDiscussionのような方法で計算されています。タスクのタイプとしては回帰であり、評価指標はRMSEでした。
コンペの詳細はリンクを参照していただくとして、ここでは自分の取り組みと上位陣のSolutionをまとめたいと思います。
自分の解法
CV
KFold
モデル
以下のモデルたちのNetflix Blending
- RoBERTa-large (22, 23, 24層のhidden statesのmeanをとってconcat → Linear)
- RoBERTa-large (12, 18, 24層のhidden statesのmeanをとってconcat → Linear)
- RoBERTa-large (7, 15, 23層のhidden statesのmeanをとってconcat → Linear)
- RoBERTa-large (1~24層のhidden statesのmeanをとってattention pooling → Linear)
- RoBERTa-large (2, 4, … , 22, 24層のhidden statesのmeanをとってattention pooling → Linear)
- RoBERTa-base (コンペデータでpretrain、10, 11, 12層のhidden statesのmeanをとってconcat → Linear)
- Pre-trained Roberta solution in PyTorch (公開Notebook)
- CommonLit Readability Prize-RoBERTa Torch|Infer 3 (公開Notebook)
Public LBへのoverfitを避けるためNetflix blendingの正則化は大きめに設定した(0.01)
学習
- epochs: 3
- batch size: 8
- optimizer: AdamW
- lr: 2e-5
- scheduler: cosine_warmup
- evaluate_interval: 20 steps
- no dropout
うまく行ったこと
- Differential Learning Rate
- 最終層からdecay_factor=0.975で徐々にlrを小さくする
- no dropout
- fewer epochs
- Linearは2層 > 1層
うまく行かなかったこと
- SWA
- spacyのlinguistic features(posとdep)を1d-CNNで処理し、BERTのLinearに結合
- 誤差が大きいexampleを見ると、単語自体はそれほど難しくないが、構文が難しいものがうまく予測されていなかったため、その情報を明示的に加えた
- robust CV
- スコアが一定ラインを超えてからCVとLBの相関がなくなった
- 今回はtestとtrainの分布が異なる(testがよりmodernな文章を多く含む)ことが明らかにされていたため、この情報を活用しようとした
- modern / non-modern分類機を作成し、modernな文章の予測値をゼロにすることでtestのmodern比率が大体40%であることを推測した(trainは30%ほど、推測が正しかったのか不明)
- これを元にmodernな文章の比率をtestに揃えたCVを作成した
- RoBERTa以外のモデル
1st place solution
CV
6-fold crossvalidation or bootstrapping
External data
- simplewiki, wikipediaなどからスクレイピングでコーパス作成
- 学習データと同じくらいの長さの文章のみにフィルタリング
- Sentence-BERTを用いて、コーパスからtrainの各文章とコサイン類似度top5の文章を抽出
Pseudo-labeling
- trainで学習したモデルでexternal dataにラベル付与
- trainの対応する文章と大きく離れたラベルが付与された場合は除外
学習
- pseudo labelデータで学習、trainデータで評価
- trainデータで学習
モデル
- albert-xxlarge, deberta-large, roberta-large, electra-large and roberta-base
- Ridge regressionでstacking
2nd place solution
CV
targetをbinningしてStratified KFold
モデル
- roberta-base + svr, roberta-base + ridge, roberta-base, roberta-large, muppet-roberta-large, bart-large, electra-large, funnel-large-base, deberta-large, deberta-v2-xlarge, mpnet-base, deberta-v2-xxlarge, funnel-large, gpt2-medium, albert-v2-xxlarge, electra-base, bert-base-uncased, t5-large, distilbart-cnn-12-6
- nelder-mead法によりblendingの重みを決定
- LBを重視した
post process
- 予測値によって異なる係数をかける
- 係数はnelder-mead法により求め、Public LBで調節
- 閾値はPublic LBとCVで調節
3rd place solution
External data
- simplewiki, children’s book test, OneStopEnglishCorpus
Pseudo-labeling
- trainで学習したモデルでexternal dataにラベル付与
学習
以下のサイクルを繰り返した
- pseudo labelデータとtrainデータで学習
- 新しいモデルでexternal dataをrelabel
モデル
- deberta-large, roberta-large, roberta-base
- simple average
4th place solution
CV
- targetをbinningしてStratified KFold
- データが小さく結果が安定しないため、上記のCVをseedを変えて行い、その平均をCV scoreの算出に用いた (5folds x 5seeds=25runs)
- CV-LB gapは0.01ほどあったが相関は十分だった
モデル
- microsoft/deberta-large, microsoft/deberta-base, deepset/roberta-base-squad2, deepset/roberta-large-squad2, distilroberta-base, funnel-transformer/large-base, bert-large-uncased, bert-large-uncased, facebook/bart-base, facebook/bart-large, microsoft/deberta-large, albert-large-v2, , sentence-transformers/LaBSE, bert-large-cased-whole-word-masking, bert-large-cased, xlm-roberta-large, google/electra-large-discriminator, sentence-transformers/paraphrase-mpnet-base-v2
- 全モデルでlayer方向ではなく、ouptutのsequence方向のattentionを用いた
- RidgeとBayesianRidgeでstacking
学習
- Epochs: 6 with SWA after epoch 3
- No dropout
5th place solution
CV
KFold without shuffle
- trainデータには順序がありソースごとに並んでいた
- testもtrainとは異なるソースの文章が含まれている可能性がある
- このout-of-distribution汎化性能をよりよく図るためにshuffleをしなかった
モデル
- roberta-large, roberta-base, deberta-large, funnel-large, electra-large
- linear head followed by mean pooling on last hidden state
- RidgeとLightGBMでstackingして平均
- LightGBMにはhand-crafted featuresも加えたほうがよかった
学習
- dropout
- 原因不明だがtrain/inference両方でdropoutをしたほうがよかった
- epochs: 5
- cosine schedule
- differential lr
- re-initialize some layers
6th place solution
CV
Stratified 5-fold
モデル
QAタスクでpretrainされたモデルがよかった。いろんな事前学習モデルを試すべき
- roberta-large, microsoft/deberta-large, xlnet-large-cased, deepset/roberta-large-squad2, deepset/roberta-large-squad2, allenai/longformer-large-4096-finetuned-triviaqa, valhalla/bart-large-finetuned-squadv1, microsoft/deberta-large-mnli, ahotrod/electra_large_discriminator_squad2_512
- all models with Attention head
- 9 modelsのattention headのoof出力に対しGaussian process regressionを使用
学習
- epochs: 5
- AdamW with SWA
- Layer reinitialisation: last 3 transformer layers
- no dropout
External data
trainデータのurlからスクレイピング
Pseudo-labeling
- trainで学習したモデルでexternal dataにラベル付与
- 学習時に同一ソースのpseudo labeled dataを追加
- 全pseudo labeled dataを追加することによるleakageを避けるため
9th place solution
CV
- KFold
- K=5, 10, 15, 25を試した
- 大きくするほどスコアが向上した
モデル
- deberta-large, roberta-large
- cross-entropy lossが効いた
12th place solution
モデル
- deberta-large, roberta-large, albert-xxlarge-v2, electra-large-discriminator
- Nelder-mead法でアンサンブルの重みを求めた
学習
以下の手順で行った
- wikipediaデータでMLM事前学習
- trainでモデル作成
- wikipediaデータをpseudo-label
- pseudo-labled dataのうち正しそうなもののみ抽出
- MLMとpseudo-labelでさらに事前学習
- trainで学習
re-initialization of top 5 layersが効いた
まとめ
私にとって初めてのTransformersを使ったNLPコンペでした。初めは右も左もわからない状態でしたが、公開Notebookや論文を読んだりするなかでTransformersの仕組みや基本的な使い方がわかるようになり、参加して非常によかったと思っています。Top solutionを読んでの感想は以下です。
- いろんなモデルを試すべきだった
- まずは存在を知るところから…(Solutionを読んで存在を知ったモデルが多数あった)
- deberta-largeが強かったっぽい
- アンサンブルはもっと工夫できた
- 上位陣はNelder-mead法によるblendingやstackingを多く使用していた
- Pseudo-labelingはいろんな場面で使えそう
本コンペで得た知見を他のNLPコンペや業務に生かせたらと思います。