使用 Qwen2.5B + QLoRA 情緒分類模型改善實驗:結構化輸出、CoT 推理與 JSON 評估實作
本章節要將情緒「分類」升級到「結構化輸出」
原本Stage 1 只回一個詞(喜悅)。Stage 2 要回一個 JSON 物件:
{
"instruction": "分析以下文本的情緒,輸出 JSON:emotion(類別)、intensity(1-5)、trigger(觸發詞)、reasoning(分析過程)",
"input": "他竟然在背後說我壞話,我真的快氣炸了",
"output": {
"emotion": "憤怒",
"intensity": 4,
"trigger": "背後說壞話",
"reasoning": "「竟然」表示出乎意料的憤慨,「快氣炸了」是強烈憤怒的慣用表達"
}
}
在這過程中要加入 COT,爲什麽呢?
使用 Qwen2.5B + QLoRA 情緒分類模型改善實驗:擴增資料集至 500~800 筆後 Macro F1 達 0.74
之前使用 kimi 生成約200筆數據,這次將數據量提高到 500~800 筆,再次進行訓練、測試,結果如下
Macro F1 = 0.74(三輪:0.62 → 0.57 → 0.74),Accuracy 0.76。
| - | precision | recall | f1-score | support |
|---|---|---|---|---|
| 喜悅 | 0.90 | 0.90 | 0.90 | 21 |
| 悲傷 | 1.00 | 0.80 | 0.89 | 20 |
| 憤怒 | 0.93 | 0.59 | 0.72 | 22 ← 從 recall 0 救回 |
| 恐懼 | 0.74 | 0.95 | 0.83 | 21 ← 從 recall 0.11 救回 |
| 驚訝 | 0.67 | 0.29 | 0.40 | 14 ← 新的弱點 |
| 厭惡 | 0.54 | 0.90 | 0.68 | 21 |
| macro avg | 0.80 | 0.74 | 0.74 | 119 |
使用 Qwen2.5B + QLoRA 情緒分類模型改善實驗:超參數調整與欠擬合分析
評估結果如下,這是按照生成的數據進行訓練並進行測試給出的結果:
| - | precision | recall | f1-score | support |
|---|---|---|---|---|
| 喜悅 | 0.79 | 1.00 | 0.88 | 11 |
| 悲傷 | 0.44 | 1.00 | 0.62 | 8 |
| 憤怒 | 1.00 | 0.40 | 0.57 | 10 |
| 恐懼 | 1.00 | 0.11 | 0.20 | 9 ← 幾乎全错 |
| 驚訝 | 0.75 | 0.75 | 0.75 | 8 |
| 厭惡 | 0.83 | 0.62 | 0.71 | 8 |
| macro avg | 0.80 | 0.65 | 0.62 | 54 |
下面是評估結論
| 指標 | 結果 | lab目標 | 達標 |
|---|---|---|---|
| Macro F1 | 0.62 | ≥0.75 | ❌ |
| Accuracy | 0.65 | ≥0.80 | ❌ |
| 推理延遲中位數 | 178ms | ≤500ms | ✅ |
| 最容易混淆 | 恐懼 ↔ 悲傷(5 次) | — | — |
使用 Qwen2.5B + QLoRA 微調情緒分類模型:訓練流程與評估結果實作
下面將每筆資料透過 _to_chat_text(...) 組成 ChatML 風格輸入
def _to_chat_text(tokenizer, instruction, user_input, output=None):
"""組成 ChatML 訓練 / 推理文本。output 為 None 時只到 assistant 起始。"""
messages = [{"role": "user", "content": f"{instruction}\n\n文本:{user_input}"}]
if output is not None:
messages.append({"role": "assistant", "content": output})
return tokenizer.apply_chat_template(messages, tokenize=False)
return tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
