Skip to main content

LLMコンペの振り返り

Created on December 20|Last edited on December 20


はじめに

はじめまして。くるぴー (twitter: @kurupical) です。普段は製造業の会社でデータサイエンティストとして働いています。
私は、2023年7月から2023年10月にかけて開催されていたLLM Science Examにソロで参加し、13位 / 2662teams で金メダルを獲得し、Kaggle Grandmasterになることができました!本記事では、最終的な解法ではなく、そこにいたる過程にフォーカスを当て、コンペ期間中に何を考えて取り組んでいたのか、ご紹介いたします。
本コンペの上位解法を知りたい方は、秀逸なまとめ記事がありますのでこちらをご参照ください。

コンペの概要

本コンペは、Kaggleが主催のコンペで、LLMが作った科学に関する5択問題を解くタスクでした。以下に問題の例を掲載します。

[Question]
What is the most popular explanation for the shower-curtain effect?

[Options]
A. The pressure differential between the inside and outside of the shower
B. The decrease in velocity resulting in an increase in pressure
C. The movement of air across the outside surface of the shower curtain
D. The use of cold water
E. Bernoulli's principle

[Answer]
E

評価指標は ``MAP@3`` です (推論時は確信度の高い順番に3つ回答を提出します)

このコンペで特徴的だったのは、訓練データがないことでした。コンペ参加者は、オープンデータやLLMを活用して自分で訓練データを作成する必要がありました。


スペック/環境

コンペ参加に関係する僕の当時の知識および使用した環境を紹介します。

NLPに関する知識
  • NLPコンペ参加経験あり(銀3枚), 基本的な学習/推論コードは実装可
  • ChatGPTは仕事でprompt engineeringを実施した経験がある
  • HuggingFaceで公開されているような 7b, 13b の LLM (``llama2``など) は触ったことがない
計算環境
  • RTX4090 * 1, 256GB RAM のローカルPC
  • 最後の1週間は vast.ai を使用 (費用: $400程度を実費)
vast.ai: GPUサーバーをユーザー同士で貸し借りできるシステム. AWS, GCPより安価だが不安定


コンペ参加で強く意識したこと

これまでに参加したコンペで金メダル獲得を逃した経験から、以下の2つを強く意識して取り組みました。
検証の方向:広く浅く検証ではなく、信じたアイデアと心中する。
  • これまでは、手広く検証してスコアが出なければ諦める、という考えでした。
  • 強いkagglerの話を聞いていると、「最終的なsolutionを描き、そこにたどり着くための実験を行っている」ように見え、今回は強い方向性をもって取り組むことにしました。
「GPUを止めるな」ではなく、「思考を止めるな」
  • GPUを止めないことを過剰に意識してしまい、結果として質の低い実験を繰り返していました。
  • 質の高い仮説を出すことを意識し、仮説が出てこないのであれば「GPUを動かさない」ようにしました。


コンペ参加記

終了1.5か月前から本コンペに参加しました。この節では、コンペ参加で行ったことや、コンペ参加中に考えていたことを記載します。


baseline notebookの調査

私の場合、わからないタスクを解く場合は、はじめに既存のDiscussionやNotebookを調査することが多いです。今回は、以下のアプローチを取っているNotebook からスタートしました。
  • GPTから生成したデータおよびオープンデータから構成された60kの訓練データを使用
  • 問題の関連情報をwikipedia文章から検索しテキストに加えたうえで学習/推論を行う (下図)





notebookの再現実装

公開notebookをベースに、実験管理ができる訓練コードの作成を行いました。

HuggingFaceのTrainerを今回初めて使用しましたが、非常に便利でした。私が今回使いたいパラメータはTrainingArgumentsの引数として実装されていたため、訓練コードはTrainerですべて実装できました。

# 使用するmodel, tokenizerを定義する
model_name = 'microsoft/deberta-v3-large'
model = AutoModelForMultipleChoice.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 訓練パラメータを定義する
training_args = TrainingArguments(
warmup_ratio=0.1,
learning_rate=2e-5,
per_device_train_batch_size=1,
per_device_eval_batch_size=2,
num_train_epochs=2,
report_to='none',
output_dir = f'./checkpoints',
overwrite_output_dir=True,
fp16=True,
gradient_accumulation_steps=8,
logging_steps=25,
evaluation_strategy='steps',
eval_steps=25,
save_strategy="steps",
save_steps=25,
load_best_model_at_end=False,
metric_for_best_model='map@3',
lr_scheduler_type='cosine',
weight_decay=0.01,
save_total_limit=2,
)

# 訓練する
trainer = Trainer(
model=model,
args=training_args,
tokenizer=tokenizer,
# MultipleChoice特有のおまじない
data_collator=DataCollatorForMultipleChoice(tokenizer=tokenizer),
# タスクに応じたDataset の定義 (train/valid)
train_dataset=tokenized_dataset,
eval_dataset=tokenized_dataset_valid,
# カスタム評価関数 (map@3)
compute_metrics=map3
)
trainer.train()

# 訓練済のモデルを保存する
trainer.save_model('model')

実験管理 with wandb!


効果的に検証を行うためには実験管理が不可欠だと考えています。

pytorchの訓練コードを生で書く場合はログを取るコードを書くのも一苦労なのですが、HuggingFaceのTrainerを使う場合は、上記のコードに1行追記するだけでwandbにログを記録してくれます。また、wandbはクラウドサービスのためローカルでの環境構築無しで実験管理ができます。wandbのユーザー登録は数分程度で完了するため、wandb環境の準備 + 実験管理コードの作成があっという間に完成してしまいます。

# report_to = "wandb" を追加するだけでOK
args = TrainingArguments(... , report_to="wandb")

こんな感じのログが出てきます。逐次 wandb の report 機能を使って考察を書いていました。

Run set
6

実験結果と考察



実験の方向性決定

初期調査の段階で、 QAモデルではなく wikipediaの検索(retrieval)にフォーカスするという方向性で実験することを決めました。精度向上の文脈ではモデルのアーキテクチャよりもデータのほうが大事とされるとされており、今回のタスクにおいても「どれだけよい参考文章を取って来れるか」が勝負の鍵になると考えたためです。


QAモデルのfinetune

retrievalに力を入れる前に、QAモデルのfinetuneを1週間程度で実施しました。具体的には以下の通りです。
1. 60k dataset から 1.5kを抽出し、粗く様々なパラメータを探索. (lr, freeze_layers, weight_decay, max_length, etc...)
2. 手順1で判明した特に大事なパラメータ(lr, freeze_layers)を振ってモデルのチューニング

この後の実験は、ここで決まったハイパラでほぼ固定していました。



retrieval専用評価データの作成

小さいサイクルで実験を回すために、retrieval単体で定量評価できる仕組みを構築しました。

  • 背景: 精度はretrieval + QA model の2つの要素で決まるが、1実験につき検索10時間 + モデル訓練2時間 = 12時間かかってしまう。これをもっと短いサイクルで回したい
  • 施策: wikipediaのうち "a" から始まるデータのみで retrieval評価専用の問題を作成した。
具体的には, "a"から始まる科学系のwikipediaページを250件程度収集し、GPT3.5に問題を生成してもらいました(問題・答え・「どのwikipediaページから生成した問題か」のデータを含む)。また、作成した問題文をクエリとし、 "a" から始まるwikipedia全文を検索。生成元の問題と同じページを検索できているかの観点で、Recall@1, Recall@5, Recall@30 の評価指標をもって評価。
  • 効果: retrievalの1実験が 12時間 -> 1時間で完了するようになった。



retrieval初期実装 + 改善

公開notebookのretrieval再現 (Recall@1: 0.5) から, 思い付く改善案を考え実装しました。


上記の施策は、考えて思い付いたものもあれば、間違えた推論に対して以下のような観点で整理することで発見できたものもありました。
  • 事象: 間違えている内容などの事実
  • 原因仮説: なぜその事象が起きているか
  • 対策: 原因仮説を取り除くために必要な施策



後処理の実装

以下の仮説から、後処理を実装しました。
事実
  • retrieval model の recall@1 = 0.925, @5 = 0.95, @30 = 0.995 だった
  • QA model には 上位6件の context を入力していた
仮説
  • recall@5 から recall@30 の間にも僅かながら正しいcontextがあるはず。上位7件以降のデータをcontextに入れ、modelに正しいcontextを与えた状態で推論させたい。
施策
1つの問題あたり 6コンテクスト * 4セットを与えた
  • [1, 2, 3, 4, 5, 6]
  • [1, 7, 8, 9, 10, 11]
  • [1, 12, 13, 14, 15, 16]
  • [1, 17, 18, 19, 20, 21]
※ 配列内の数値は, 上位 i 件の意味
  • 4件の予測値を max + mean でアンサンブル
maxを入れたのは以下2つの考えから:
  • context が正しく与えられたら正解するはず
  • 「正解しているデータ」のシグナルをつかみたい


最後の追い込み

コンペ中盤までに上記の実験を行い、コンペ終盤は細かいところの追い込みを行いました。

retrieval枠組みのパラメータチューニング
  • 区切る単語数(デフォルト150を 60-120で)や、retrievalモデルを変えて実験
  • RTX4090 を使っても1実験10~20時間かかるため、インスタンスに課金
別のQAモデル実験
  • deberta-v3-large シリーズをいくつか訓練させ、アンサンブルに効くかを手元検証
アンサンブル
  • 有効なretrieval, QAモデルのアンサンブルの組み合わせを手元で検証


コンペ感想

LLMコンペの振り返り

コンペを通じてLLMを触ってみたい、と思っていましたが、結局ほとんど触れないままに終わってしまいました。上位者は llama2-7b, llama2-13b 等のLLMモデルをfinetuneして精度を出しておられたので、次回以降は使ってみようと思っています。
また、実用化に向けてはretrievalがかなり大事だと感じました。Discussionなどで参加者が行った実験結果を見てみると、deberta / LLM いずれも retrieval の有無がもっとも精度の差がでています。(下表)
参加する前は、「科学の知識は deberta / LLM の学習用データセットには含まれるはず、5択問題をたくさん解かせてフォーマットさえ覚えさせれば精度が出る」と思っていましたが、実際は全然違いました。

表: 公開されているnotebook の score




Grandmasterになるまでの振り返り

4枚目の金メダルを取った2年前からGrandmasterを目指してコンペに参加していましたが、7回目のチャレンジでようやく目標を達成できました。
振り返ってみると、このチャレンジのなかでコンペへの取り組み方が少しずつ洗練されていったように。特に今回の取り組みにおいては、広く浅く検証ではなく、信じたアイデアと心中する。 の考えのもと、勝負の鍵はretrievalと考え大きくリソースを割けた点と、「GPUを止めるな」ではなく、「思考を止めるな」 の考えのもと、継続的に質の高い実験ができた点、の2点は2年前と比較して成長できたと感じます。また、心中するために値するアイデアを思い付くためには機械学習の場数が必要だと思うので、あきらめずに挑戦し続けてよかったです。


さいごに

本記事では最終的な解法に至るまでのプロセスにフォーカスを当てて記事を作成しました。これを読んでくださったみなさまが、kaggle等のコンペに参加する際や実務で分析する際に本内容を少しでも役立てていただければ幸いです。
また、分析業務において実験管理は不可欠です。実験管理ツールを4種類以上試しましたが、導入にかかるコストや可視化のリッチさから直近のコンペはwandbを愛用しています。(素晴らしいサービスの提供ありがとうございます!) まだ実験管理をされていない方はこれを機にwandbで実験管理を始めてみてはいかがでしょうか!