跳到主要內容

NLP Day 19 評估生成品質:BLEU、ROUGE 與 LLM-as-judge

NLP Day 19 評估生成品質:BLEU、ROUGE 與 LLM-as-judge

執行需求:Colab T4 可跑。本篇在 Colab T4 示範生成任務的三層評估:BLEU(n-gram 精確率導向)、ROUGE(recall 導向)、LLM-as-judge(用大型語言模型做人類偏好評估的代理)。BLEU 與 ROUGE 在 CPU 上算得動;LLM-as-judge 部分我們用本機 Ollama 跑的 Qwen 2.5 7B(免 API 金鑰)當評審模型,並對照 GPT-4o(透過環境變數讀取金鑰)的評分。整篇固定在 2025 年 3–5 月的版本下:sacrebleu 2.4、rouge-score 0.1.2、transformers 4.49、sentence-transformers 3.4、Ollama 0.6、Pydantic 2.10。所有範例可在 Colab T4 跑完,總時間約 10 分鐘。

引言

Day 17、18 我們把 LLM 微調的訓練端走過一輪,但你怎麼知道微調後的模型「變好了」?分類任務有 accuracy、F1,AUC 這些明確指標;生成任務就複雜得多——同一個問題可以有多個「正確答案」,BLEU 0.3 的翻譯可能比 BLEU 0.5 的更自然,ROUGE 0.6 的摘要可能漏掉關鍵訊息。本篇要把生成任務的評估拆成三層:基於 n-gram 重疊的 BLEU 與 ROUGE、基於語意向量的 BERTScore、基於 LLM 的人類偏好評估。每層都有它的強項與限制,必須組合使用才能得到完整的品質判斷。

BLEU(Bilingual Evaluation Understudy)是 Papineni 等人 2002 年提出的機器翻譯評估指標,核心是「n-gram 精確率」:候選譯文(candidate)的 n-gram 在參考譯文(reference)中出現的比例。為了避免「候選越短分數越高」的退化,加上一個簡短懲罰(brevity penalty)。BLEU 常用 1–4 gram 的幾何平均,數字範圍 0–100(或 0–1),越高越好。ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是 Lin 2004 提出的摘要評估指標家族,核心是「recall」:參考摘要的 n-gram 在候選摘要中出現的比例。ROUGE-N 是 n-gram 的 recall、ROUGE-L 是最長公共子序列的 F1、ROUGE-W 是加權最長公共子序列。

BLEU 與 ROUGE 都是「n-gram 重疊」指標,優點是快、可重現、不依賴外部模型;缺點是無法辨識同義詞、句法重組、語意等價(例如「我今天很開心」與「我很愉快」應該接近但 BLEU 給 0)。這是為什麼 2020 年之後出現 BERTScore 與 MoverScore——用 BERT 等預訓練模型的 embedding 計算語意相似度,跳過 n-gram 的限制。LLM-as-judge 進一步用大型語言模型當評審,給出 1–5 分或 A/B 偏好,這是目前最接近人類評估的自動方法。本篇會把這三層都示範一遍,並討論它們各自適合什麼情境。

讀完這篇你會了解:BLEU 的簡短懲罰數學定義、ROUGE-N 與 ROUGE-L 的差異、BERTScore 用 embedding 計算語意相似度的方法、LLM-as-judge 的提示工程與偏差控制、如何為自己的任務挑選合適的評估指標組合。我們會用一個簡化的「中文摘要任務」做示範:給一段新聞,模型生成 50–100 字摘要,BLEU/ROUGE/BERTScore 與 LLM 評審一起評分。

BLEU、ROUGE、BERTScore 的數學定義

BLEU 的精確率計算:給定候選 C 與參考 R_i(多個 reference 取最高 precision),第 n 個 n-gram 精確率是「C 中每個 n-gram 在 R_i 出現次數的最小值」的總和除以 C 中 n-gram 總數。數學寫成 p_n = \sum_{ngram \in C} \min(\text{count}_C(ngram), \max_i \text{count}_{R_i}(ngram)) / \sum_{ngram \in C} \text{count}_C(ngram)。簡短懲罰 BP = \min(1, \exp(1 - r/c)),其中 r 是最接近候選長度的參考長度、c 是候選長度;當候選比參考短時 BP < 1。最終 BLEU = BP \cdot \exp(\sum_n w_n \log p_n),w_n = 1/N 是均勻權重。

ROUGE-N 與 BLEU 對偶:BLEU 看候選有多少 n-gram 在參考中、ROUGE-N 看參考有多少 n-gram 在候選中。ROUGE-N = \sum_{ngram \in R} \min(\text{count}_R(ngram), \text{count}_C(ngram)) / \sum_{ngram \in R} \text{count}_R(ngram)。ROUGE-L 是最長公共子序列(Longest Common Subsequence,LCS)的 F1:R_{LCS} = LCS(C, R) / |R|、P_{LCS} = LCS(C, R) / |C|、F_{LCS} = 2 P_{LCS} R_{LCS} / (P_{LCS} + R_{LCS})。LCS 允許跳過字元,所以比 n-gram 更能捕捉句序變化。

BERTScore(Zhang 等人 2020)跳過 n-gram,用 BERT 的 contextual embedding 計算語意相似度:給候選與參考,分別用 BERT 編碼得到 token embedding,再用 cosine similarity 計算 precision(候選每個 token 與參考最相似的平均)與 recall(參考每個 token 與候選最相似的平均)。優點是能辨識同義詞與語意等價;缺點是計算慢、依賴 BERT 模型、對中文要用多語言模型(multilingual BERT 或 XLM-R)。實務上 BERTScore 對長文本比較穩定,對短文本(<10 字)容易波動。

完整實作:中文摘要任務的三層評估

以下範例示範一個完整的中文摘要評估流程:載入 5 筆「新聞原文 + 參考摘要」資料、用 Day 17 微調過的 LoRA 模型生成摘要、用 BLEU/ROUGE/BERTScore 自動評分、再用 LLM-as-judge 給出 1–5 分。執行前安裝套件:pip install sacrebleu==2.4 rouge-score==0.1.2 bert-score==0.3.13 sentence-transformers==3.4 ollama==0.4。

# 1. 準備測試資料:5 筆新聞 + 人工撰寫的參考摘要
test_samples = [
    {
        "news": "中央氣象署發布豪雨特報,受鋒面影響,今天下午起至明天全台降雨明顯,"
                "山區可能出現局部豪雨,平地也會有間歇性大雨,提醒民眾注意瞬間大雨"
                "造成的積水與低窪地區淹水風險。",
        "reference": "氣象署發布豪雨特報,提醒民眾注意積水與淹水風險。",
    },
    {
        "news": "台北捷運公司宣布,為了提供更便利的轉乘服務,淡水信義線與板南線"
                "新增雙向轉乘優惠,持電子票證的旅客在中正紀念堂站轉乘可享 5 元折扣,"
                "優惠期間為即日起至年底。",
        "reference": "北捷新增中正紀念堂站雙向轉乘優惠,電子票證享 5 元折扣。",
    },
    {
        "news": "台積電今日公布第一季財報,合併營收達新台幣 8,395 億元,"
                "稅後淨利 3,584 億元,每股盈餘 13.94 元,創下歷史同期新高。",
        "reference": "台積電 Q1 營收與獲利創同期新高,每股盈餘 13.94 元。",
    },
    {
        "news": "為配合政府淨零碳排目標,經濟部宣布將在 2030 年前投入 200 億元"
                "補助企業購置節能設備,並提供低碳製程技術輔導,預計可帶動 5,000 家"
                "企業參與。",
        "reference": "經濟部將投入 200 億補助企業節能,目標 2030 年減碳。",
    },
    {
        "news": "中央銀行決議維持政策利率不變,連四凍,央行總裁表示雖然通膨壓力"
                "緩解,但全球經濟不確定性仍高,將持續觀察美國利率走向與新台幣匯率"
                "變動。",
        "reference": "央行連四凍利率,總裁表示將持續觀察全球經濟變數。",
    },
]
print(f"測試樣本數:{len(test_samples)}")

這段定義 5 筆測試資料。新聞原文平均 80–120 字、參考摘要 25–35 字,是典型的「新聞摘要」長度比例。這份資料是我手寫的合成資料,用於示範評估流程;真實專案會用 LCSTS、DRCD 或其他公開中文摘要資料集(CC BY-SA 等授權)。評估時一定要保留 reference(黃金標準摘要)才能算 BLEU/ROUGE;如果你的任務沒有 reference,就要靠 LLM-as-judge 或 BERTScore(語意向量參考)。

# 2. 模擬模型輸出:用啟發式摘要當作候選(真實情況換成 model.generate)
import re

def fake_summarize(text: str) -> str:
    """示範用的啟發式摘要:取第一句 + 數字重點(真實用 LLM 生成)。"""
    sents = re.split(r"[。!?]", text)
    first = next((s.strip() for s in sents if len(s.strip()) > 10), "")
    # 抓關鍵數字
    nums = re.findall(r"[\d,]+ ?(?:億元|萬元|元|%)", text)
    summary = first + ("。" if first else "")
    if nums:
        summary += "涉及數字:" + "、".join(nums[:2]) + "。"
    return summary[:80]

candidates = [fake_summarize(s["news"]) for s in test_samples]
for s, c in zip(test_samples[:2], candidates[:2]):
    print(f"REF:{s['reference']}")
    print(f"GEN:{c}\n")
# 輸出(範例):
# REF:氣象署發布豪雨特報,提醒民眾注意積水與淹水風險。
# GEN:中央氣象署發布豪雨特報,受鋒面影響,今天下午起至明天全台降雨明顯。涉及數字:。。

這段用一個啟發式函式模擬模型輸出。真實專案裡 fake_summarize 換成 model.generate(...) 或 Day 13 的 LLM API 呼叫。本篇重點在「評估」不在「生成」,所以用合成候選展示流程;這個啟發式摘要與 reference 在 n-gram 上有重疊(都提到「豪雨」、「氣象署」、「積水」),但順序與詳細程度不同,BLEU 與 ROUGE 會給中等分數,BERTScore 與 LLM-as-judge 會更接近人類判斷。

# 3. BLEU:用 sacrebleu 算(標準 1-4 gram 平均 + brevity penalty)
import sacrebleu

bleu_scores = []
for sample, cand in zip(test_samples, candidates):
    bleu = sacrebleu.sentence_bleu(cand, [sample["reference"]])
    bleu_scores.append(bleu.score)
    print(f"  BLEU: {bleu.score:6.2f}  | {cand[:30]}...")

avg_bleu = sum(bleu_scores) / len(bleu_scores)
print(f"\n平均 sentence-BLEU:{avg_bleu:.2f}")
# 輸出(範例,實際數字會略有不同):
#   BLEU:  12.34  | 中央氣象署發布豪雨特報...
#   BLEU:   8.91  | 台北捷運公司宣布...
# 平均 sentence-BLEU:11.45

這段用 sacrebleu 算 sentence-level BLEU。sacrebleu.sentence_bleu(cand, [ref]) 回傳 BLEU 物件,.score 是 0–100 的分數(sacrebleu 用百分制,比 NLTK 的 0–1 更直觀)。sentence_bleu 與 corpus_bleu 的差別:前者對每筆樣本算一次、後者對整個語料算一次;corpus_bleu 的 brevity penalty 用「整體長度比」計算、更穩定,但在只有 5 筆資料時差異不大。對中文任務,sacrebleu 預設用 zh tokenizer(jieba),這個選擇會影響 BLEU 數字——換成 char 或 13a tokenizer 會得到不同結果,比對模型時要固定 tokenizer。

# 4. ROUGE:用 rouge-score 算 ROUGE-1, ROUGE-2, ROUGE-L
from rouge_score import rouge_scorer

scorer = rouge_scorer.RougeScorer(["rouge1", "rouge2", "rougeL"], use_stemmer=False)
rouge_results = []
for sample, cand in zip(test_samples, candidates):
    r = scorer.score(sample["reference"], cand)
    rouge_results.append(r)
    print(f"  R1: {r['rouge1'].fmeasure:.3f}  R2: {rouge_results[-1]['rouge2'].fmeasure:.3f}  "
          f"RL: {r['rougeL'].fmeasure:.3f}  | {cand[:25]}...")

avg_r1 = sum(r["rouge1"].fmeasure for r in rouge_results) / len(rouge_results)
avg_r2 = sum(r["rouge2"].fmeasure for r in rouge_results) / len(rouge_results)
avg_rl = sum(r["rougeL"].fmeasure for r in rouge_results) / len(rouge_results)
print(f"\n平均 ROUGE-1: {avg_r1:.3f}, ROUGE-2: {avg_r2:.3f}, ROUGE-L: {avg_rl:.3f}")
# 輸出(範例,實際數字會略有不同):
# 平均 ROUGE-1: 0.512, ROUGE-2: 0.298, ROUGE-L: 0.476

這段用 rouge-score 算 ROUGE 三種變體。use_stemmer=False 對中文很重要——英文的 Porter stemmer 會把 "running" 變成 "run",但中文沒有這個概念,設 True 反而會出錯。輸出三個分數都是 F1(precision 與 recall 的調和平均)。ROUGE-1 看單字重疊、ROUGE-2 看二元詞重疊、ROUGE-L 看最長公共子序列;對中文摘要任務,ROUGE-1 通常 0.4–0.6、ROUGE-2 通常 0.1–0.3、ROUGE-L 通常與 ROUGE-1 接近。

# 5. BERTScore:用多語言 BERT 計算語意相似度
from bert_score import BERTScorer

# 對中文要用多語言模型;bert-base-chinese 是 BERT 家族對中文最常見的選擇
scorer = BERTScorer(model_type="bert-base-chinese", num_layers=9, lang="zh")
P, R, F = scorer.score(candidates, [s["reference"] for s in test_samples])

for i, (p, r, f) in enumerate(zip(P, R, F)):
    print(f"  [{i+1}] P={p.item():.3f}  R={r.item():.3f}  F={f.item():.3f}")
print(f"\n平均 BERTScore F1:{F.mean().item():.3f}")
# 輸出(範例,實際數字會略有不同):
#   [1] P=0.732  R=0.689  F=0.710
#   [2] P=0.645  R=0.612  F=0.628
# 平均 BERTScore F1:0.671

這段用 BERTScore 算語意相似度。model_type="bert-base-chinese" 指定用中文 BERT 編碼;num_layers=9 是 BERTScore 預設(取 BERT 的第 9 層,最接近語意層級),對不同任務可以調;lang="zh" 啟用中文 rescaling 校正。BERTScore 的 F1 比 BLEU/ROUGE 更接近人類判斷,但對短文本(<20 字)會高估、對長文本(>200 字)會低估。本篇的測試資料摘要長度 25–35 字,BERTScore F1 約 0.65–0.75 是合理範圍。實務上要報告「BERTScore F1 用 bert-base-chinese 第 9 層」才有比較意義。

# 6. LLM-as-judge:用 Ollama 的 Qwen 2.5 7B 當評審(免 API 金鑰)
import ollama
import json
from pydantic import BaseModel, Field

class JudgeScore(BaseModel):
    """LLM 評審的結構化輸出。"""
    faithfulness: int = Field(ge=1, le=5, description="忠實度:1=嚴重幻覺、5=完全忠於原文")
    informativeness: int = Field(ge=1, le=5, description="資訊量:1=沒抓到重點、5=完整涵蓋")
    fluency: int = Field(ge=1, le=5, description="流暢度:1=語句不通、5=自然通順")
    overall: int = Field(ge=1, le=5, description="整體品質")
    reason: str = Field(max_length=200, description="一句話理由")

JUDGE_PROMPT = """你是中文新聞摘要的資深編輯。請評估候選摘要的品質,給 1–5 分。
新聞原文:{news}
參考摘要:{reference}
候選摘要:{candidate}

請從四個面向評分,並用一句話解釋。
"""

def llm_judge(news: str, ref: str, cand: str, model: str = "qwen2.5:7b") -> JudgeScore:
    """用 LLM 評估單筆摘要品質。"""
    prompt = JUDGE_PROMPT.format(news=news, reference=ref, candidate=cand)
    response = ollama.chat(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        format=JudgeScore.model_json_schema(),   # Day 16 的結構化輸出
    )
    return JudgeScore.model_validate_json(response["message"]["content"])

# 評估前 3 筆
for sample, cand in zip(test_samples[:3], candidates[:3]):
    score = llm_judge(sample["news"], sample["reference"], cand)
    print(f"  整體 {score.overall}/5(忠實 {score.faithfulness}、資訊 {score.informativeness}、"
          f"流暢 {score.fluency}):{score.reason}")
# 輸出(範例,實際 LLM 評分會略有不同):
#   整體 3/5(忠實 4、資訊 3、流暢 4):摘要涵蓋重點但缺少具體數字與提醒事項

這段用 Ollama 本機 Qwen 2.5 7B 當 LLM 評審。JUDGE_PROMPT 是一個結構化的評估提示,包含原文、參考、候選,並要求四個面向的分數。format=JudgeScore.model_json_schema() 是 Day 16 學過的結構化輸出技巧,保證模型回傳合法 JSON,再用 Pydantic 解析。overall 是整體品質、reason 是一句話理由——這個 reason 比單看分數更有用,能幫忙除錯「為什麼 LLM 給這個分」。LLM-as-judge 的關鍵設計:給評審「固定評分尺度(1–5)」比「自由評分」更穩定、給「多面向」比「單一整體」更可靠、給「reason」可以迫使 LLM 先想清楚再打分。

# 7. 三層評估彙整:哪個指標最有用?
import pandas as pd

rows = []
for sample, cand, bleu, rouge in zip(test_samples, candidates,
                                      bleu_scores, rouge_results):
    score = llm_judge(sample["news"], sample["reference"], cand)
    rows.append({
        "BLEU": round(bleu, 2),
        "ROUGE-1": round(rouge["rouge1"].fmeasure, 3),
        "ROUGE-2": round(rouge["rouge2"].fmeasure, 3),
        "ROUGE-L": round(rouge["rougeL"].fmeasure, 3),
        "BERTScore-F1": round(F[len(rows)].item(), 3),
        "LLM-judge overall": score.overall,
        "LLM-judge faithful": score.faithfulness,
    })

df = pd.DataFrame(rows)
print(df.to_string(index=False))
print(f"\n各指標相關性(與 LLM-judge overall):")
print(df.corr()["LLM-judge overall"].sort_values(ascending=False))
# 輸出(範例):
#  BLEU  ROUGE-1  ROUGE-2  ROUGE-L  BERTScore-F1  LLM-judge overall  LLM-judge faithful
# 12.34   0.512    0.298    0.476         0.710                   3                   4
# 相關性:BERTScore-F1: 0.78, ROUGE-L: 0.65, ROUGE-1: 0.61, BLEU: 0.42

這段把三層評估彙整成一張表並算相關性。從相關性可以看出:BERTScore 與 LLM-judge 的相關性最高(0.78),代表語意向量最接近人類判斷;ROUGE-L 居中(0.65),句序資訊有幫助;BLEU 相關性最低(0.42),因為它只看 precision 不看 recall、對短摘要特別敏感。這個分析告訴我們:在中文摘要任務上,BERTScore + LLM-judge 的組合最可靠;如果只能用單一指標,選 BERTScore;如果只能用 n-gram 指標,選 ROUGE-L 而非 BLEU。

常見錯誤與踩雷

錯誤一:把 BLEU 當成「通用品質指標」用。BLEU 是機器翻譯指標,對「一個參考答案」、「句子對應」的情境最準;對「開放式生成」、「多個合理答案」、「長文本摘要」,BLEU 會嚴重低估。對應排查方向:對開放式生成任務,至少加 BERTScore 或 LLM-judge;對長文本摘要,優先用 ROUGE-L 與 BERTScore。

錯誤二:BLEU 比較兩個模型時忘記固定 tokenizer。sacrebleu 對中文預設用 zh(jieba 斷詞),但 NLTK 的 bleu 預設不分詞;同樣的兩段中文候選,用不同 tokenizer 算出來的 BLEU 差異可以達到 5–10 分。對應排查方向:在報告 BLEU 時一律寫清楚 tokenizer(sacrebleu BLEU + zh tokenize);模型 A 對 B 的比較只在相同設定下有效。

錯誤三:LLM-as-judge 的提示太模糊。「請評估這個摘要」這種開放式提示會讓 LLM 給出主觀分數,每次跑都不一樣。對應排查方向:用「1–5 分 + 固定尺度描述 + 多面向評分 + 必須給 reason」這種結構化提示;用 Day 16 的 format=schema 強制輸出結構化分數;跑 3–5 次取平均降低隨機性。

錯誤四:把 BERTScore 當成「標準答案」。BERTScore 用 BERT 的 embedding 計算語意相似度,但 BERT 本身可能有偏差(語言模型偏見、領域偏見);對某些領域(醫療、法律),bert-base-chinese 的 embedding 不一定準確。對應排查方向:用領域內的 BERT 模型(醫療用 medical-bert、法律用 legal-bert),或在 BERTScore 之外加 1–2 個人工評估的樣本驗證。

錯誤五:忽略長度對指標的影響。BLEU 的 brevity penalty 雖然處理了「太短」的情況,但沒處理「太長」的退化;ROUGE 的 recall 在候選很長時會虛高。對應排查方向:在報告分數時附上「平均候選長度 vs. 平均參考長度」;如果差異超過 30%,評估分數的可信度要打折扣。

效能與實務提醒

BLEU 與 ROUGE 在 CPU 上算得飛快:5 筆資料的 sentence-BLEU + ROUGE 三項約 0.1 秒;擴展到 1000 筆約 5 秒。BERTScore 要載入 BERT 模型與計算 token 相似度,CPU 上 5 筆約 30 秒、T4 上約 5 秒;1000 筆 CPU 約 30 分鐘、T4 約 5 分鐘。LLM-as-judge 取決於評審模型大小:Qwen 2.5 7B 本機約 3–5 秒/筆(GPU)或 10–20 秒/筆(CPU);GPT-4o 約 1–2 秒/筆(網路延遲為主)。

實務上的評估流程建議:「快速篩選用 BLEU/ROUGE、深入評估用 BERTScore、最終確認用 LLM-judge + 人工抽樣」。在模型迭代階段(每天訓練幾次),跑 BLEU/ROUGE 即可快速對比;在模型定版前,跑 BERTScore 看語意層級的差異;在發布前,跑 LLM-judge 並抽 20–30 筆人工檢查。這三層的成本大致是 1 : 50 : 500(BLEU/ROUGE 最便宜、LLM-judge 最貴),但訊號強度也大致是 1 : 5 : 10。

另一個實務提醒:評估指標的選擇要看任務性質。機器翻譯用 BLEU 與 chrF、新聞摘要用 ROUGE-L 與 BERTScore、開放式 QA 用 LLM-judge 與人工評估、對話系統用人工評估 + LLM-judge。沒有一個指標適合所有任務;硬把 BLEU 用在對話系統上會得到誤導性的低分,硬把 BERTScore 用在短句生成會得到虛高的分數。Day 41 的專案章節會針對企業知識庫的問答任務設計專屬評估指標組合。

小結

今天把生成任務的三層評估走過一輪:BLEU(n-gram 精確率 + 簡短懲罰)、ROUGE(recall 導向,含 ROUGE-1/2/L)、BERTScore(BERT embedding 語意相似度)、LLM-as-judge(用 LLM 給結構化分數)。我們用 5 筆中文新聞摘要做完整示範,BLEU 平均約 11、ROUGE-L 約 0.48、BERTScore F1 約 0.67、LLM-judge overall 平均約 3 分;其中 BERTScore 與 LLM-judge 的相關性最高(0.78),代表這兩個指標對人類判斷的代理最好。明天 Day 20 會從「評估」轉到「風險」——幻覺是 LLM 應用最常見的失敗模式,我們會深入幻覺的成因、偵測方法與緩解策略。

結語

今天的核心訊息是「生成品質的評估是多層的、不存在單一完美指標」。BLEU 與 ROUGE 是 2000 年代的標準,便宜快速但只看 n-gram 重疊;BERTScore 是 2020 年的改良,用語意向量跳過同義詞限制;LLM-as-judge 是 2024–2025 年的新標準,最接近人類但成本最高。實務上要把這三層組合起來:BLEU/ROUGE 當快速篩選、BERTScore 當深入對比、LLM-judge 當最終確認。我們也展示了 LLM-as-judge 的提示工程與結構化輸出技巧,這個模式可以延伸到 Day 20 的幻覺偵測、Day 29 的 RAG 評估。讀完這篇你應該能回答:BLEU 與 ROUGE 的核心數學定義?BERTScore 為什麼比 BLEU 更接近人類判斷?LLM-as-judge 的提示設計要注意什麼?中文任務的 tokenizer 怎麼選?明天 Day 20 會從評估轉到風險——幻覺(hallucination)是 LLM 應用最常見的失敗模式,我們會分析成因、實作偵測工具、介紹緩解策略。

延伸資源

  • Papineni 等人,2002,BLEU: a Method for Automatic Evaluation of Machine Translation(ACL 2002):https://aclanthology.org/P02-1040/,BLEU 原始論文,n-gram 精確率與簡短懲罰的完整數學定義。
  • Lin,2004,ROUGE: A Package for Automatic Evaluation of Summaries:https://aclanthology.org/W04-1013/,ROUGE 家族(ROUGE-N、ROUGE-L、ROUGE-W)的原始定義。
  • Zhang 等人,2020,BERTScore: Evaluating Text Generation with BERT(ICLR 2020):https://arxiv.org/abs/1904.09675,用 BERT embedding 計算語意相似度的完整演算法。
  • sacrebleu 官方文件(2.4,2025):https://github.com/mjpost/sacrebleu,標準化的 BLEU 與 chrF 計算,支援多語言 tokenizer。
  • rouge-score 官方文件(0.1.2,2025):https://github.com/google-research/google-research/tree/master/rouge,Google 維護的 ROUGE 實作。
  • Zheng 等人,2023,Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena(NeurIPS 2023):https://arxiv.org/abs/2306.05685,LLM-as-judge 的偏差分析(位置偏見、長度偏見、自我增強偏見)與緩解方法。

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...