たかいとの備忘録

自然言語処理や機械学習のことについて学んだことを忘れないように書いていけたらと思います.

Jigsaw - Agile Community Rules Classificationのまとめ

はじめに

2025年7月24日〜2025年10月24日に開催されたJigsaw - Agile Community Rules Classificationというkaggleで開催されたコンペに参加し,参加者2,934人,2,445のチームが参加する中で11位の順位で終えることができました.

いつものような振り返り記事ではなく,来月出版予定の『Kaggleではじめる大規模言語モデル入門 自然言語処理〈実践〉プログラミング』の応用編のフォーマットに則って,こちらのコンペのまとめを行えたらと思います.(細かい形式や図表番号,解法の取り扱い方などはブログ記事であるため,書籍とは多少異なります)

jigsaw-agile-community-rules (by Nano Banana)

コンペの情報

URL:https://www.kaggle.com/competitions/jigsaw-agile-community-rules

開催期間:2025年7月〜10月

順位:11 位(金メダル、チーム参加)

コンペの概要

Reddit (海外の掲示板型SNS) のコメントとルールが与えられ,該当コメントが指定されたルールに違反しているかどうかを分類するタスクでした. コンペの訓練データとして提供されている train.csv で出現するルールは以下の2つとなります.

  1. No Advertising: Spam, referral links, unsolicited advertising, and promotional content are not allowed. (広告禁止:スパム、紹介リンク、未承諾の広告、および宣伝コンテンツは禁止されています。)
  2. No legal advice: Do not offer or request legal advice. (法的助言禁止:法的助言の提供または依頼を行わないでください。)

以下に例を示します. 「There is no jurisdiction I am aware of that would consider this to be self defense. (私が知る限り、これを正当防衛とみなす司法管轄区域は存在しません。)」というコメントが与えられたとき,1. のルールには違反しておらず,2. のルールでは違反しています. したがって,1. のルールと合わせてコメントが与えられた場合は0に近い値,2. のルールと合わせてコメントが与えられた場合は1に近い値を出力するようなモデルを開発することが求められるコンペでした.

コンペの評価

評価指標は二値分類のタスクでよく使用される AUC (Area Under the Curve) が採用されていました. AUC の特徴は評価対象となるデータの順序関係が重要な指標です. 例えば,100 件のメールに 5 件のスパムメールが含まれているようなデータを考えた場合,その予測値が 0 から 0.1 の値に収まっていたとしても,5 件のスパムメールの予測値が 0.1 付近で,それ以外のメールの予測値が 0 から 0.1 にまんべんなく散らばっているようであれば,AUC の値はとても高くなります. このように,予測値の順序関係のみでスコアが決まるため,予測値のスケール調整に気を遣う必要はなく,複数モデルの予測のアンサンブルなども容易であり,比較的取り組みやすい評価指標の一つです.

コンペの特徴

コンペの訓練データとして提供されている train.csv とテストデータである test.csv には,コメント (body) とコメントが投稿されている掲示板のトピック (subreddit),そしてルール (rule) が含まれます. それらに加えて,このコンペでは,訓練データおよびテストデータに,正例 (違反する) コメントと負例 (違反しない) コメントが2つずつ与えられていました. テストデータのイメージを以下の図に示します.

データの例

正例と負例には,重複が非常に多いという特徴がありました. また,あくまでルールに対する例として与えられるため,subreddit との対応関係もなさそうでした. Discussion内でホストが,コメント (body) に対する正解データのアノテーションプロセスにおいても,subreddit を使用していないと言及があったため,subreddit は削除しているチームが多かったです (1位から5位は subreddit を意図的に使用していませんでした).

このコンペの最大の特徴として,テストデータには訓練データの2つのルールに加えて,未知のルールが複数存在していました. コンペ序盤の段階で,LB Probing (提出notebookを用いてテストデータのデータを調査する方法) により,未知のルールは4つ存在することが discussion 上に公開されていました. さらにその4つのルールに関しても,複数人の kaggler が協力することでコンペ開始一カ月頃に明らかになりました. 具体的にテストデータでは,訓練データに含まれる2つのルールに以下に示す4つのルールが追加され,6つのルールがあることが判明しました.

  1. No Advertising: Spam, referral links, unsolicited advertising, and promotional content are not allowed. (広告禁止:スパム、紹介リンク、未承諾の広告、および宣伝コンテンツは禁止されています。)
  2. No legal advice: Do not offer or request legal advice. (法的助言禁止:法的助言の提供または依頼を行わないでください。)
  3. No financial advice: We do not permit comments that make personal recommendations for investments, taxes, or careers. (金融アドバイス禁止:投資、税金、キャリアに関する個人的な推奨を行うコメントは許可しません。)
  4. No medical advice: Do not offer or request specific medical advice, diagnoses, or treatment recommendations. (医療助言の禁止:特定の医療助言、診断、治療法の推奨を提供または要求しないでください。)
  5. No promotion of illegal activity: Do not encourage or promote illegal activities, such as drug-related activity, violence, exploitation, theft, or other criminal behavior. (違法行為の助長禁止:薬物関連活動、暴力、搾取、窃盗、その他の犯罪行為など、違法行為を助長または推奨しないでください。)
  6. No spoilers: Do not reveal important details that would limit people's ability to enjoy a show or movie. (ネタバレ禁止:番組や映画を楽しむ妨げとなる重要な詳細を明かさないでください。)

(3から6がテストのみに出現するルール)

LB Probingによりルールは判明したものの,結局その判定 (アノテーション) 基準が不明であったため,データ拡張によるスコアアップはあまり機能していないようでした. これは,ルールが判明する前から上位にいたチームのスコアが,ルール判明後に大きく伸びなかったことや,他チームが劇的にスコアを伸ばし,上位の順位の入れ替えが起こらなかったことから,ある程度はコンペ開催期間中に察することができました.

このコンペの特徴は,正例と負例のコメントが2つずつ与えられていたことと,テストのみに存在するルールがあったことであり,Test Time Training (TTT) と呼ばれる,提出 notebook 内でモデルを学習 (ファインチューニング) するテクニックが非常に強力でした.

ベースライン

ベースラインは大きく2つ存在しました.

LLM を train.csv でチューニングする方法 (by monnuさん)

コンペ開始直後に公開されていた最も王道な方法を紹介する notebook で,このコンペで2番目に upvote の多かった notebook です. notebook は,学習と推論に分かれていました.

簡単に紹介すると,Qwen2.5-32B-Instruct-GPTQ-Int4 を LoRA でファインチューニングしています. プロンプトは,システムプロンプトとメインのプロンプトを使用しており,それらを以下に示します.

  • System Prompt
You are given a comment on reddit. Your task is to classify if it violates the given rule. Only respond Yes/No.
  • Prompt
{row.subreddit}
Rule: {row.rule}

1) {row.positive_example_1}
Violation: Yes

2) {row.negative_example_1}
Violation: No

3) {row.negative_example_2}
Violation: No

4) {row.positive_example_2}
Violation: Yes

5) {row.body}

プロンプトに与えられている例を利用しており,まったくモデルを学習させない場合,few-shot 分類 (この場合は four-shot) と呼ばれるようなプロンプトとなっております. train.csv のデータを用いて検証すればわかることですが,まったくモデルをファインチューニングせずに few-shot 分類をおこなっても,期待するような精度は出ませんでした. したがって,こちらの notebook は,このコンペのタスクに特化した few-shot プロンプトによる分類性能の向上を狙ったモデルのファインチューニングを行っていることになります.

LB で 0.872 のスコアが出る notebook であり,一般的な NLP コンペのベースラインとして申し分ない notebook でした.

ただし,このコンペの特徴であるテストデータにのみ存在するルールへの対応に限界があるため,この方法をベースにした手法のみで上位入賞は難しいコンペでした. (解法の一部にこちらの手法を取り入れているチームはいました.)

Test Time Training

コンペの特徴で紹介した提出 notebook 内で test.csv のデータも活用してモデルを学習させる方法です. モデルは BERT 系統のモデルのファインチューニングと LLM の RoLA チューニングの大きく二通りが存在していました. まず,test.csv を用いてどのように訓練データを作るかを説明します.

先ほど示したデータの例を改めて,以下に示します.

データの例

正例①,正例②,負例①,負例②が与えられているので,例えば,bodyのみの訓練データをテストデータから作成する場合,以下のようなデータを作成することができます.

bodyのみの訓練データ

このような訓練データでモデルをチューニングすることで,以下のような形式のテストデータの予測が可能になります.

bodyのみを用いたテストデータの分類

それ以外にも,例えば,正例②を body とみなし,正例①と負例②を few-shot (two-shot) の例としてプロンプトに使用するようなデータ作成も可能であり,このような方法で作成したデータを以下に示します.

body + few-shot の訓練データ

このような訓練データでモデルをチューニングすることで,以下のような形式のテストデータの予測が可能になります.

body + few-shot を用いたテストデータの分類

このように,テストデータを用いて訓練データを作成することで,テストデータにしか存在しないルールの分類の判定基準を学習させることが可能になります. BERT 系統の軽量なモデルは,高速に学習が可能である一方で,LLM の学習には時間がかかるため,データの一部削除や学習方法の工夫による高速化が求められました.

BERT 系統のモデルは,シンプルな分類タスクの学習だけでなく,距離学習を用いた方法なども共有されていました. LLM は分類用の SequenceClassificationHead (SC Head) を利用する方法もありますが,推論時の速度を考慮すると vllm を利用する方が推論を高速化することができるため,LanguageModelHead (LM head) による方法が人気でした.

上位解法の紹介

大きなマジックはないコンペでした. 基本的にはベースラインの手法を元に,大きく2つのエンハンスが重要だったコンペだったと思います.

  1. kaggle 環境で学習が可能な LLM の中で,より大きいモデルを使用
  2. 多様なモデルや方法を用いたアンサンブル

このコンペでは8位のチームまで賞金がもらえるコンペでしたが,5位のチームを除いて7チームが14Bのモデルを使用しており,5位と9位のチームも 8B,7B のモデルを使用していました. 一方で,9位から15位までの賞金を逃したチームの中で,14B を使用していたチームはありませんでした. したがって,14B のモデルを解法に組み入れることができたかどうかという点が,勝敗を分けた一つの要因だと思います. TTT は,kaggle 環境で学習を行う必要があるため,メモリおよび時間の制約があります. QLoRA + unslothを利用することで,T4 × 1 枚で 14B くらいまでのモデルであれば学習が可能であり,T4 x 2 枚の kaggle 環境は並列実行が可能でした. もちろん,学習には時間がかかるため,訓練データに含まれる無駄な重複の削除やサンプリングなどが必須でした. 上位8チームが使用していたモデルは以下の通りです.

モデル 使用していたチーム メモ
Qwen3-14b 1st, 2nd, 3rd, 4th, 6th, 7th, 8th Qwen, 14B
Qwen2.5-14b 3rd, 6th Qwen, 14B
phi-4-14b 2nd, 7th phi, 14B
llama2-13b 8th llama, 13B
Qwen3-8b 1st, 2nd, 3rd, 5th Qwen, 8B
Qwen3-8B-Guard 7th Qwen, 8B, 特化モデル
Qwen2.5-7b 2nd, 3rd Qwen, 7B
gemma-2-9b-it 7th gemma, 9B
shieldgemma-9b 7th gemma, 9B, 特化モデル
llama3.1-8b 1st, 5th, 8th llama, 8B
Qwen3-4b 1st, 4th Qwen, 4B
Qwen3Guard-Gen-4B 6th Qwen, 4B, 特化モデル
Qwen3-32b 5th Qwen, 32B (ローカル環境でチューニングしたものをそのまま使用)
Ettin-xxxx 1st 埋め込みモデル,400m, 1b など
bge-xxxx 3rd, 5th, 8th Qwen, 14B | 埋め込みモデル, small, base, large など
gte-xxxx 5th Qwen, 14B | 埋め込みモデル, small, base, large など
DeBERTa-xxxx 3rd, 5th Qwen, 14B | small, base, large など
Qwen3-embedding-0.6b 3rd, 5th 埋め込みモデル

今回のタスクと似たようなタスクに特化して調整された特化モデルを見つけるのも有効だったようで,7位のチームが使用している shieldgemma-9b は 14B の性能を凌駕していたと解法に紹介がありました.

ここまで使用していたモデルのサイズに注目してきましたが,合わせてアンサンブルも重要でした. 例えば,1 位のチームは Ettin-400M をアンサンブルの一つとして採用していました. 3位のチームは,14Bや8Bのモデルだけでなく,bge-base-v1.5,Qwen3-embedding-0.6b,DeBERTa-v3-small などの軽量なモデルも採用していました. 5位のチームは,上位で唯一 14B モデルを採用していませんでしたが,軽量なモデルをたくさん採用しており,距離学習である Triplet Loss を用いたモデル学習や,埋め込みを行ったベクトルに対して,ロジスティック回帰や knn などのクラシックな手法も採用していました.また,ベースラインで紹介した TTT をしない 32B モデルによる推論などもアンサンブルに組み込むことで,14B を使用せずに上位入賞を達成していました.

(各チーム,細かくスコアを伸ばすためのテクニックが解法に記載されていますが,本当に効果があるか確かめるための再現実験をする時間がとれなかったので,このブログでは共通している部分の紹介に留めようかと思います.以下は効果を確認していないですが,使用して有効だったと記述があったものを列挙したものとなります.)

  • Yes/No の token の表記揺れ対策に,["Yes","YES","Y","yes","True"],["No","NO","N","no","False"] などの生成確率も考慮する (1st)
  • シェルスクリプトで実行することで Dual GPU Parallel Scheduling (2nd)
  • Pseudo-Label (4th)
  • Deep Mutual Learning (6th)

当チームの解法紹介

15位までのチームで公開されている解法を確認したところ,他の14チームは,8B 以上のモデルを採用していました. 一方で,当チームは下記の図に示す通り,唯一,4Bまでのモデルを使用しています.

11th Place Solution — Jigsaw

図に示したモデルをすべて TTT しています. zero shot は以下のような形式の訓練データでモデルを学習させています.

bodyのみの訓練データ
few shot は以下のような形式の訓練データでモデルを学習させています.
body + few-shot の訓練データ

工夫した点は以下の通りです.

アンサンブルを重視

大きいモデルよりも小型なモデルをたくさんアンサンブルすることを重視していました. また,5位チームも採用していた距離学習である Triplet Loss を用いたモデル学習なども採用することで,多様性が出るように意識した手法を取り入れるようにしていました.

Test Time Augmentation (TTA)

プロンプトの長さが長くなる few-shot 分類のチューニングは,性能が良い一方で多く時間を使用するというデメリットがありました. 一方で,推論はそこまで時間を消費しないため,正例①,正例②,負例①,負例②から正例と負例を選ぶ計4通りの推論を行うことで性能の底上げをしました.

Pseudo-Label

LB で 0.93 程度のスコアが出ていたこともあり,有効だと考え採用しました. 特に,与えられる例は重複がとにかく多く,より多様なコメントで学習を行うことが有用だと考え,前段のモデル群で推論した結果をもとに,ルールごとに上位と下位 xx % のデータを訓練セットとして使用しました. このときに工夫した点として,LLM の学習には時間がかかるため,前段でチューニングしたLora adapter を使用することで,継続する形で LLM のチューニングを行いました. コンペ終了後に,各サブの Private Score を見ましたが,この LLM の Pseudo-Label がないサブでは,金圏に残ることができていなかったため,当チームのスコアを底上げしてくれていました.

個人的な反省

ここからはいつも書いているような個人的なメモです.

コンペが終了した今では 14B のモデルを試すべきだと反省していますが,コンペ開催期間中はとにかく多くのモデルを積んだ方が良いと考え,サイズの大きいモデルを使用する選択肢を外してしまっていました. また,BERT 系統のモデルを手元で検証したところ ,xlarge や large よりも base や small の方が性能が良かったこともあり,LLM のサイズも大きくしたところで,あまり効果が期待できないと考えていました. このあたりは取捨選択も大事ですが,可能な限りすべての可能性を試すべきだなと改めて思いました.

BERT 系統はかなり高速化のテクニックが身についていましたが,LLM の高速化などはまだまだ詰めが甘く,14B を採用したら時間の多くが取られてしまうと思っていたので,このあたりのテクニックも改めて学び直す良いきっかけになりました.

おわりに

Jigsaw コンペは,TTT が非常に大事なコンペであり,手元に GPU がなくても上位入賞が可能な近年では珍しい NLP コンペでした. 本業,客員研究員,非常勤講師,書籍執筆など,忙しい中での取り組みでしたが,何とか上位入賞できてよかったです. さらにこの時期は,「NeurIPS - Ariel Data Challenge 2025」や「MAP - Charting Student Math Misunderstandings」と連続でコンペに参加しており,残り10日間で何とか金圏復帰を目指す戦いをしておりました. 短い時間で試行錯誤をたくさん回すことができたのは,このタイミングでチームを組んでくれたチームメンバーのおかげであり,大変感謝しております.

本記事は特段レビューもなく趣味の一環で書いたものですが,書籍の応用編では,NLP コンペで大活躍している著名な Kaggler の皆様に寄稿してもらっており,さらに複数回のレビューも行っています. テキストデータおよび LLM の活用は,現在,非常に注目が集まっており,その活用を手助けするような内容を心がけました. 書籍に込めた思いは,以下の記事にまとめてありますので,良かったら参考にしてください.

takaito0423.hatenablog.com

来年もいろいろなコンペに参加しようと思っておりますので,同じコンペに参加するときには何卒よろしくお願いいたします.

最後まで読んでいただき,ありがとうございました!