一、为什么“大模型”评估比小模型更棘手

  1. 生成空间爆炸:分类输出 3 个标签,生成输出 ∞ 文本,穷举参考答案不可能。
  2. 语义等价形式多:“北京是中国的首都”≈“中国首都是北京”,字符串匹配直接 0 分。
  3. 人工成本高:一篇 500 字摘要请 3 人双盲打分,成本 ≈ ¥15/条,1000 条就要 1.5 万。
  4. 任务边界模糊:同样一段用户 query,既能当“分类”也能当“生成”——先定任务,再选指标是第一步。

二、任务类型速定位(1 分钟自检)

场景举例输出形式任务类型本文章节
垃圾评论识别离散标签 {spam, normal}分类
情感极性离散标签 {负, 中, 正}分类
摘要/对话/翻译自由文本(≥0 字)生成
抽取式问答原文片段生成(可归为抽取)
多标签分类多标签同时成立分类(特殊)三.5

三、分类任务:指标、代码、可视化一条龙

3.1 必备指标与解释

指标公式何时看
Accuracy(TP+TN)/N均衡数据
Macro-F1ΣF1_i / k不均衡数据
Weighted-F1按支持度加权不均衡+关心整体
ROC-AUC∫TPR dFPR阈值未定时
PR-AUC∫Precision dRecall正类极少
Cohen’s κ(Po-Pe)/(1-Pe)多人标注一致性

3.2 代码模板(单文件可跑)

# evaluate_cls.py
import evaluate, pandas as pd, seaborn as sns, matplotlib.pyplot as plt
from sklearn.metrics import classification_report, confusion_matrix, cohen_kappa_score
import numpy as np

labels = ["负", "中", "正"]
y_true = [0,1,2,0,1,2,0,0,1,1]
y_pred = [0,2,2,0,1,1,0,1,1,0]

# 1. 综合报告
print(classification_report(y_true, y_pred, target_names=labels, digits=3))

# 2. 混淆矩阵
plt.figure(figsize=(3,3))
sns.heatmap(confusion_matrix(y_true, y_pred),
            annot=True, fmt="d", cmap="Blues",
            xticklabels=labels, yticklabels=labels)
plt.ylabel("True"); plt.xlabel("Pred")
plt.title("Confusion Matrix")
plt.savefig("cm.png", dpi=200)

# 3. Cohen’s κ(多人标注场景)
κ = cohen_kappa_score(y_true, y_pred)
print("Cohen κ =", round(κ,3))

3.3 不均衡数据实战

数据:情感 3 类,比例 负:中:正 = 78% : 15% : 7%
结果:Accuracy=78% 看似高,Macro-F1=0.42 暴露模型只会判“负”。
修复:

  • 采样:SMOTE 过正类 + 随机欠负类 → Macro-F1 提升至 0.71
  • 代价敏感:class_weight=“balanced” → 0.69
  • 阈值移动:PR-AUC 峰值处调阈值 → 0.73

结论:不均衡任务不看 Accuracy,只看 Macro-F1 / PR-AUC。

3.4 大模型“零样本”分类特别技巧

from transformers import pipeline
clf = pipeline("text-classification", model="bert-base-chinese")
# 标签在 ChineseBERT 之外,用“标签描述”映射
label2desc = {0:"负面情感",1:"中性",2:"正面情感"}
# 无标注也能看置信度分布
pred = clf("这破系统又崩了")[0]
print(pred)   # {'label': 'LABEL_0', 'score': 0.92}

注意:零样本无 gold label,只能

  1. 统计置信度分布 → 看漂移
  2. 人工抽样 100 条算 Precision@K

四、生成任务:脚本指标 → 语义指标 → LLM 裁判

4.1 脚本指标(快速离线)

指标适用一行代码
BLEU-1/2/3/4机器翻译、摘要evaluate.load("bleu").compute(predictions=[pred], references=[[ref]])
ROUGE-1/2/L摘要evaluate.load("rouge").compute(predictions=[pred], references=[ref])
chrF多语言evaluate.load("chrf").compute(predictions=[pred], references=[ref])

4.2 语义指标(字符串不同但语义同)

指标原理代码
BERTScore余弦相似度(上下文 embedding)evaluate.load("bertscore").compute(predictions=[pred], references=[ref], lang="zh")["f1"][0]
BLEURT谷歌轻量回归模型evaluate.load("bleurt").compute(predictions=[pred], references=[ref])["scores"][0]

4.3 LLM 裁判(无参考也 OK)

4.3.1 pairwise 胜负
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

llm = ChatOpenAI(model="gpt-4", temperature=0)
template = """你是一名公正评委,比较哪条回答更好。
问题:{q}
回答A:{a1}
回答B:{a2}
请只输出:A 胜 | B 胜 | 平
"""
prompt = ChatPromptTemplate.from_template(template)
chain = prompt | llm
winner = chain.invoke({"q": q, "a1": a1, "a2": a2}).content
4.3.2 多维度打分(1-5)
rubric = """对回答按 1-5 打分并 JSON 返回:
{"相关性":int, "准确性":int, "流畅度":int}
问题:{q}  回答:{a}"""
score_json = llm.invoke(rubric.format(q=q, a=a)).content
4.3.3 幻觉检测(RAG 必备)
from deepeval.metrics import HallucinationMetric
metric = HallucinationMetric(model="gpt-4")
metric.measure(
    output="柏林是法国首都。",
    context=["柏林是德国首都。"]
)
print(metric.score)  # 0.0 → 严重幻觉

五、端到端实战:摘要模型对比实验

模型
A) 原生 ChatGPT-3.5
B) 自己 LoRA 微调 7B(Chinese-Alpaca-7b + 6k 摘要数据)

数据:50 篇中文财经新闻(平均 800 字)
指标:ROUGE-L、BERTScore、LLM 裁判(相关性+准确性+流畅度)
成本:脚本指标 0 元,LLM 裁判 ¥0.08/条 × 50 = ¥4

5.1 批量生成

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch, json

model_path = "./chinese-alpaca-7b-lora"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16, device_map="auto")

def generate(text):
    prompt = f"文章:{text}\n摘要:"
    inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
    out = model.generate(**inputs, max_new_tokens=120, do_sample=False)
    return tokenizer.decode(out[0][inputs.input_ids.shape[-1]:], skip_special_tokens=True)

with open("news.json") as f:
    data = json.load(f)

for d in data:
    d["summary_7b"] = generate(d["article"])
    d["summary_gpt"] = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": f"用 80 字概括下文:{d['article']}"}]
    ).choices[0].message.content

5.2 脚本指标

import evaluate
rouge = evaluate.load("rouge")
bertscore = evaluate.load("bertscore")

scores = {"7b": {"rougeL": [], "bertscore": []}, "gpt": {"rougeL": [], "bertscore": []}}

for d in data:
    ref = d["summary_gt"]          # 人工参考
    scores["7b"]["rougeL"].append(rouge.compute(predictions=[d["summary_7b"]], references=[ref])["rougeL"])
    scores["gpt"]["rougeL"].append(rouge.compute(predictions=[d["summary_gpt"]], references=[ref])["rougeL"])

    bert_7b = bertscore.compute(predictions=[d["summary_7b"]], references=[ref], lang="zh")["f1"][0]
    scores["7b"]["bertscore"].append(bert_7b)
    bert_gpt = bertscore.compute(predictions=[d["summary_gpt"]], references=[ref], lang="zh")["f1"][0]
    scores["gpt"]["bertscore"].append(bert_gpt)

print("平均 ROUGE-L | 7b:", np.mean(scores["7b"]["rougeL"]), "gpt:", np.mean(scores["gpt"]["rougeL"]))
print("平均 BERTScore | 7b:", np.mean(scores["7b"]["bertscore"]), "gpt:", np.mean(scores["gpt"]["bertscore"]))

结果(示例):

平均 ROUGE-L | 7b: 0.412  gpt: 0.489
平均 BERTScore | 7b: 0.834  gpt: 0.865

5.3 LLM 裁判

from langchain.schema import SystemMessage, HumanMessage
judge = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[
        {"role": "system", "content": "你是摘要评委,按 1-5 打分并 JSON 返回:{\"相关性\":int, \"准确性\":int, \"流畅度\":int}"},
        {"role": "user", "content": f"问题:{d['article'][:200]}...\n回答A:{d['summary_7b']}\n回答B:{d['summary_gpt']}"}
    ]
)

统计 50 条平均分:

维度7B LoRAGPT-3.5差值
相关性4.14.5+0.4
准确性4.04.6+0.6
流畅度3.94.7+0.8

结论

  • 脚本指标:GPT 全面领先 ∼6-8%。
  • LLM 裁判:流畅度差距最大,7B 模型存在“重复句、指代混乱”问题 → 后续加长度惩罚 + 多样性采样即可修复。

六、评估框架全景图(收藏级)

框架最强场景指标数是否支持 LLM 裁判一行安装
HF Evaluate经典脚本指标300+pip install evaluate
LangSmith在线可观测+人工反馈环境变量开关
DeepEval生成任务专用20+pip install deepeval
RAGASRAG 幻觉检测8pip install ragas
OpenCompass大模型综合基准50+pip install opencompass

七、生产级 checklist:从离线到在线

  1. 离线
    • 分类:Macro-F1 + PR-AUC + Cohen κ ≥ 0.75
    • 生成:ROUGE-L + BERTScore + LLM 裁判 ≥ 4.0/5
  2. 灰度
    • A/B 测试:用户留存、投诉率、平均轮数
  3. 在线
    • 实时看板:Accuracy@5min、Calibration-ECE、人工举报率
    • 自动回滚:指标下跌 > 2σ 或举报率 > 1.5% 立即切流

八、总结

分类任务先看“数据均衡”再选指标:

  • 均衡 → Accuracy
  • 不均衡 → Macro-F1 + PR-AUC + Cohen κ

生成任务三层金字塔:

  1. 脚本指标(BLEU/ROUGE)快速迭代
  2. 语义指标(BERTScore/BLEURT)减少漏杀
  3. LLM 裁判(GPT-4 打分/幻觉检测)贴近人类

最后一条铁律
“没有评估的模型上线,等同于蒙眼在高速倒车。”
AI大模型学习代码仓库

更多推荐