多任務微調:一個介面卡處理多種任務
為每個任務訓一個介面卡,維運會爆炸。合併訓練有技巧。
當你有五種相關任務(分類、抽取、摘要、改寫、路由)時,訓五個介面卡意味著五套版本管理、五組評測、五次部署。多任務微調能把它們收成一個。
但合併不是把資料倒在一起就好。沒有處理好任務區分與資料配比,結果通常是每個任務都比單獨訓練差。
一、用明確的任務標記
# 每筆訓練資料的 system 訊息明確標示任務
{"messages": [
{"role": "system", "content": "[TASK:classify] 你是客服工單分類助手。"},
{"role": "user", "content": "..."},
{"role": "assistant", "content": "{\"type\":\"logistics\"}"}
]}
{"messages": [
{"role": "system", "content": "[TASK:extract] 從工單抽取結構化欄位。"},
...
]}任務標記讓模型能清楚切換模式。推論時務必用完全相同的標記格式,這是最常見的錯誤來源。
二、資料配比
- 不要按資料量的自然比例——樣本多的任務會主導訓練。
- 常見做法是開根號取樣:任務權重與樣本數的平方根成正比,平衡大小任務。
- 關鍵任務可以額外加權。
import math, random
def balanced_sample(datasets, total):
weights = {k: math.sqrt(len(v)) for k, v in datasets.items()}
s = sum(weights.values())
out = []
for k, v in datasets.items():
n = int(total * weights[k] / s)
out += random.choices(v, k=n) # 小資料集會被重複取樣
random.shuffle(out)
return out三、評測要分任務看
多任務模型的整體分數毫無意義。必須每個任務各自評測,並與「單任務專用介面卡」比較。可接受的結果是:每個任務比專用版低 1–2 個百分點,換來單一模型的維運簡化。
for task in TASKS:
single = eval_adapter(f'adapter-{task}', evalsets[task])
multi = eval_adapter('adapter-multi', evalsets[task], task_tag=task)
print(f'{task:10} 單任務 {single:.3f} / 多任務 {multi:.3f} '
f'/ 差距 {multi-single:+.3f}')四、什麼時候不要合併
- 任務之間的輸出格式差異極大(例如一個要 JSON、一個要長文)。
- 某個任務的資料量遠大於其他(差一個數量級以上)。
- 各任務的更新頻率不同——合併後任一任務要更新都得重訓全部。
- 任務有不同的權限或資料敏感度要求。
漸進式合併
務實的做法是先訓兩個最相關的任務,驗證合併沒有損失,再逐步加入第三、第四個。一次合併五個任務,出問題時無法定位是哪一個造成的。
把任務標記設計成可擴充的格式(例如
[TASK:xxx])。日後新增任務時,舊資料不需要重新處理。訂閱後繼續閱讀全文
本篇為訂閱者專屬內容。訂閱後可取得下列權限:
- 解鎖全部內容權限
- 閱讀不限篇數
- 全站移除廣告
月卡
NT$240
開通 30 天
一次付清,開通 30 天
季卡
NT$620
開通 90 天
一次付清,開通 90 天,每天約 NT$7
年卡
NT$2,160
開通 365 天
一次付清,開通 365 天,每天約 NT$6
一次性付款,付款成功後立即開通,到期自動結束,不會再次扣款,也不需要取消訂閱。
立即訂閱
金額均為新臺幣(TWD),即實際扣款金額,不另收手續費
支援信用卡 · Apple Pay · Google Pay · WebATM · ATM 轉帳
購買須知與退款政策