概述
本章系统性地介绍了语言模型从统计方法到深度学习的演进,重点解析了Transformer架构的各个组件,并探讨了文本分词、模型部署、缩放法则及局限性等实践议题。
作为学习者,本章最大的收获是建立了从"词序列概率"到"自注意力并行计算"的连贯知识链条,理解了为什么Transformer能够成为当今LLM的基石。
【心得】学习者视角:从N-gram到Transformer的认知跃迁
通过本章的逐步推导,我清晰地看到了三条演进主线:
1. 从离散到连续
N-gram模型将词视为孤立符号,导致数据稀疏和泛化能力差;神经网络语言模型通过词嵌入将词映射为连续向量,使语义相似的词在向量空间中靠近,解决了泛化问题。
2. 从固定窗口到全局依赖
前馈神经网络语言模型仍有固定窗口限制;RNN/LSTM通过循环结构理论上可以捕捉任意长距离依赖,但梯度消失/爆炸问题使其难以实际学习长程关系;Transformer的自注意力机制一次性计算序列中所有词对的关系,既突破了固定窗口,又避免了梯度问题。
3. 从串行到并行
RNN必须按时间步顺序计算,无法充分利用GPU并行能力;Transformer的自注意力可以同时计算所有位置的关注权重,实现了真正的并行化,这是其训练效率远超RNN的关键。
个人感悟:技术演进往往不是"凭空创造",而是针对前人局限的"精准改进"。理解每种模型的设计动机,比记住其公式更重要。
【归纳】知识体系结构化整理
1. 语言模型演进脉络
| 阶段 | 代表模型 | 核心思想 | 优势 | 局限 |
|---|---|---|---|---|
| 统计方法 | N-gram | 马尔可夫假设:词概率仅依赖前n-1个词 | 简单、可解释 | 数据稀疏、泛化差 |
| 早期神经网络 | 前馈NNLM | 词嵌入 + 前馈网络 | 语义泛化 | 固定窗口 |
| 循环结构 | RNN/LSTM | 隐藏状态传递历史信息 | 理论上可处理任意长序列 | 梯度消失/爆炸、串行计算 |
| 注意力革命 | Transformer | 自注意力 + 并行计算 | 全局依赖、高效并行 | 内存随序列长度平方增长 |
2. Transformer架构核心组件
- 自注意力(Self-Attention) :计算序列中每个词对所有词的关注权重,公式:
(\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^{T}}{\sqrt{d_{k}}}\right)V) - 多头注意力(Multi-Head Attention):并行执行多次自注意力,捕捉不同维度的依赖关系。
- 位置编码(Positional Encoding):为输入添加位置信息,弥补自注意力对顺序不敏感的缺陷。
- 前馈网络(Feed-Forward Network):逐位置进行非线性变换,提取高阶特征。
- 残差连接与层归一化:缓解梯度消失,加速训练收敛。
3. 关键技术补充
- 文本分词:BPE(Byte Pair Encoding)算法,平衡词汇表大小与词表外(OOV)问题。
- 模型部署:开源模型(如Qwen3-0.6B)的本地部署流程及参数调优。
- 缩放法则:模型性能与计算资源、数据规模、参数数量的定量关系。
- 模型幻觉:LLM生成与输入矛盾或事实错误内容的现象及缓解方案(RAG、CoT等)。
【代码】代码运行记录
本章包含多个代码示例,以下为实际运行结果。
1. Bigram概率计算
代码位置 :src/hello-agents/chapter3/bigram.py
运行结果:
第一步: P(datawhale) = 2/6 = 0.333
第二步: P(agent|datawhale) = 2/2 = 1.000
第三步: P(learns|agent) = 1/2 = 0.500
最后: P('datawhale agent learns') ≈ 0.333 * 1.000 * 0.500 = 0.167
2. 词向量相似度计算
代码位置 :src/hello-agents/chapter3/word_similarity.py
运行结果:
king - man + woman 的结果向量: [0.9 0.2]
该结果与 'queen' 的相似度: 1.0000
3. Transformer骨架代码(依赖检查)
本章提供的Transformer实现依赖于PyTorch库。当前沙箱环境中PyTorch未安装,因此无法直接运行。以下为代码结构示意:
文件 :src/hello-agents/chapter3/transformer_skeleton.py
python
import torch
import torch.nn as nn
import math
# 位置编码模块(占位符)
class PositionalEncoding(nn.Module):
def forward(self, x):
pass
# 多头注意力模块(占位符)
class MultiHeadAttention(nn.Module):
def forward(self, query, key, value, mask):
pass
# 前馈网络模块(占位符)
class PositionWiseFeedForward(nn.Module):
def forward(self, x):
pass
# 编码器层
class EncoderLayer(nn.Module):
def __init__(self, d_model, num_heads, d_ff, dropout):
super().__init__()
self.self_attn = MultiHeadAttention()
self.feed_forward = PositionWiseFeedForward()
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
self.dropout = nn.Dropout(dropout)
def forward(self, x, mask):
attn_output = self.self_attn(x, x, x, mask)
x = self.norm1(x + self.dropout(attn_output))
ff_output = self.feed_forward(x)
x = self.norm2(x + self.dropout(ff_output))
return x
说明 :在实际环境中,需要先安装PyTorch(pip install torch)方可运行上述代码。
【踩坑】踩坑填坑记录
N-gram概率计算中的零概率问题
现象 :若词序列未在训练语料中出现,N-gram模型会给出零概率,不符合语言实际
模拟 :在迷你语料库中查询未出现的bigram(如learns datawhale)
python
count_learns_datawhale = bigram_counts.get(('learns', 'datawhale'), 0)
print(f"P(datawhale|learns) = {count_learns_datawhale}/Count(learns) = 0")
解决:采用平滑技术(如Add-k smoothing)或转向神经网络语言模型
注意力分数缩放忽略
现象 :若忽略除以(\sqrt{d_k}),softmax输入的方差随维度增大而增大,导致梯度不稳定
模拟 :比较缩放前后的注意力分数分布
解决:始终遵循缩放点积注意力公式
【习题】习题完整解答
习题1:语言模型演进
1.1 计算句子agent works在Bigram模型下的概率
代码实现:
python
import collections
corpus = "datawhale agent learns datawhale agent works"
tokens = corpus.split()
# 计算Bigram概率
bigrams = zip(tokens, tokens[1:])
bigram_counts = collections.Counter(bigrams)
# P(agent)
p_agent = tokens.count('agent') / len(tokens)
# P(works|agent)
count_agent_works = bigram_counts.get(('agent', 'works'), 0)
count_agent = tokens.count('agent')
p_works_given_agent = count_agent_works / count_agent if count_agent > 0 else 0
# 句子概率
p_sentence = p_agent * p_works_given_agent
print(f"P(agent) = {tokens.count('agent')}/{len(tokens)} = {p_agent:.3f}")
print(f"P(works|agent) = {count_agent_works}/{count_agent} = {p_works_given_agent:.3f}")
print(f"P('agent works') ≈ {p_agent:.3f} * {p_works_given_agent:.3f} = {p_sentence:.3f}")
运行结果:
P(agent) = 2/6 = 0.333
P(works|agent) = 1/2 = 0.500
P('agent works') ≈ 0.333 * 0.500 = 0.167
1.2 马尔可夫假设的含义与N-gram局限
- 马尔可夫假设:一个词的出现概率只与其前面有限的n-1个词有关,而非整个历史。这大大简化了概率计算。
- N-gram根本局限 :
- 数据稀疏性:长词序列在训练数据中可能从未出现,导致概率估计为零。
- 泛化能力差 :无法理解语义相似性(如
agent与robot)。 - 上下文窗口固定:只能考虑有限的历史信息。
1.3 神经网络语言模型与Transformer的改进
- 神经网络语言模型(RNN/LSTM) :
- 改进:通过词嵌入实现语义泛化;循环结构理论上可处理任意长序列。
- 优势:捕捉长距离依赖;参数共享减少计算量。
- 局限:梯度消失/爆炸;串行计算效率低。
- Transformer :
- 改进:自注意力实现全局依赖;并行计算大幅提升训练速度。
- 优势:高效处理长序列;可扩展性强(缩放法则)。
- 局限:内存消耗随序列长度平方增长;位置编码对绝对位置敏感。
习题2:Transformer架构
2.1 自注意力核心思想
自注意力允许序列中的每个词同时关注所有其他词,根据相关性动态分配权重。其核心是通过查询(Q)、键(K)、值(V)三个向量,计算词与词之间的关联强度,并加权聚合信息。
2.2 并行处理与位置编码作用
- 并行处理:Transformer的自注意力可同时计算所有位置的关注权重,而RNN必须按时间步顺序计算,因此Transformer能充分利用GPU并行能力。
- 位置编码作用:自注意力本身不包含顺序信息,位置编码为输入添加绝对/相对位置信息,使模型能区分序列中词的位置关系。
2.3 Decoder-Only与Encoder-Decoder架构区别
- 完整Encoder-Decoder:包含编码器(理解输入)和解码器(生成输出),适用于序列到序列任务(如翻译)。
- Decoder-Only:仅保留解码器,通过自回归方式生成文本,代表模型有GPT系列。
- 主流原因 :
- 训练效率:Decoder-Only结构更简单,预训练成本更低。
- 生成能力:自回归生成更符合语言的自然流。
- 零样本泛化:Prompt工程可激发Decoder-Only模型的多种能力。
习题3:文本分词
为什么不能直接以"字符"或"单词"为输入单元?
- 字符:序列过长,模型难以捕捉语义单元;计算开销大。
- 单词:词汇表过大(尤其多语言);无法处理未见词(OOV)。
BPE算法解决的问题 :
BPE通过迭代合并频繁共现的字节对,构建一个大小可控的子词词汇表。它平衡了字符与单词的优缺点:
- 可表示任意单词(通过子词组合)
- 词汇表规模可控
- 能捕捉词根、词缀等形态学信息
习题4:本地部署实践
由于环境限制,本题以分析为主:
4.1 部署流程关键步骤
- 环境准备:安装Python、PyTorch、Transformers库。
- 模型下载 :使用
from_pretrained加载Qwen3-0.6B。 - 参数调整:温度(temperature)、top_p、重复惩罚(repetition_penalty)对输出多样性、一致性的影响。
4.2 提示策略对比
- Zero-shot:直接描述任务,依赖模型先验知识。
- Few-shot:提供示例,引导模型模仿格式。
- Chain-of-Thought(CoT):要求模型分步推理,提升复杂问题准确率。
4.3 闭源 vs 开源模型比较
| 维度 | 闭源模型(GPT-4) | 开源模型(Qwen3) |
|---|---|---|
| 性能 | 顶尖,多任务强 | 中等,特定任务优 |
| 成本 | API调用计费 | 一次性硬件投入 |
| 可控性 | 黑盒,定制难 | 白盒,可微调 |
| 隐私 | 数据需上传 | 本地部署,数据安全 |
4.4 企业客服智能体模型选择
- 选择类型:中等规模开源模型(如Qwen3-7B)
- 考虑因素 :
- 数据隐私:企业对话敏感,需本地部署。
- 定制需求:客服场景特定话术、知识库需微调。
- 成本可控:避免API按量计费的不确定性。
- 响应延迟:本地部署可优化响应速度。
习题5:模型幻觉缓解
选择检索增强生成(RAG):
- 工作原理 :
- 将外部知识库(如文档、数据库)向量化存储。
- 用户查询时,检索最相关的知识片段。
- 将检索结果与原始查询拼接,输入LLM生成回答。
- 适用场景:知识密集型任务(如问答、文档总结)、需要事实准确性的场景。
前沿方法调研:
- Self-Consistency:多次采样生成多个推理路径,投票选择最一致的答案。
- Step-back Prompting:遇到复杂问题时,先退一步问抽象原理,再具体解答。
- Constitutional AI:通过多轮自我批判和修订,减少有害输出。
习题6:论文辅助阅读智能体设计
6.1 基座模型选择
- 候选模型:Qwen2-72B(强推理能力)、Llama-3-70B(生态完善)
- 考虑因素 :
- 上下文长度:需支持长文本(≥128k tokens)。
- 多语言能力:国际学术论文涉及多种语言。
- 推理精度:对公式、逻辑的理解要求高。
- 微调友好性:需针对学术领域做继续预训练。
6.2 长文本处理策略
- 分层处理 :
- 摘要层:用较小模型提取章节摘要。
- 检索层:根据用户问题检索相关段落。
- 精读层:将相关段落输入大模型深度分析。
- 滑动窗口:对超长论文,采用重叠窗口分段处理,保持上下文连贯。
6.3 准确性保障设计
- 多源验证:交叉引用论文内不同部分、参考文献、外部数据库。
- 置信度标注:对生成信息标注可信度分数,提供原文引用位置。
- 人工复核接口:关键结论提供人工复核标记,形成人机协同闭环。
总结
通过本章学习,我不仅理解了LLM的工作原理,更掌握了分析模型演进逻辑的方法论。代码实践部分验证了基础概念,而习题解答则深化了对技术细节和应用场景的理解。