📚

2023-24年のKaggleコンペから学ぶ、NLPコンペの精度の上げ方

2024/07/14に公開

23-24年もKaggleでNLP系のコンペがたくさん開かれています。
このうち、コンペで使えるTipsをまとめてみました。

23-24年のNLPコンペまとめ

コンペ名(略記) 概要 日本語記事
LLM Science Exam(LLM Sci) LLMが作成した問題をKaggle環境下で動く言語モデルで解くコンペ(分類) まとめ1, まとめ2
Commonlit2(Commonlit2) 要約文の品質を評価するコンペ(回帰) 4th, まとめ
LLM Detect AI Generated Text(DAIGT) LLMが作成した文と人間が作成した文とを見分けるコンペ(分類) 14th
LLM Prompt Recovery(Prompt Recovery) LLMによる文書変換に使われたプロンプトを復元するコンペ(文作成) 12th, まとめ記事
PII Detect(PIIDD) 文中に埋め込まれた個人情報を検出するコンペ(固有表現抽出) まとめ
Automated Essay Scoring(AES2) 文の品質を評価するコンペ(回帰) まとめ

LLM関係のコンペがかなり多かったですね。

ベースラインノートブック

最近はほとんどのコンペがHuggingfaceのTrainerを使って学習が行われます(テーブルデータにおけるscikit-learnのような立ち位置です)。ChrisのNotebookは非常にシンプルにまとまっているのでぜひ参考にしてください。

  • 分類(+RAG)

https://www.kaggle.com/code/cdeotte/how-to-train-open-book-model-part-1

  • 回帰、分類

https://www.kaggle.com/code/cdeotte/deberta-v3-small-starter-cv-0-820-lb-0-800

  • 固有表現抽出

https://www.kaggle.com/code/emiz6413/deberta-v3-single-model-lb-0-966

NLP・精度上昇で検討すること

データを増やす

  • LLMによるデータ生成 + ラベリング(CommonLit2 1st, DAIGT 1st, LLM Sci Exam 5th, PIIDD 1st
    • LLMによるデータ生成は必ずしも効果があるとは限らない
    • データ生成方法も現状はベストプラクティスはない
    • Mistral, Mixtral系列でデータ生成がよさそうな感じはする
    • なお、LLMがラベル付けできないタスクでは厳しい印象です
  • TTA(テストデータ水増し)
  • 再翻訳

Tokenizer,データ処理

  • 改行("\n")をトークンに追加, [BR]などの文字に置換

    • DeBERTaがデフォルトで改行を無視してしまうため、トークンとして追加することでDeBERTaが改行の意味を考えてくれるようになる(PIIDD 3rd, AES2 1st
  • RandomMask

    • 過学習を抑える効果があるようです

機械学習モデルの変更

  • ほとんどのコンペでDeBERTa-v3が使われる(CommonLit2 1st, DAIGT 1st, PIIID 1st, AES2 1st)。

    • DeBERTa-v3-largeが基本だが、DeBERTa-v3-baseもアンサンブルなら検討可能
    • 他使われているのはDeBERTa-v2, Longformerなど
    • 近年は文章全体を入力とすることが多く、Relative position(相対位置)を使用するDeBERTaがとても便利
  • コンペによってはLLMを使っている例もある

  • コンペによってはtf-idfで精度上昇の可能性もあり(AES2 baseline

    • tf-idfはPrivateでスコアを下げることが多い印象はある

モデルや学習時の工夫

PoolingやHeaderの変更については以下の記事にもわかりやすく書いてあるのでご参照ください
https://www.ai-shift.co.jp/techblog/2145

  • Modelの継続事前学習(MLM)(DAIGT 1st

ドメインが特殊なときに有効な印象がある。Kaggle周りだとNBME(医療系のNLPコンペ)ではMLMが上位への鍵の1つのようでした。

https://blog.recruit.co.jp/data/articles/kaggle-nbme-score-clinical-patient-notes/

  • 学習時にノイズを足す(AWP)

AI Shiftさんの記事やカレーちゃんさんの記事に詳しく書かれています。今も有効な手段であることは間違いないですが、23-24年のコンペではAWPが効かないコンペもいくつか見られる印象があります。

https://www.ai-shift.co.jp/techblog/2985

https://www.docswell.com/s/currypurin/Z8L7L5-2022-05-23-081854

  • 学習時のロス関数を変更

HuggingfaceのTrainerは、回帰はMSELossが、分類ではCrossEntropyLossが使われます。

このロス関数を変えることで、学習を安定させたり精度向上につなげることがあります。

  • 過去コンペの予測値とのロスも合わせた補助損失(Aux Loss; CommonLit 2nd

  • 回帰問題におけるSmoothL1 Loss, RMSE Loss, RankLossの組み合わせ(Commonlit2 11th

  • DiscussionではFocal loss(簡単に分類できるサンプルはロスを小さくする)もよく言及されています(23年ではないですが、NBME 4thなど)。

Huggingface TrainerでLoss functionを書き換えるのは以下の記事が参考になります。

https://dev.classmethod.jp/articles/huggingface-usage-custom-loss-func/

  • 問題を違う形で捉える

特に最上位の解法では、問題を違う形で捉えるということが多く行われています。

簡単なところでは、Targetの値が1,2,3,4,5,6のいずれかの場合に回帰でなく分類問題として解くというものがあります。(AES2 baseline

  • 分類 → ランキング問題(DAIGT 1st

  • 知識蒸留(PIIDD 1st

    • 学習データセットAで学習したものを教師とし、学習データセットBにおける学習に利用したとのこと

データ分割

  • Stratified K-Fold, K-Foldなどなど。

    • データの分割については通常のテーブルコンペとそこまで変わらない印象
  • データ数足りない時はFull Trainも検討(Commonlit2 4th

https://speakerdeck.com/chumajin/model-ensemblenoke-shi-hua

パラメーター

  • 回帰問題においてはモデルのDropoutを0とすることがほぼ定石

https://www.kaggle.com/code/cdeotte/deberta-v3-small-starter-cv-0-820-lb-0-800

https://www.ai-shift.co.jp/techblog/2170

  • 学習のパラメーターはそこまで大きな影響は与えなさそう

公開ノートブックを元に修正していけばよいと思いますが、よくいじられているパラメーターは以下のあたり

"learning_rate": [1e-6, 1e-5, 2e-5]
"lr_scheduler_type": ["cosine", "linear"]
"warmup_ratio": [0, 0.01, 0.1]
"weight_decay": [0, 0.01]

アンサンブル

  • 上記までの組み合わせ

後処理

  • DeBERTaの予測値、tf-idf、文章の統計情報を組み合わせ、LightGBMなどで予測(AES2 baseline

    • 2-stage予測と呼ばれるもの
  • 過去コンペ(Feedback 3; FB3)で作成された予測値を利用

Feedback 3は生徒の書いた文章を複数の観点からの評価値を予測するコンペです。

https://www.kaggle.com/competitions/feedback-prize-english-language-learning

日本語だと以下のブログがわかりやすかったです。

https://moritake04.hatenablog.com/entry/2022/12/02/185835

具体的な活用方法としては以下

  • DeBERTaでの予測やロスにFB3の予測値も追加(CommonLit2 2nd

  • 2-stageで予測する際にFB3の予測値も特徴量として追加(AES 7th

  • ルールベースの後処理

    • 明らかに間違いと思われるものの除外や、特定のルール下において改行を回答に追加する...など(PIIDD 2nd

銀圏と金圏の差分となったテクニック

銀圏と金圏の差分になったであろうテクニック(私見)をまとめます。銀と金の差分は色々あって法則性がないのがKaggleの難しいところであり、よいところですね。

・公開Wikipediaデータの処理ミスを修正(LLM Sci)

・要約文+原文を入力するが、要約文のPoolingのみ使用(モデリング;Commonlit2)

・データ量を増やしてDeBERTaで殴る(公開NBではtf-idf使ってる人が多かった;DAIGT)

・ルールベース後処理(PIIDD)

・公開データ/新規データの違いに着目(AES2)


学習時のメモリ節約

精度とは直接関係ありませんが、Kaggleのノートブック上での学習のためにメモリを節約することが求められます。基本的にはChrisのNotebookを参考にしてください。

https://www.kaggle.com/code/cdeotte/how-to-train-open-book-model-part-1

  • TrainingArgumentsで設定できるもの

    • fp16=True
    • per_device_train_batch_size=1にしてgradient_accumlation_steps=4などにする
    • gradient_checkpointing=True (メモリ節約できるが、学習が2割ほど遅くなる)
  • モデルの層、EmbeddingをFreezeする

  • PEFTの利用

    • PEFTは精度が下がる可能性有り(逆にアンサンブルに使われる例もあり)
  • 8bit-adam

    • あまりKaggleで使われる例は見ないですが、ほぼ精度に影響なくメモリ使用量を減らせます

https://huggingface.co/docs/transformers/ja/perf_train_gpu_one

Discussion