「AIが書いた文章か人間が書いた文章かを見分けるコンペ」の、上位チームの解法が出そろいつつあります。今日は、そのうち、1位~3位のチームの解法を、(1)データセット、(2)特徴量(トークナイザ&ベクトル化)、(3)分類モデルの観点で、まとめてみます。不勉強なもので、(2)と(3)の分類がちょっとあやふやなところがあるかもしれません。お気づきの点があればご指摘ください。
1位:1st place short solution summary
-
順位の変遷
- パブリック:9位(0.979)⇒プライベート:1位(0.987)
-
(1) データセット
- 合計で16万件の例文。うち人間の文章は4万件
- 人間の文章:Persuadeコーパス全文+一般的な文章
- AIの文章:多様なLLM、プロンプトを使用。Persuadeコーパスにあわせて、プロンプトをチューニング
-
(2) 特徴量
- train + testのエッセイを使って訓練したdeberta-v3をトークナイザとして利用
- deberta-v3-smallでプライベートLB0.943、largeでプライベートLB0.961を達成
-
(3) 分類モデル
- Ghostbasterアプローチを採用
- LoRA でファインチューニングしたMistralモデル (mistralai/Mistral-7B-v0.1)
- 確信度付きの予測を出力し、弱ラベルとして利用
2位:2nd place solution with code and data
-
順位の変遷
- パブリック:17位(0.976)⇒プライベート:2位(0.983)
-
(1) データセット
- SlimPajamaデータセットから様々なLLMを使って約50万件の人間とAIの文章のペアを作成
- Persuadeコーパスに対して言語モデル(LM)の微調整を行い、LLMに学生の文章を模倣したテキストを生成させた
- DAIGT-V4-TRAIN-DATASET上で3つのモデルをファインチューニングし、アンサンブルに加えた
-
(2) 特徴量
- deberta-v3-largeでプライベートLB0.967を達成
-
(3) 分類モデル
- 一般的なモデル(詳細は不明)
3位:3rd place solution
-
順位の変遷
- パブリック:15位(0.976)⇒プライベート:3位(0.974)
-
(1) データセット
- データ前処理で、15以上のエラーがある文章のみ、deobfuscatorで修正
- オリジナルのtrainデータに含まれない文字を削除/正規化
- 1.1万件のリフレーズされた文章に対して、4つのモデルをトレーニング⇒4回のトレーニングごとにLBスコアを算出。数値が悪化したら前のデータセットに戻してまたやり直した。
- DAIGT | External Datasetから、少しずつデータを増やしながら、誤分類したデータを人間500件、AI500件ずつ追加してモデルを繰り返しトレーニング
- pileとslimpajamaデータセットを利用。短すぎる/長すぎるテキスト、コードや数学を含むテキスト、英語以外のテキスト、非文字/文字の比率が高いテキストをフィルタリング
- パラメータの組み合わせが異なる、~35種類のオープンソースモデルを使用して文章を生成。50万件、100万件、120万件のサンプルを作成。
-
(2) 特徴量
- TfIdfパイプライン
-
(3) 分類モデル
- catboostとlightgbmの反復回数を250回増やし、VotingClassifierにweights=[0.05, 0.225, 0.225, 0.5]を使用
- 12個のdeberta-v3-largeモデルを使用
- 2段階の確率的重み付きアンサンブルを使用
- 後処理として、各prompt_idのうちサンプルが1000件以上ある場合は、TfIdfの特徴量の次元削減を行い、人間の書いた文章との距離を算出し、予測値をスケーリングした
これら上位3チームは、いずれもパブリックLBが高く、プライベートLBでもさらにshake-upしたチームでした。めちゃくちゃカッコいい勝ち方ですね。彼らの共通点は、
・データの品質と多様性を吟味しつつ、大量のデータセットを構築していた
・deberta-v3の活用
・SlimPajamaデータセットの活用(3チーム中2チーム)
などがありますね。時間と手間をかけてでも、やるべきことをやっていたチームが最後まで生き残ったという感じでしょうか。
個人的には、3位のチームがやっていた「小さなデータセットからはじめて、誤分類したデータを追加していく手法」が、自分の頭からすっぽ抜けていたことが悔やまれます。まさにMLOpsとして、実務でやっていたはずのことなのに、すっかり忘れていました。Out of Memoryエラーに泣かされたときに、このアプローチをとるべきだったなあと思います。
1位のチームが参考にしていた、Ghostbasterアプローチというのも気になりますね。またそのうち論文を読んだら、シェアしようと思います。