ファインチューニングよりヘッドの訓練:BANKING77 で 93.1%
decidekit 0.2 は BANKING77 のテスト分割で 90.6% から 93.1% に、CLINC150 で 94.6% から 96.1% に上がりました。エンコーダーは変えていません。最初にファインチューニングを試しましたが、開発用分割で BANKING77 が 2.5 ポイント、CLINC150 が 1.2 ポイント下がりました。効果があったのは、その上の小さなヘッドを当てはめる最適化手法を、jimothy の設定を使ったフルバッチの Adam に置き換えることでした。npm install decidekit で新しい訓練を使えます。
| テスト精度、全訓練データ | 0.1 | 0.2 | 変化 | 0.1 だけが正解した数 | 0.2 だけが正解した数 |
|---|---|---|---|---|---|
| BANKING77(77 ラベル) | 90.62% | 93.12% | +2.50 | 41 | 118 |
| CLINC150(150 ラベル) | 94.62% | 96.13% | +1.51 | 39 | 107 |
| HWU64(64 ラベル、調整には一切不使用) | 90.15% | 91.17% | +1.02 | 18 | 29 |
シードは 1 つで、デフォルトモデル(bge-small-en-v1.5)の q8 埋め込みをキャッシュして計測しました。対応のある検定(McNemar のカイ二乗)は、上の 2 行で 36.3 と 30.7 です。HWU64 の 2.1 はこのサイズでは有意ではないので、この行は良い兆候という以上のものではありません。train() を通した計測は eval/results-h14.json にあり、BANKING77 が 93.05%、CLINC150 が 96.29% です。同じ方法で計測した 0.1 は 90.7% と 94.4% でした。
すべての実行、テストの確認記録とスクリプトは eval/spike にあります。ファインチューニングのスクリプトは残しておらず、あるのは結果だけです。
前提
判定は 2 つの部分からなります。34 MB のエンコーダーがテキストをベクトルに変え、ヘッド(softmax の層が 1 つ)がベクトルをラベルの確率に変えます。すべてのヘッドが 1 つのキャッシュ済みエンコーダーを共有するので、ヘッドは小さく(77 ラベルで 118,580 バイト)、ブラウザのタブで訓練できます。
作業を始める前に合格基準を決めました。BANKING77 と CLINC150 の平均で +0.5 ポイント以上、どちらのデータセットとラベルあたり 5 例と 10 例で低下は 0.2 以内とします。さらに、HWU64 が下がらないこと、ラベルあたり 10 例以上で較正誤差が 0.03 以下であることです。調整にはシードで固定した 20% の開発用分割を使いました。最終候補ごとにテスト分割を見たのは 1 回だけで、その後は何も変えていません。
1. ファインチューニングは逆効果でした
ファインチューニングには、報告に使うベンチマーク以外の意図データが必要です。これで思った以上に候補が減りました。SLURP の 13,514 件のうち 5,133 件は HWU64 にそのまま含まれています。使ったのは SNIPS(CC0、13,576 件、7 意図)と PAWS の言い換えで、合わせて 41,119 ペアです。MultipleNegativesRanking で 2 エポック訓練し、RTX 5060 で 271 秒かかりました。
訓練の課題そのものでは成功に見えました。取り分けておいた SNIPS での accuracy@1 は 0.949 から 0.985 に上がりました。しかし、本当に必要なデータでは、試した両方のサイズで下がりました。
| 開発用分割の精度 | ラベルあたり | 元のエンコーダー | ファインチューニング後 |
|---|---|---|---|
| BANKING77 | 全部 | 92.45% | 89.91% |
| BANKING77 | 10 | 85.92% | 81.48% |
| CLINC150 | 全部 | 96.63% | 95.40% |
| CLINC150 | 10 | 93.22% | 90.20% |
どちらの列も同じ ONNX 書き出しと q8 量子化を通しているので、差の原因は書き出しではありません。検証はしていませんが、原因は大まかな 7 意図と Wikipedia の言い換えだと推測しています。card_arrival と card_delivery_estimate のような細かい違いを、エンコーダーが見分けにくくなったのでしょう。否定できたのは、このデータの組み合わせとこの設定だけです。
2. 改善の大半はヘッドにありました
同じく小さな意図分類器である jimothy は、古いエンコーダー all-MiniLM-L6-v2 で BANKING77 の 92.4% を報告しています。実行してみると、それ自身の分割でレポートの値は 92.66% でした。つまり効いているのはエンコーダーより最適化手法だと考え、その設定を私たちのヘッドで試しました。
各行は開発用分割で全データを使った 1 回の実行です。
| ヘッドへの変更 | BANKING77 | CLINC150 |
|---|---|---|
| 0.1:ミニバッチ SGD、重み減衰 1e-4 | 88.46% | 95.43% |
| SGD、重み減衰なし | 90.55% | 96.30% |
| ゼロから Adam、lr 0.05、重み減衰なし、100 エポック | 92.35% | 96.67% |
| 同じ設定で、ラベルの重心とラベル名から開始 | 92.85% | 96.90% |
| ゼロから Adam、400 エポック | 92.95% | 96.57% |
| L-BFGS、試した中で最良の重み減衰(1e-5) | 92.75% | 96.67% |
BANKING77 では、重み減衰をなくしただけで改善の約半分になり、残りの大半は Adam によるものです。L-BFGS、400 エポック、ラベルスムージングの差は開発用データで 12 問以内でした。シードが 1 つではこの差で順位は付けられないので、100 エポックの実行を採用しました。decidekit がすでに計算している重心から始めると、少ないデータでの優位が保たれます。ゼロからの Adam は、CLINC150 のラベルあたり 5 例でこれを失いました(91.36% から 90.12%)。
3. 少ないデータでは SGD のままです
重心から始めても、CLINC150 のラベルあたり 5 例で Adam は 0.29 ポイント下がり、基準を超えました。そこで 0.2 は、ラベルあたり平均 8 例以上で Adam を使い、それ未満では SGD のままにしています。計測したのは 5 例と 10 例で、境界そのものは計測していないので、8 は判断で決めた値です。
| テスト精度、3 シードの平均 | ラベルあたり | 0.1 | 0.2 |
|---|---|---|---|
| BANKING77 | 10 | 84.43% | 87.52% |
| CLINC150 | 10 | 92.16% | 92.50% |
| HWU64 | 10 | 85.50% | 85.38% |
| 3 つすべて | 5 | 変化なし | 変化なし |
代償
- 訓練時間: Node でキャッシュ済み埋め込みを使うと、BANKING77 は 84 秒から 123 秒に、CLINC150 は 167 秒から 332 秒に増えました。計測中のマシンは他の作業でも負荷がかかっていました。
- ページの停止: 問題になるものはありません。Ryzen 7 260 のノート PC の Chrome で BANKING77 を最初から最後まで訓練すると 208 秒かかり、最長の停止は 19 ms でした。
- サイズ: 増えません。ヘッドの形は同じです。
- 較正: 全データでは悪化しません。3 つのデータセットすべてで誤差は 0.019 以下です。
- しきい値: 再訓練したヘッドはスコアが変わるので、0.1 で選んだ
minConfidenceはそのまま使えません。CLINC150 の範囲外判定のしきい値は 0.9 から 0.98 に変わりました。保存済みのヘッドは変更なしで動きます。
ここからは言えないこと
- HWU64 はラベルあたり 10 例で下がりました。 低下は 0.12 ポイントで、3 シード、各 1,076 問のうち 4 問分です。合格基準の「下がらないこと」は少ないデータも含むのかを決めていなかったので、私たちはこれを、受け入れた未達と見ています。ラベルあたり 10 例の HWU64 では、1 つのシードの較正誤差も 0.034 で、上限の 0.03 を超えました。0.1 の最悪のシードは 0.048 でした。
- 全データの行はシードが 1 つです。 対応のある検定が見ているのはテストセットで、訓練の実行ごとのばらつきではありません。
- 報告するベンチマークで調整しています。 開発用分割はテストと分けましたが、BANKING77 と CLINC150 が選択に影響したことは変わりません。関わっていないのは HWU64 だけで、その改善幅は最も小さいものです。
- jimothy に勝ったわけではありません。 93.1% と 92.66% では分割とエンコーダーが異なり、設定は jimothy のものです。jimothy は Node で訓練するので、事前の訓練に向いています。
- ラベルあたり 5 例は変わりません。 対照学習の層が役立つかもしれませんが、実行していません。ヘッドごとに約 590 KB(見積もり)増えるうえ、ヘッドの変更ですでに基準を超えていたからです。
自分のラベルで実行して、何が変わったかを Discussions で教えてください。
npm install decidekit@latest