Kaggle Google QUEST Q&A コンペ 振り返り
はじめに
Kaggleで開催されていた Google QUEST Q&A Labeling Competition 、通称 QUEST コンペ、QA コンペに参加したので、コンペの概要を記載します。また、このコンペで、 78位 / 1579チーム中でギリギリ銀メダルを獲得できたので、取り組んだことを記載します。
コンペの概要
英文による質問と回答のペアが与えられており、そのペアに対する30項目における評価値 ( ] )を予測します。
質問タイトルや質問者・回答者の名前、サイトURLやカテゴリーもデータとして提供されていました。
この30項目はとても主観的な内容であり、コンピュータでは評価が困難なQAに対する主観的評価を行うことが今回のコンペの意義のようです。
url | http://stats.stackexchange.com/questions/125/what-is-the-best-introductory-bayesian-statistics-textbook |
カテゴリ | SCIENCE |
質問者 | Shane |
回答者 | gappy |
質問 タイトル | What is the best introductory Bayesian statistics textbook? |
質問 本文 | Which is the best introductory textbook for Bayesian statistics? One book per answer, please. |
回答 | "Bayesian Core: A Practical Approach to Computational Bayesian Statistics" by Marin and Robert, Springer-Verlag (2007) |
評価項目 1 質問の意図が理解できる |
1.0 |
評価項目 30 回答が上手く書かれてる |
1.0 |
Notebook Competition
QUEST コンペは Kaggle Notebook のみのコンペでした。予測結果を submission.csv というファイルで出力するようなコードを Notebook に記載して提出します。トレーニング済みのモデルをデータセットとしてアップロードして使うことが許可されていたため、実質は推論のみを Kaggle Notebook 上で実行すればOKでした。
また、Internet は Off でないといけないため、外からデータをダウンロードすることはできませんでした。
他のNotebook コンペと同様、GPUの場合は2時間、CPUの場合は9時間の時間制限があります。
しかし、時間制限よりもソロ参加者にとっては、Private Datasetの容量制限が 20GBというのがちょっと苦しかったです。
評価関数
このコンペの評価関数はスピアマン順位相関係数でした。
正解データと予測値のランクの類似度を表した値になります。
は正解データと予測データのランキングの差になります。 (あるデータで、正解が10位、予測が9位なら は 1)
データの特徴
Training データの数は6079, PublicになってるTest データの数は476です。
Training データと Test データのデータ提供元 (host名) の割合です。
両方とも20%強が stack overflowからで、それ以外はどれも5%未満です。
カテゴリの割合は Training データと Test データはほぼ同じです。
また、正解データを見ると離散値であることが確認できます。
(30項目中10個をピックアップ)
Start From Here : QUEST Complete EDA + FE ✓✓ | Kaggle
正解データが離散値であり、ほとんどが循環小数であることから何人かのアノテータが各項目を0, 1で評価し、その平均値を正解データとしたようです。また、その循環小数を見ることで何人のアノテータがいたかが、おおよそわかります。
取り組んだこと
モデル
BERT, XL-Net, RoBERTa の平均です。
Transformers の BertForSequenceClassification はヘッドが以下のようになっているので、config の num_labels にクラス数 ( 評価項目の数 ) を指定して、事前学習済みモデルを Fine-tuning して利用しました。
( XL-Net, RoBERTaも同じ)
class BertForSequenceClassification(BertPreTrainedModel): def __init__(self, config): super().__init__(config) self.num_labels = config.num_labels self.bert = BertModel(config) self.dropout = nn.Dropout(config.hidden_dropout_prob) self.classifier = nn.Linear(config.hidden_size, self.config.num_labels) self.init_weights()
transformers/modeling_bert.py at master · huggingface/transformers · GitHub
モデルを上手に改良してスコアを上げられたら良かったのですが、色々試みたものの全く良くなりませんでした。
評価項目ごとにモデルを作成
評価項目を以下の3つに主観で分類しました。
- 1. 質問文のみで評価できる (例えば「質問の意図が理解できる」)
- 2. 回答文のみで評価できる (例えば「回答が構造的に書かれているか」)
- 3. 質問文と回答文揃ってないと評価ができない(例えば「回答が尤もらしいか」)
また、ぞれぞれ以下のように学習しました。
- 1. に分類される評価項目は、インプットを質問文と質問タイトルを結合したもので学習
- 2. に分類される評価項目は、インプットを回答文のみで学習
- 3. に分類される評価項目は、インプットを質問文と質問タイトルと回答文を結合したもので学習
前処理
基本的にTransformersのTokenizerがよしなにやってくれるので、stop word や省略形などの対応はしませんでした。
BERTを使う上で必要な special token に変換される、[CLS]や[SEP]などを結合することや attention mask を作成することなどはしました。
後処理
データの特徴で記載したとおり、正解データが離散値で評価関数がスピアマン順位相関係数であることから出力された値を、クラスタリングしてまとめて同じ値に変換する後処理をしました。
例えば、[question_type_instructions] という評価項目なら、ヒストグラムを描くとこのような予測値なのですが
以下のように近い値を同じ値に変換するということです。
クラスタリングは scikit-learn の BayesianGaussianMixture を使いました。
from sklearn.mixture import BayesianGaussianMixture dp = BayesianGaussianMixture(18) pred = dp.fit_predict(sub[col].values.reshape(-1, 1))
CV結果をみて、実際に変換する評価項目を以下の 3 つにしました。
- question_has_commonly_accepted_answer
- question_type_consequence
- answer_plausible
また、Training データからアノテーターの人数を推測し、想定される離散値に予測値を寄せるという対応も行いました。離散値どうしの中間の値を閾値にして、どちらに近いかで寄せる値を決めました。
CV結果をみて、実際に変換する評価項目を以下の 4 つにしました。
- question_conversational
- question_type_compare
- question_type_definition
- question_type_entity
学習時のパラメータ
- loss: BCEWithLogitsLoss
- optimizer: AdamW
- lr: 3e-5
- Batch Size: 8
- 5-fold
その他
BERTとNLPライブラリのTransformersの使い方を学びました。
( BERTは完全理解というより、お気持ち理解程度です。)
Transformerの論文 : [1706.03762] Attention Is All You Need
BERTの論文 : [1810.04805] BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
Transformersのライブラリ: Transformers — transformers 2.4.1 documentation
まつけん (@Kenmatsu4) | Twitterさんの資料 : BERT入門
Ryobotさんのブログ : 論文解説 Attention Is All You Need (Transformer) - ディープラーニングブログ