はじめに
前回の記事では、松尾研のLLMコンペでスコア0.737を達成し、合格ライン(0.7)を突破するまでの道のりを紹介しました。
ひと安心……したのもつかの間、「もっと上に行けるんじゃないか?」という欲が出てきます。
ここからさらに10回の実験を重ねたのですが、待っていたのは失敗の連続でした。データを増やしたらスコアが下がる。最新手法を試したら逆効果。良かれと思った改善が裏目に出る──。
最終的には0.81053まで伸ばせたのですが、正直、たどり着くまでの道のりは地雷原でした。この記事では、その地雷を5つ紹介します。
失敗1: 学習率を0.000001変えただけでスコアが崖落ち
前回の実験で、学習率(モデルが「どれくらいガツガツ学ぶか」を決める数値)は2e-6がベストだと分かっていました。
「じゃあもう少しだけ上げたら?」と3e-6を試してみたところ──
| 学習率 | スコア | 変化 |
|---|---|---|
| 2e-6 | 0.738 | ── |
| 3e-6 | 0.654 | -0.084 |
| 5e-6 | 0.524 | -0.214 |
たった0.000001の違いで、スコアが0.084も下がりました。
5e-6に至っては合格ライン0.7すら下回る大暴落です。
これはかなり衝撃的でした。「ちょっとだけ変えた」つもりが、モデルにとっては「急に勉強スピードを1.5倍にされた」くらいのインパクトだったようです。
教訓: LLMの微調整は学習率に超敏感。「ちょっとだけ」が命取りになる。
失敗2: データを増やしたのにスコアが下がった
前回、「余計な推論ステップ(CoT)が付いたu-10bei系データを外して、クリーンなdaichira系だけにしたらスコアが伸びた」と書きました。
でも「せっかくあるデータを使わないのはもったいない」という気持ちが出てきます。u-10bei系データからCoT部分を取り除いて、出力部分だけを抽出するスクリプトを書きました。これならクリーンなデータとして使えるはず──。
| データ構成 | スコア |
|---|---|
| daichiraのみ(12,000件) | 0.738 |
| daichira + u-10bei混合 | 0.663 |
0.075も下がりました。
さらに調査すると、もう一つ問題が見つかりました。重複除去のスクリプトにバグがあったのです。u-10beiのデータはIDフィールドが全て空(None)で、スクリプトが「全部同じデータだ」と判断して13,087件中13,086件を削除していました。実質、追加したはずのデータが1件しか残っていなかったわけです。
バグを修正して再実験しましたが、それでもスコアは0.663。データの質が合わないものを混ぜると、量を増やしても逆効果でした。
教訓: データは「量」ではなく「質と相性」。出力スタイルが違うデータの混合は危険。
失敗3: DPOという寄り道
SFTの次のステップとして、**DPO(Direct Preference Optimization)**を試しました。
DPOは「良い回答」と「悪い回答」のペアを見せて、モデルに「こっちのほうがいいよ」と教える手法です。人間が好むような回答を出せるようになる──と言われています。
指定データセットにDPO用のデータがあったので、「これを使えばさらに伸びるのでは?」と期待して実験。
結果: 0.706。SFTベストの0.738から**-0.032**。逆効果でした。
原因を調べると、DPOデータの93.8%で**「短い回答のほうが良い」**とラベル付けされていました。モデルは「短く答えるのが正解」と学んでしまい、構造化データに必要な情報まで省略するように。
教訓: 最新手法だからといって効果があるとは限らない。データの中身を確認せずに使うのは危険。
転機: テスト問題を分析してみた
ここまで3連続の失敗。「闇雲に実験するのはやめよう」と方針を変え、テスト問題そのものの分析から始めることにしました。
ベンチマークのテスト150問を分類してみると、衝撃の事実が。
| タスクタイプ | 学習データ | テスト問題 | 状態 |
|---|---|---|---|
| json_to_xml | 1,291件 | 6問 | カバー済み |
| csv_to_xml | 1,309件 | 3問 | カバー済み |
| yaml_to_xml | 0件 | 5問 | 未カバー |
| text_to_xml | 0件 | 6問 | 未カバー |
| ...他6タスク | 0件 | 不明 | 未カバー |
全25タスクタイプのうち、8タスクの学習データが0件。 テスト150問の7.3%が、モデルが一度も見たことのないタスクだったのです。
これではスコアに上限がかかるのは当然です。
そこで、u-10bei系データから足りない8タスクだけを抽出するスクリプトを書きました。前回の失敗で学んだ「フル混合はNG」を踏まえて、ピンポイントで補完する戦略です。
結果: 0.742。地味ですが着実に改善。方向性は合っていました。
教訓: 闇雲に実験する前に、テスト問題を分析する。データの「何が足りないか」を把握するのが先。
失敗4: いいデータも盛りすぎると逆効果
カバレッジ補完がうまくいったので、調子に乗りました。
TOMLフォーマットの正答率が64%と低かったので、「TOML特化のデータを大量に追加すればもっと上がるはず」と、補完データを1,008件 → 2,976件に約3倍に増量。
| 指標 | 増量前 | 増量後 |
|---|---|---|
| パース成功率 | 90.7% | 88.7% |
| TOML正答率 | 64% | 60% |
TOML特化データを増やしたのに、TOMLの正答率が逆に下がりました。 しかも他のフォーマット(YAML、JSONなど)にも悪影響。
料理で言えば「塩が足りないから足したら、今度は塩辛くなった」状態です。補完データが全体の約19%を占めるようになり、元々バランスの取れていたデータの比率を崩してしまいました。
教訓: 弱点を補強するデータも、全体バランスを崩さない量に留める。
突破: 正則化とデータ品質の両輪で0.81
ここまでの4つの失敗から見えてきたのは、**「データをむやみに増やしても効果は薄い」**ということ。では何を変えればいいのか?
答えは**「モデルの学び方そのもの」**でした。
正則化の強化
正則化とは、モデルが学習データを丸暗記するのを防ぎ、初見の問題にも対応できる力(汎化性能)をつけるテクニックです。
たとえるなら、「教科書を丸暗記する勉強法」から「なぜそうなるか理解する勉強法」に切り替えたイメージです。
| 設定 | 変更前 | 変更後 | 何をする設定か |
|---|---|---|---|
| LoRA r | 64 | 32 | 調整するパラメータ数を半減。丸暗記を抑える |
| Label Smoothing | なし | 0.1 | 「正解を100%確信しない」ように学ばせる |
| NEFTune | なし | 5.0 | 学習データに少しノイズを加えて、打たれ強く |
| 勾配クリッピング | 1.0 | 0.5 | 急激な学習を抑えて安定させる |
データ品質の改善
補完データもクリーニングしました。
- TOMLの「ミニファイド形式」(改行なしの1行表記)を除去
- 50文字未満の短すぎる出力を除去
- CSVでデータ行がないもの(ヘッダーのみ)を除去
- 全件100%パース成功を確認してから学習に使用
量を増やすのではなく、既存データの質を上げる方向に切り替えたわけです。
結果
| 指標 | 改善前 | 改善後 |
|---|---|---|
| スコア | 0.742 | 0.81053 |
| パース成功率 | 86.0% | 90.7% |
| JSON | 96% | 98% |
| TOML | 52% | 64% |
| CSV | 75% | 100% |
+0.068の大幅改善で0.81を突破。 CSVは100%パース成功。
正則化の効果がここまで大きいとは正直驚きました。データの量や種類をいじるより、「モデルの学び方」を変えたほうが効果的だったのです。
まとめ: 5つの地雷と教訓
| # | 地雷 | 教訓 |
|---|---|---|
| 1 | 学習率を少し上げたら崖落ち | ハイパーパラメータに超敏感。微調整の名に偽りなし |
| 2 | データを混ぜたら悪化 | 質と相性が大事。量を増やせばいいわけじゃない |
| 3 | DPOで逆効果 | 手法よりデータの中身。バイアスを事前に確認 |
| 4 | 補強データを盛りすぎた | 全体のバランスを崩さない量に留める |
| 5 | (転機)テスト分析で方向転換 | 闇雲に実験せず、まず課題を特定する |
0.737から0.81053へのスコア改善で最も効いたのは、派手な手法の導入ではなく、地味なデータクリーニングと正則化パラメータの調整でした。
思いつきで実験を繰り返すのではなく、テスト問題を分析して課題を特定 → 仮説を立てて → 小さな変更で検証。このサイクルを回せるようになったのが、失敗を重ねた一番の収穫だったと思います。
この記事は、松尾研LLM講座のコンペティションに参加した際の備忘録です。
前編: 構造化データ変換に特化したローカルLLMを作る ── SFTコンペ挑戦記