查看全课大纲(第 37 / 40 节)
- 1.从规则到学习:深度学习解决什么问题
- 2.表示学习与端到端训练
- 3.张量、计算图与自动微分
- 4.训练三要素:数据、模型、目标函数
- 5.从感知机到多层感知机
- 6.反向传播:手推一个两层网络
- 7.激活函数与初始化
- 8.优化器:SGD → Momentum → Adam
- 9.正则化:权重衰减、Dropout、BN/LN
- 10.卷积的直觉与参数共享
- 11.池化、感受野与下采样
- 12.经典网络演进:LeNet → AlexNet → VGG → ResNet
- 13.残差连接与归一化为什么有效
- 14.迁移学习与特征可视化
- 15.RNN 与 BPTT
- 16.LSTM/GRU:门控如何缓解梯度问题
- 17.Seq2Seq 与编码器-解码器
- 18.注意力前史:Bahdanau 加性注意力
- 19.Self-Attention:QKV 与缩放点积
- 20.多头注意力:并行的多种关系
- 21.位置编码:正弦与可学习
- 22.残差、LayerNorm 与前馈层
- 23.从零实现一个最小 Transformer block
- 24.训练稳定性、复杂度与常见误区
- 25.自监督与语言建模目标
- 26.BERT:掩码语言模型与双向编码
- 27.GPT:自回归生成与缩放定律
- 28.指令微调与对齐:SFT → RLHF/DPO
- 29.参数高效微调:LoRA 与适配器
- 30.自编码器与 VAE
- 31.GAN:对抗训练与模式崩塌
- 32.扩散模型:前向加噪与反向去噪
- 33.扩散模型的应用与采样加速
- 34.对比学习与 CLIP
- 35.ViT:把图像当序列
- 36.多模态架构:对齐、融合与生成
- 37.能力边界、幻觉与评测
- 38.PyTorch 2.x 训练循环与混合精度
- 39.实验管理、评测与复现
- 40.推理部署与成本:量化/蒸馏概览
能力边界、幻觉与评测
小象实战讲义 · 深度学习基础:从神经网络到 Transformer
学完本节,你将能回答:为什么看似强大的大语言模型会“一本正经地胡说八道”?怎么量化评估一个模型,而不是凭感觉?本节是第 8 章《多模态与前沿》的收尾,会讲清能力边界从哪来、幻觉分几类、评测基准与方法怎么选。先修:Transformer 解码器与自回归生成、交叉熵与最大似然、预训练与指令微调。后续:第 9 章《工程实践与收口》讲训练循环、评测复现与推理部署。
💡 核心导读
- 模型能力边界:模型的能力由其训练数据、架构和优化目标共同决定,存在固有的“知识截止日期”和“推理天花板”。
- 幻觉的定义与分类:幻觉指模型生成与输入无关或与事实不符的内容,可分为内在幻觉(与输入矛盾)和外在幻觉(无法验证)。
- 评测基准:模型能力需通过标准化的基准(如MMLU、GSM8K、HumanEval)进行量化评估,而非主观判断。
- 评测方法:包括基于答案匹配的自动评测(如准确率、ROUGE)和基于人类偏好的评测(如Elo评分、Chatbot Arena)。
- 缓解幻觉的策略:从数据清洗、训练目标设计到推理时干预,存在一系列技术手段,但无法根除。
🧭 前置知识
- Transformer解码器与自回归生成:理解模型如何基于上文逐词生成下文。
- 交叉熵损失与最大似然估计:理解模型训练的基本优化目标。
- softmax函数与概率分布:理解模型输出的是下一个词的概率分布。
- 预训练与指令微调:了解模型获得通用能力和遵循指令能力的基本流程。
模型的能力边界:它“知道”什么,又“不知道”什么?
一个模型并非全知全能,其能力存在明确的边界。这些边界主要由以下三个因素划定:
- 训练数据边界:模型的知识完全来源于其训练语料。如果语料中未包含某个事件(例如2025年后的新闻),模型就无法“知道”它。这导致了知识截止日期问题。此外,数据中的偏见、错误也会被模型吸收。
- 架构与规模边界:模型的参数量、层数、注意力头数等决定了其表示能力和上下文窗口大小。较小的模型可能无法处理复杂的多步推理。
- 训练目标边界:标准的自回归语言建模目标是预测下一个词(token)。这个目标鼓励模型生成在统计上“合理”的文本,但并不直接保证事实准确性或逻辑一致性。
我们可以通过一个简单的代码实验来感受“知识边界”。我们构造一个微型模型,它只在有限的数据上训练过。
import torch
import torch.nn as nn
import torch.nn.functional as F
torch.manual_seed(0)
# 模拟一个在极有限数据上训练过的"知识库"
# 假设模型只"知道"以下几个简单事实(输入:输出)
knowledge_pairs = [
("capital of france", "paris"),
("largest planet", "jupiter"),
("2 + 2", "4")
]
# 一个极其简化的"记忆"模型:计算输入与已知问题的余弦相似度,返回最相似问题对应的答案
class SimpleMemoryModel:
def __init__(self, pairs):
from collections import defaultdict
self.qa_dict = defaultdict(str)
self.questions = []
self.answers = []
for q, a in pairs:
self.qa_dict[q] = a
self.questions.append(q)
self.answers.append(a)
def embed(self, text):
# 简陋的字符级词袋嵌入,仅用于演示
vec = torch.zeros(26) # a-z
for ch in text.lower():
if 'a' <= ch <= 'z':
vec[ord(ch) - ord('a')] += 1
return vec / (vec.norm() + 1e-6)
def query(self, question):
q_vec = self.embed(question)
best_sim = -1
best_answer = "[我不知道]"
for known_q in self.questions:
k_vec = self.embed(known_q)
sim = torch.dot(q_vec, k_vec).item()
if sim > best_sim:
best_sim = sim
best_answer = self.qa_dict[known_q]
# 设置一个相似度阈值,低于则认为"不知道"
if best_sim < 0.3:
return "[我不知道]"
return best_answer
model = SimpleMemoryModel(knowledge_pairs)
test_queries = [
"capital of france", # 已知
"biggest planet", # 近似已知(同义词)
"capital of germany", # 未知
"2 plus 2" # 近似已知(不同表述)
]
print("测试简单记忆模型的知识边界:")
for q in test_queries:
print(f" 问题: '{q}' -> 答案: '{model.query(q)}'")测试简单记忆模型的知识边界:
问题: 'capital of france' -> 答案: 'paris'
问题: 'biggest planet' -> 答案: 'jupiter'
问题: 'capital of germany' -> 答案: 'paris'
问题: '2 plus 2' -> 答案: 'jupiter'印刷输出分析:biggest planet 答对了,但 capital of germany 答成 paris、2 plus 2 答成 jupiter。原因有二:①词袋只数 a–z,germany 与 france 的字母分布很像,越过 0.3 阈值就硬答;②2 plus 2 只含 p、l、u、s 四个字母,归一化后仍是单位向量,它与 largest planet 共享 p/l/s,余弦相似度约 0.4,越过阈值于是返回 jupiter。检索式记忆在分布外不会说“不知道”,只会给最像的那个答案——大模型同样受训练数据分布限制,超出分布就容易编。
幻觉:生成内容的“失真”
幻觉指模型生成的内容在语法上流畅、看似合理,但实质上与提供的输入源(内在幻觉)或公认的世界知识(外在幻觉)不符。根据 Survey of Hallucination in Natural Language Generation(Ji et al., 2022,arXiv:2202.03629)的分类,主要有两种:
- 内在幻觉:生成内容与输入源(如检索到的文档、用户问题)直接矛盾。例如,输入是“梅西效力于巴黎圣日耳曼队”,模型却回答“梅西是巴塞罗那的现役球员”。
- 外在幻觉:生成内容无法从输入源中验证,且与事实不符。例如,问“爱因斯坦何时获得了诺贝尔化学奖?”,模型可能编造一个具体的年份和细节。
幻觉产生的根源与模型的工作原理紧密相关:
- 训练目标错位:语言模型的目标是建模序列的联合概率 ,即生成“看起来像”训练数据的文本。这个目标不包含“忠于事实”的显式约束。
- 数据噪声与冲突:训练数据本身包含错误、过时信息或矛盾陈述,模型会学习到这些模式。
- 生成过程的贪婪性:自回归生成时,模型通常选择概率最高的词(贪婪解码)或进行采样。即使上下文指向一个低概率的事实,模型也可能被高频但无关的关联词带偏。
- 知识融合困难:在检索增强生成中,模型需要将外部检索到的知识与自身参数知识融合,融合失败会导致幻觉。
让我们模拟一个因“数据偏见”而产生外在幻觉的场景。假设训练数据中“诺贝尔奖”与“物理学”的共现频率远高于“化学”。
import torch
import torch.nn.functional as F
torch.manual_seed(0)
# 模拟一个基于词频的简单概率分布(logits)
# 词汇表:["physics", "chemistry", "prize", "einstein", "curie"]
vocab = ["physics", "chemistry", "prize", "einstein", "curie"]
# 假设模型看到"诺贝尔"后,预测下一个词的logits。
# 由于数据偏见,"physics"的分数远高于"chemistry"
logits_after_nobel = torch.tensor([5.0, 1.0, 3.0, 0.5, 0.5]) # 对应vocab顺序
# 计算softmax概率
probs = F.softmax(logits_after_nobel, dim=-1)
print("在上下文包含'诺贝尔'时,模型预测下一个词的概率分布:")
for word, prob in zip(vocab, probs.tolist()):
print(f" '{word}': {prob:.4f}")
# 模拟生成:从分布中采样(而非选最高概率)
sampled_idx = torch.multinomial(probs, num_samples=1).item()
print(f"\n采样结果的下一个词是: '{vocab[sampled_idx]}'")在上下文包含'诺贝尔'时,模型预测下一个词的概率分布:
'physics': 0.8504
'chemistry': 0.0156
'prize': 0.1151
'einstein': 0.0094
'curie': 0.0094
采样结果的下一个词是: 'physics'印刷输出分析:模型给“physics”的概率是 85.0%,“chemistry”只有 1.56%。这模拟了训练数据偏见导致的事实性错误倾向:一旦生成早期选错路径,后续很容易沿这个方向“编造”下去,形成连贯但错误的文本,即幻觉。
如何评测模型能力?
由于模型存在幻觉和能力边界,我们不能仅凭几个例子就评判其优劣,必须依赖系统性的评测基准和评测方法。
主流评测基准
评测基准通常是一个标准化的数据集,包含输入(问题/指令)和期望输出(答案/代码)。例如:
- MMLU(Massive Multitask Language Understanding):涵盖57个学科(从初级数学到专业法律)的多选题,测试模型的世界知识和推理能力。
- GSM8K(Grade School Math 8K):小学数学应用题,测试模型的多步推理能力。
- HumanEval:通过模型生成代码来解决编程问题,测试代码功能正确性。
- BIG-bench:包含数百个多样化、挑战性任务的超大规模基准。
评测时,模型在未见过的测试集上运行,其输出通过特定规则(如精确匹配、代码执行)与标准答案对比,计算出指标(如准确率)。
评测方法分类
- 自动评测:匹配类(准确率、ROUGE、BLEU,算与参考答案的重叠度)、模型类(BERTScore,用预训练模型算语义相似度)、执行类(直接跑生成的代码看输出对不对)。
- 人工评测:评分制(按事实性、连贯性、无害性打分)与对比评测(如 Chatbot Arena,Chiang et al., 2024,arXiv:2403.04132,让人类给两个匿名回复投票,再用 Elo 排名)。后者更贴近真实使用体验。
下面我们以GSM8K中的一个简化问题为例,演示如何用代码实现一个最简单的“基于答案匹配”的自动评测。
import torch
import re
torch.manual_seed(0)
# 模拟一个模型对GSM8K某个问题的生成过程(假设模型直接输出最终答案数字)
def mock_model_generate(question):
# 这是一个有缺陷的模型:它有时能算对,有时会犯低级计算错误(幻觉)
# 我们用一个固定的随机行为来模拟
if "20 books" in question and "5 shelves" in question:
# 正确逻辑:20 / 5 = 4。但模型有50%概率犯错
if torch.rand(1).item() > 0.5:
return "4"
else:
# 产生一个幻觉答案
return "6" # 可能是误加了或记错了
else:
return "[未定义行为]"
# 定义一个GSM8K风格的问题和标准答案
test_question = "John has 20 books, equally on 5 shelves."
ground_truth_answer = "4" # 标准答案
# 模拟多次生成,计算准确率
num_trials = 10
correct_count = 0
generated_answers = []
for i in range(num_trials):
ans = mock_model_generate(test_question)
generated_answers.append(ans)
# 简单答案匹配:去除空格后直接比较字符串
if ans.strip() == ground_truth_answer.strip():
correct_count += 1
accuracy = correct_count / num_trials
print(f"评测问题: {test_question}")
print(f"标准答案: '{ground_truth_answer}'")
print(f"模型{num_trials}次生成的结果: {generated_answers}")
print(f"基于精确匹配的准确率: {accuracy:.2f} ({correct_count}/{num_trials})")
print("说明:真实答案格式多样(如 '4 books'),需要更鲁棒的匹配。")评测问题: John has 20 books, equally on 5 shelves.
标准答案: '4'
模型10次生成的结果: ['6', '4', '6', '6', '6', '4', '6', '4', '6', '4']
基于精确匹配的准确率: 0.40 (4/10)
说明:真实答案格式多样(如 '4 books'),需要更鲁棒的匹配。印刷输出分析:10 次里 4 次答对,准确率 0.40。真实评测中 GSM8K 有上千道题,平均准确率才是可靠指标;这种量化评估让我们能客观比较不同模型在同一任务上的强弱。
缓解幻觉的常见策略
完全消除幻觉极其困难,但有几类缓解手段:
- 数据层面:清洗去重训练语料,标注事实性,引入高质量知识库。
- 训练目标:在预训练或微调阶段加入事实性约束或对比学习目标,让模型区分事实与非事实。
- 推理时干预:检索增强生成(实时检索外部知识再生成)、自我验证(生成后再对关键事实自问自答)、约束解码(用语法规则限制生成空间)。
- 后处理:高风险领域(医疗、法律)的输出必须人工核查。
需要明确:没有任何单一技术能根除幻觉。理解其根源并设好预期(“模型是文本生成器,不是事实数据库”)才是正确姿势。
📝 动手练一练
题目:在上面的 GSM8K 评测模拟里,模型有 50% 的概率答错(上面 10 次采样就错了 6 次,准确率 40%)。请改写 mock_model_generate,模拟一种检索增强生成的简单策略:输出候选答案之前,先“检索”一张乘法口诀表(用 Python 字典模拟),验证 候选答案 × 5 == 20 是否成立,只有通过验证才输出。观察准确率是否提升。
👉 点击查看参考答案
思路:我们模拟RAG的关键思想——生成时访问外部知识。在函数内部,我们不再随机返回答案,而是先根据问题确定运算类型(这里是除法),然后利用一个“外部知识”(乘法口诀字典)来验证候选答案。只有通过验证的答案才会被输出。
import torch
import re
torch.manual_seed(0)
# 模拟一个外部知识源:乘法口诀表(字典)
multiplication_table = {}
for i in range(1, 13):
for j in range(1, 13):
multiplication_table[(i, j)] = i * j
def mock_model_generate_rag(question):
# 简单规则提取数字
nums = [int(s) for s in re.findall(r'\b\d+\b', question)]
if len(nums) >= 2 and "equally" in question.lower():
total, divisor = nums[0], nums[1]
candidate_answer = total // divisor # 正确计算
# RAG验证:利用外部知识验证 total == candidate_answer * divisor 是否成立
if multiplication_table.get((candidate_answer, divisor)) == total:
return str(candidate_answer)
else:
# 如果验证失败(本例中不会),可以回退或标记未知
return "[验证失败]"
return "[未定义行为]"
test_question = "John has 20 books, equally on 5 shelves."
ground_truth_answer = "4"
num_trials = 10
correct_count = 0
generated_answers = []
for i in range(num_trials):
ans = mock_model_generate_rag(test_question)
generated_answers.append(ans)
if ans.strip() == ground_truth_answer.strip():
correct_count += 1
accuracy = correct_count / num_trials
print("RAG 结果:", generated_answers)
print(f"基于精确匹配的准确率: {accuracy:.2f} ({correct_count}/{num_trials})")
print("说明:这个极度简化的 RAG 模拟消除了计算错误导致的幻觉,准确率提升到 100%。")RAG 结果: ['4', '4', '4', '4', '4', '4', '4', '4', '4', '4']
基于精确匹配的准确率: 1.00 (10/10)
说明:这个极度简化的 RAG 模拟消除了计算错误导致的幻觉,准确率提升到 100%。常见错误
| 错误理解或写法 | 现象或报错 | 原因 | 正确做法 |
|---|---|---|---|
| 认为模型幻觉是“bug”可以彻底修复 | 投入大量精力试图根除,收效甚微。 | 幻觉是自回归模型架构与训练目标的固有特性,不是程序错误。 | 把重点放在缓解与检测上,关键应用加人工审核。 |
| 仅用几个主观例子评价模型好坏 | 同一模型有人说“聪明”、有人说“愚蠢”。 | 模型在不同任务上差异巨大,个别例子没有统计代表性。 | 依赖公开基准(MMLU、GSM8K)的量化结果。 |
| 在自动评测中直接比较字符串 | 答案“4 books”与标准答案“4”不匹配,被误判为错。 | 生成文本的单位、标点、措辞都可能不同。 | 用正则提取数值,或改用 BERTScore 这类语义指标。 |
| 忽略评测基准的局限性 | 基准分很高的模型,实际产品里表现不佳。 | 基准可能过时、有偏,或与真实用户分布不符。 | 基准分只作参考,必须结合领域测试集与人工评估。 |
本章小结
- 模型的能力严格受限于其训练数据、架构和优化目标,存在知识截止日期和推理天花板。
- 幻觉是模型生成流畅但不符合事实或输入内容的现象,分为内在和外在两类,根植于概率生成模型的本性。
- 量化评估模型必须依赖标准化的评测基准(如MMLU、GSM8K)和科学的评测方法(自动匹配与人工偏好结合)。
- 检索增强生成等推理时干预技术能有效缓解幻觉,但无法根除,理解并管理幻觉风险是应用落地的关键。
- 模型评测是一个动态、多维的过程,需结合自动指标、人工评估和实际场景测试。
📋 行动清单
- 访问LMSYS的Chatbot Arena (https://chat.lmsys.org) ,匿名比较两个不同模型对同一复杂问题的回答,体会幻觉和回答质量的差异。
- 选择一个你感兴趣的评测基准(如GSM8K),在Hugging Face上查找相关排行榜,了解当前开源模型在该任务上的最佳准确率。
- 修改“动手练一练”中的代码,尝试模拟另一种幻觉(如“约翰有20本书,给了妹妹3本,还剩多少本?”模型错误回答“23本”),并设计一个简单的验证逻辑来纠正它。
延伸阅读
- Survey of Hallucination in Natural Language Generation (Ji et al., 2022, arXiv:2202.03629)
- Measuring Massive Multitask Language Understanding (Hendrycks et al., 2021, arXiv:2009.03300) – MMLU基准论文
- Training language models to follow instructions with human feedback (Ouyang et al., 2022, arXiv:2203.02155) – InstructGPT论文,涉及基于人类偏好的模型评测与优化
- Chatbot Arena: An Open Platform for Evaluating LLMs by Human Preference (Chiang et al., 2024, arXiv:2403.04132) – 大规模众包对比评测的实践
—— 小象教研组