iT邦幫忙

2025 iThome 鐵人賽

0
AI & Data

從RAG到EmoRAG:讓AI真正聽懂你的心聲系列 第 31

[番外篇・重製版]用 BERT 微調+BGE 混合檢索把 EmoRAG 做到能跑(誠實實作版成果)

  • 分享至 

  • xImage
  •  

這篇是 30 天系列的補完。系列文在第 10 天之後就沒有可執行的實作、第 30 天也坦承「斷賽」與硬體限制。這裡用一套能在 RTX 4060(8GB VRAM)本機完整跑完的方案重建文字版 EmoRAG,並且把數字老實攤開——包含做得好的、和還做不到的。


架構總覽

EmoRAG 重製版架構圖

三段式流程:① 訓練(先切分再增強的誠實流程、兩階段微調)→ ② 推理檢索管線(分類偵測情緒 → BM25+BGE 融合 → 情緒加權 → rerank)→ ③ 檢索層評測(Hit Rate / MRR)。


一、為什麼要重做:先認帳系列文的四個坑

  1. 第 2 天那個 0.95 是假的。 當時是「先用隨機複製做類別平衡,再切訓練/測試集」,複製出來的同一筆同時落在兩邊,屬於資料洩漏(data leakage),準確率被灌水。
  2. all-MiniLM-L6-v2 處理中文效果差。 它是英文為主的輕量模型,第 30 天就是卡在這裡。
  3. cross-encoder/ms-marco-MiniLM-L-6-v2 這個 reranker 不支援中文(第 11 天自己也指出了),用在中文檢索會越排越差。
  4. Qwen3-Embedding-0.6B 記憶體跑不動,所以微調的念頭無疾而終。

這篇的目標不是「衝出漂亮數字」,而是把流程接成一條可重現、且誠實標示能力邊界的線。


二、方法:換掉每一個有問題的零件

2.1 情緒分類器(取代第 2 天的 TF-IDF+隨機過採樣)

  • 模型hfl/chinese-macbert-base(102M 參數,fp16 微調尖峰約 5GB,4060 跑得動),四類分類:積極/消極/中性/期待。
  • 三個準確度強化手段
    • 資料增強:替弱勢類別(中性、期待)補樣本,但只加進訓練集
    • 兩階段訓練:Stage1 先在 ChnSentiCorp(9,600 筆中文評論正/負)做二分類預熱,讓 BERT 先熟悉中文情感語料;Stage2 換 4 類分類頭微調。(CPU 環境會自動跳過 Stage1。)
    • Label smoothing(0.05):小資料集防止模型過度自信。
  • 不平衡處理:改用 class weights,不再用隨機過採樣。
  • 杜絕洩漏的關鍵動作先切 train/test → 測試集只保留原始、未增強的資料 → 增強句若與測試集重複就剔除。所以底下的數字反映的是真實能力,不是看過答案。

2.2 檢索層(取代第 4–5 天)

使用者查詢
  ├─① MacBERT 分類 → 偵測目標情緒
  ├─② BM25 關鍵字檢索(jieba 分詞)
  ├─③ BGE 向量檢索(BAAI/bge-base-zh-v1.5 + ChromaDB, cosine)
  ├─④ 分數融合 + 情緒加權(emotion_boost,已修正為只套用一次)
  └─⑤ Rerank(BAAI/bge-reranker-base,中文原生,取代不支援中文的 ms-marco-MiniLM)

向量檢索在查詢端加上 BGE 建議的 instruction 前綴;reranker 輸出過 sigmoid 正規化到 [0,1] 以利跨查詢比較。情緒加權原本在 BM25/向量/rerank 三個階段各乘一次(等於加權三次),已改為只在最終分數套用一次


三、誠實的成果

3.1 訓練設定

原始 380 筆(積極 186/消極 140/中性 13/期待 41),增強 +236 筆(補中性、期待),切成訓練 540 筆/測試 76 筆(純原始)。5 epochs + early stopping,CPU 實測 train_runtime ≈ 147 秒(約 2.5 分鐘;4060 GPU 會更快,另加 Stage1 預熱約 5–8 分鐘)。

3.2 測試集表現(純原始資料、無洩漏)

類別 precision recall f1-score support
積極 1.00 0.97 0.99 40
消極 0.97 1.00 0.98 30
中性 0.00 0.00 0.00 1
期待 0.83 1.00 0.91 5
accuracy 0.97 76
macro avg 0.70 0.74 0.72 76
weighted avg 0.96 0.97 0.97 76

混淆矩陣:積極 39 對、1 筆被判成期待;消極 30 筆全對;中性唯一 1 筆被判成消極;期待 5 筆全對。

這份報表想講的重點不是 0.97,而是 0.72。 weighted-F1 0.97 看起來漂亮,是因為積極+消極佔了 70 筆;但 macro-F1 只有 0.72,而且中性類 recall = 0——測試集裡中性只有 1 筆,模型根本沒機會、也沒能力學好它。

3.3 老實說:數字會抖

換另一次(CPU、沒跑 Stage1 預熱)的結果是 accuracy 0.92/macro-F1 0.67,中性類(那次 support=3)一樣 recall = 0。兩次跑下來的共同結論很一致:

強勢類別(積極/消極)很穩,弱勢類別(中性/期待)受小樣本主宰、會隨切分抖動,中性幾乎必掛。這是資料規模問題,不是調個超參數就能補的。

3.4 一個具體的「修好了」

系列文第 6 天那句被判成「正面」的句子,在新分類器上:

輸入 預測 信心度
生成的程式碼一直報錯我好煩躁喔 消極 0.839 ✅(第 6 天原誤判為正面)
這個產品真的很棒,我非常滿意 積極 0.796
服務態度太差了,讓我很失望 消極 0.911
我渴望它能有更強的創造力 期待 0.929
我把檔案備份好之後就下班了 中性 0.924
還可以,沒什麼特別的感覺 消極 0.539 ⚠️(其實偏中性,低信心,正是中性弱項的體現)

3.5 與系列文舊版的差異

舊版(系列文) 新版(emorag_bert)
TF-IDF + LogisticRegression(第 2 天) BERT 端到端微調,理解語意而非詞頻
先過採樣再切分 → 0.95 虛高 先切分、測試集純原始 → macro-F1 0.72(誠實)
all-MiniLM-L6-v2(中文差) bge-base-zh-v1.5(中文專用)
ms-marco-MiniLM reranker(不支援中文) bge-reranker-base(中文原生)
情緒加權重複套用(三重) 只在最終分數加權一次
Colab T4 雲端、片段程式碼 RTX 4060 本機、完整可跑

四、還沒解決的(不藏)

  • 中性/期待樣本太少,macro-F1 被中性拖垮;要再往上,得先補資料而不是換模型。
  • 資料品質:原始資料多為「……讓我感到 X」的模板化造句,且 emotiontag 標籤有衝突。清理腳本見 emorag_bert/clean_dataset.py,待人工複核的衝突清單見 label_conflicts_reviewed.csv
  • 檢索層還沒做端到端量化評測(Hit Rate、MRR 都還沒跑),目前有數字的只有分類器。
  • 圖像/多模態還沒接進這條 BERT 線,本篇只重建了文字 EmoRAG。

五、怎麼跑

Emorag_bert

# 1. 環境(Windows PowerShell;4060 用 CUDA 版 PyTorch)
python -m venv venv ; .\venv\Scripts\Activate.ps1
pip install torch --index-url https://download.pytorch.org/whl/cu121
pip install -r requirements.txt

# 2.(建議)先清資料,產生 emotion_dataset_clean.csv 與 label_conflicts.csv
python clean_dataset.py

# 3. 微調情緒分類器
python train_bert_emotion.py

# 4. 跑情緒感知檢索 demo(含互動查詢)
python emorag_pipeline.py

六、結論

把 0.95 換成 0.72,數字看起來退步了,但它第一次反映了模型真正的能力:強勢情緒判得準、弱勢情緒(尤其中性)因資料太少而學不起來。對一個入門學習專案來說,一個誠實、可重現、知道自己邊界在哪的 0.72,遠比一個藏著資料洩漏的 0.95 有價值——因為它清楚告訴你下一步該做什麼:補資料、清標籤,而不是繼續換模型。

數據來源:emorag_bert/eval_report.txt(測試集報表與 demo 預測)、emorag_bert/train_log_clean.txt(訓練過程與另一次跑的對照)、emorag_bert/README.md(硬體與模型設定)。


上一篇
[總結]第30天:總結
系列文
從RAG到EmoRAG:讓AI真正聽懂你的心聲31
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言