目录
[2.1 Transformer结构](#2.1 Transformer结构)
[2.1.1 嵌入表示层](#2.1.1 嵌入表示层)
[2.1.2 注意力层](#2.1.2 注意力层)
[2.1.3 前馈层](#2.1.3 前馈层)
[2.1.4 残差连接与层归一化](#2.1.4 残差连接与层归一化)
[2.1.5 编码器和解码器结构](#2.1.5 编码器和解码器结构)
[2.2 生成式预训练语言模型GPT](#2.2 生成式预训练语言模型GPT)
[2.2.1 无监督预训练](#2.2.1 无监督预训练)
[2.2.2 有监督下游任务微调](#2.2.2 有监督下游任务微调)
[2.2.3 基于HuggingFace的预训练语言模型实践](#2.2.3 基于HuggingFace的预训练语言模型实践)
[2.3 大语言模型的结构](#2.3 大语言模型的结构)
[2.3.1 LLaMA的模型结构](#2.3.1 LLaMA的模型结构)
[2.3.2 注意力机制优化](#2.3.2 注意力机制优化)
[2.4 实践思考](#2.4 实践思考)
大语言模型(Large Language Model, LLM)的崛起,并非一蹴而就的技术奇点,而是深度学习在自然语言处理领域长期积淀后的集中爆发。其技术根基源于2017年问世的Transformer架构,并经由生成式预训练(GPT)范式的催化,最终在 scaled-up 的模型参数、数据量和计算力下,涌现出令人瞩目的推理、创作与对话能力。本章将系统性地剖析这一技术体系的基石:从Transformer的核心机制,到GPT系列的开创性预训练范式,再到以LLaMA为代表的现代大模型结构优化,最终落脚于工程实践中的关键思考。
2.1 Transformer结构
在Transformer诞生之前,循环神经网络(RNN)及其变体LSTM、GRU长期主导着序列建模任务。然而,其固有的顺序计算特性导致了训练并行度差和长程依赖建模困难两大瓶颈。Transformer的提出,通过"纯注意力机制"彻底摒弃了递归,实现了完全的并行化训练,并因其卓越的长程信息捕获能力,迅速成为大语言模型不可或缺的骨架。
一个标准的Transformer结构由编码器(Encoder)和解码器(Decoder)堆叠而成。鉴于当前主流的大语言模型(如GPT、LLaMA系列)均采用解码器架构,我们的讲解将侧重于解码器,并对编码器-解码器结构进行对比分析。
2.1.1 嵌入表示层
模型的输入首先需要被转化为稠密向量表示。在Transformer中,这通过以下三个嵌入层的加和来实现:
-
词元嵌入 :将输入序列中的每个词元(Token)映射为一个高维向量。例如,词汇表大小为
vocab_size,嵌入维度为d_model,则该嵌入层是一个可学习的矩阵W_t ∈ R^(vocab_size × d_model)。 -
位置嵌入 :由于自注意力机制本身不具备位置信息感知能力,必须显式地注入序列的顺序信息。原始Transformer论文使用正弦余弦函数来生成绝对位置编码:

-
其中,
pos是位置索引,i是维度索引。这种函数式编码的优势在于能够外推到比训练序列更长的位置。然而,在现代大模型中,可学习的位置嵌入 更为常见。模型直接将位置索引
pos映射为一个可学习的向量,其效果通常不逊于甚至优于正弦余弦编码,且更易于实现。 -
分段嵌入(可选):在某些任务(如句子对分类)中,会引入一个额外的分段嵌入(Segment Embedding)来区分不同的句子片段(如句子A和句子B)。
最终,输入序列的初始表示为:Input = TokenEmbedding + PositionEmbedding。
关键理解:嵌入层的本质是将离散的、符号化的语言信息(词元、位置)转化为连续、可微的数值表示,为后续的深度神经网络处理奠定基础。
2.1.2 注意力层
注意力机制是Transformer的灵魂,其核心思想是:在处理序列中的某个元素时,可以根据一个"查询",动态地为序列中所有元素分配不同的权重(即"注意力"),从而聚合全局信息。
缩放点积注意力
最核心的注意力形式是缩放点积注意力,其公式为:

-
Q, K, V :分别代表查询、键和值矩阵。它们是由输入序列
X通过三个不同的线性变换(W^Q,W^K,W^V)投影得到。d_k是键向量的维度。 -
QK^T:计算查询和所有键之间的点积相似度,得到一个注意力分数矩阵。
-
缩放:除以 dkdk 是为了防止点积结果过大,导致softmax函数梯度消失。
-
softmax:将注意力分数归一化为概率分布,表示每个位置获得的关注程度。
-
加权和 :将softmax输出的权重与值矩阵
V相乘,得到最终的注意力输出。
多头注意力
单一注意力头可能只关注到一种模式的信息。为了增强模型的表达能力,Transformer引入了多头注意力 。它将 Q, K, V 在 d_model 维度上切分成 h 个头,每个头在各自的子空间(维度为 d_k = d_v = d_model / h)中独立执行注意力计算,最后将各头的输出拼接并通过一个线性层融合。

这种设计允许模型同时关注来自不同表示子空间的信息,例如,一个头关注语法结构,另一个头关注指代关系等。
自注意力与因果注意力
-
自注意力 :在编码器中,
Q, K, V均来自同一个输入序列。它允许序列中的每个位置关注到整个输入序列的所有位置,从而建立全局依赖。 -
因果注意力 :在解码器 中,为了保持生成过程的自回归 特性(即当前词元的生成只能依赖于已生成的词元),必须引入注意力掩码。具体而言,通过一个下三角矩阵(主对角线及以下为0,以上为负无穷)与注意力分数相加,使得第
i个位置只能关注到第1到i个位置。简化的因果自注意力Mask实现(PyTorch伪代码)
import torch
import torch.nn.functional as Fdef causal_attention_mask(seq_len):
"""生成一个下三角因果掩码矩阵"""
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1).bool()
# mask[i, j] = True 表示第i个位置不能关注第j个位置 (j > i)
return mask在计算注意力分数后应用
scores = Q @ K.transpose(-2, -1) / (d_k ** 0.5)
scores.masked_fill_(causal_attention_mask(seq_len), -1e9) # 将mask位置设为负无穷
attn_weights = F.softmax(scores, dim=-1)
context = attn_weights @ V
2.1.3 前馈层
在注意力层之后,每个位置的特征会独立地通过一个前馈神经网络。该网络由两个线性变换和一个中间激活函数构成,通常称为位置式前馈网络。

其中,W_1 ∈ R^(d_model × d_ff), W_2 ∈ R^(d_ff × d_model),d_ff 是中间层的维度,通常是 d_model 的4倍。GeLU(高斯误差线性单元)是比ReLU更平滑的激活函数,在大模型中表现更优。
关键理解:FFN为每个位置引入了非线性和模型容量的巨大提升。它可以被视为一个"专家",负责对注意力层聚合而来的上下文信息进行深度处理和转换。
2.1.4 残差连接与层归一化
为了训练极深的神经网络,Transformer在每个子层(自注意力层、前馈层)周围都应用了残差连接 ,并紧随其后进行层归一化。
-
残差连接 :将子层的输入与其输出相加,即
Output = LayerNorm(x + Sublayer(x))。这有助于缓解梯度消失问题,使得模型可以轻松地学习到恒等映射,从而训练更深的网络。 -
层归一化:对单个样本的所有特征维度进行归一化,使其均值为0,方差为1。这稳定了训练过程,加速了收敛。公式为:

- 其中
μ和σ是x的均值和标准差,γ和β是可学习的缩放和偏移参数。
在现代架构(如LLaMA)中,为了训练稳定性,有时会将层归一化的位置进行调整,例如使用前置归一化 ,即 Output = x + Sublayer(LayerNorm(x))。
2.1.5 编码器和解码器结构
理解了上述组件,我们就可以宏观地审视Transformer的两种主要结构:
-
编码器:
-
由N个完全相同的层堆叠而成。
-
每一层包含一个多头自注意力 子层和一个前馈网络子层,每个子层周围都有残差连接和层归一化。
-
编码器的目标是双向地理解整个输入序列,为每个位置生成富含全局上下文的表示。适用于文本分类、命名实体识别等理解类任务。
-
-
解码器:
-
同样由N个完全相同的层堆叠而成。
-
每一层包含三个子层 :
a. 掩码多头自注意力 :因果自注意力,确保当前位置不窥见未来信息。
b. 交叉注意力 :以解码器第一子层的输出作为
Q,以编码器的最终输出作为K和V。这使得解码器在生成每个词元时,可以"询问"编码器提供的源序列信息。c. 前馈网络。
-
每个子层周围同样有残差连接和层归一化。
-
解码器的目标是基于编码器的上下文和已生成的词元,自回归地生成目标序列。适用于机器翻译、文本摘要等生成类任务。
-
大语言模型的结构选择 :需要重点指出的是,GPT系列、LLaMA、Bloom等当今绝大多数的大语言模型,本质上都是"仅解码器"的架构。它们移除了原始的编码器和解码器中的交叉注意力层,只保留了堆叠的解码器层(带掩码自注意力)。这种架构通过在海量文本上进行自回归语言建模任务(预测下一个词)的预训练,获得了强大的生成能力,并通过后续指令微调等方式,使其能够完成对话、问答等多种任务,而无需明确的编码器-解码器分工。
2.2 生成式预训练语言模型GPT
GPT(Generative Pre-Training)系列模型的开创性贡献在于,它证实了"生成式预训练 + 判别式任务微调"这一范式在NLP领域的巨大潜力。其核心思想是:首先在无标签的大规模文本语料上,通过自监督目标(如下一个词预测)训练一个大型Transformer模型,学习通用的语言表示和世界知识;然后,针对特定的下游任务,使用有标签的数据对这个预训练模型进行微调。
2.2.1 无监督预训练
预训练阶段的目标函数是标准的自回归语言建模:给定一个词元序列 U={u1,...,un}U={u1,...,un},模型通过最大化如下似然函数来学习参数:

其中,k 是上下文窗口大小,Θ 是模型参数。模型架构就是上文介绍的仅解码器Transformer。通过这个过程,模型不仅学会了语法、句法,还内化了训练数据中蕴含的丰富事实和常识。
2.2.2 有监督下游任务微调
在预训练之后,模型被应用于下游任务(如文本分类、自然语言推理等)。假设下游任务的标注数据为 CC,其中每个样本由输入序列 x1,...,xmx1,...,xm 和标签 yy 组成。
-
输入序列被送入预训练模型,获取最后一个词元对应的隐藏状态 hlmhlm。
-
然后,将其通过一个新增的线性输出层(参数为 WyWy)来预测标签:

微调阶段的目标是最大化以下目标函数:

为了提升泛化能力和收敛速度,OpenAI发现将语言建模目标作为辅助任务与微调目标共同优化是有效的:

这里的 L1(C)L1(C) 是针对下游任务数据计算的(无监督)语言建模损失,λ 是权重系数。
2.2.3 基于HuggingFace的预训练语言模型实践
HuggingFace的 transformers 库极大地简化了预训练模型的使用。以下是一个加载预训练GPT-2模型并进行文本生成的示例。
from transformers import GPT2LMHeadModel, GPT2Tokenizer
# 加载预训练模型和分词器
model_name = "gpt2" # 可以是 "gpt2-medium", "gpt2-large" 等
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
model = GPT2LMHeadModel.from_pretrained(model_name)
# 添加pad_token(GPT2原始训练时未设置)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
# 准备输入
text = "The future of artificial intelligence is"
inputs = tokenizer(text, return_tensors="pt")
# 生成文本
outputs = model.generate(
inputs.input_ids,
max_length=100, # 生成最大长度
num_return_sequences=1, # 生成序列数
temperature=0.8, # 控制随机性:较低值更确定,较高值更多样
do_sample=True, # 是否采样
pad_token_id=tokenizer.eos_token_id, # 避免pad_token警告
attention_mask=inputs.attention_mask # 提供注意力掩码
)
# 解码并打印生成结果
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(generated_text)
这段代码展示了如何使用一个预训练的仅解码器模型进行文本补全。model.generate 方法内部实现了自回归生成过程,并支持多种解码策略(如贪婪搜索、束搜索、Top-k采样等)。
从GPT到GPT-3,再到InstructGPT和ChatGPT,其核心架构范式一脉相承,但规模急剧扩大,并且引入了基于人类反馈的强化学习等更为精巧的对齐技术,使其能力发生了质的飞跃。
2.3 大语言模型的结构
随着模型规模的不断扩大,原始Transformer架构在计算效率、训练稳定性和长序列处理方面面临挑战。因此,一系列结构优化被提出。我们以Meta开源的LLaMA模型家族为例,剖析现代大语言模型在结构上的演进。
2.3.1 LLaMA的模型结构
LLaMA本质上是一个基于Transformer的仅解码器模型,但它集成了多个近年来被证明有效的高效架构改进。
1. 前置层归一化
LLaMA采用了 RMSNorm (Root Mean Square Layer Normalization)作为前置归一化。与原始Transformer的后置LN不同,前置LN将层归一化置于子层之前,即 子层输出 = 输入 + 子层(LN(输入))。这种做法被证明能带来更好的训练稳定性和收敛速度。
RMSNorm是LayerNorm的一个变体,它去掉了中心化(减均值),只进行缩放,计算更简洁:

其中 γ 是可学习的参数。
2. SwiGLU激活函数
LLaMA在前馈网络中使用了 SwiGLU 激活函数,取代了原始的ReLU或GeLU。SwiGLU是GLU(Gated Linear Unit)变体的一种,其形式如下:

在实践中,前馈网络的公式变为:

这里,W, V ∈ R^(d_model × d_ff), W_2 ∈ R^(d_ff × d_model)。与标准FFN相比,SwiGLU引入了门控机制,增强了模型的非线性表达能力,但参数数量也略有增加(因为有两个投影矩阵W和V)。为了保持参数量可比,通常会将 d_ff 设置为 (2/3)*4*d_model。
3. 旋转位置编码
这是LLaMA模型在位置编码上的关键改进。为了解决传统绝对位置编码(如正弦余弦、可学习)外推能力差的问题,LLaMA采用了 RoPE。
RoPE的核心思想是:通过一个旋转矩阵,在计算查询和键向量的点积注意力分数时,显式地注入绝对位置信息。对于位置为 m 的向量 x,其对应的查询(或键)向量通过如下旋转矩阵进行变换:

其中,R 是一个旋转矩阵,Θ 是一组预设的频率参数。在二维情况下,旋转操作可以直观理解为:

RoPE的优势在于:
2. KV缓存
在自回归生成中,为了避免为每个新生成的词元重新计算之前所有词元的键和值,模型会缓存之前时间步的键值状态。这被称为KV缓存。它能将生成过程中注意力层的计算复杂度从 O(n3)O(n3) 降低到 O(n2)O(n2),是推理加速的关键技术。
总结:大语言模型的基础是Transformer架构,其生命力在于持续的创新与优化。从最初的Encoder-Decoder,到统治性的仅解码器架构,再到集成RMSNorm、RoPE、GQA等改进的现代变体,模型的效率和能力在不断被推向新的高度。理解这些底层原理,是进行有效的模型选型、微调、优化乃至创新的根本前提。在接下来的章节中,我们将深入探讨如何在这些坚实的基础上,通过指令微调、对齐技术等高级方法,激发出大语言模型的全部潜能。
-
相对性 :注意力分数 qmTknqmTkn 只依赖于相对位置
m-n,这与语言的内在特性相符。 -
外推性:由于使用了正弦余弦函数,模型能够在一定程度上泛化到比训练序列更长的序列。
# RoPE实现的简化概念(非完整代码)
import torch
def apply_rope(x, freqs):
"""
x: (batch, seq_len, num_heads, head_dim)
freqs: (seq_len, head_dim//2) 预计算的频率张量
"""
x_ = x.float().reshape(*x.shape[:-1], -1, 2) # 将head_dim拆分为 (..., D/2, 2)
cos = torch.cos(freqs).unsqueeze(0).unsqueeze(2) # (1, seq_len, 1, D/2)
sin = torch.sin(freqs).unsqueeze(0).unsqueeze(2) # (1, seq_len, 1, D/2)
# 旋转操作
x_rotated = torch.stack([
x_[..., 0] * cos - x_[..., 1] * sin,
x_[..., 1] * cos + x_[..., 0] * sin
], dim=-1)
return x_rotated.flatten(-2) # 恢复形状 (..., head_dim)
2.3.2 注意力机制优化
随着上下文长度的增加,标准自注意力 O(n2)O(n2) 的计算和内存复杂度成为瓶颈。LLaMA系列模型(尤其是LLaMA 2)通过以下技术进行优化:
1. 分组查询注意力
GQA是Multi-Head Attention (MHA) 和 Multi-Query Attention (MQA) 的折中。
-
MHA :
h个查询头、h个键头、h个头值,计算量和KV缓存都较大。 -
MQA:所有查询头共享同一个键头和值头。这大大减少了KV缓存,提升了推理速度,但可能带来轻微的性能损失。
-
GQA :将查询头分成
g个组,每组内的查询头共享一个键头和值头。当g = h时,GQA退化为MHA;当g = 1时,GQA退化为MQA。通过选择合适的g,可以在性能和效率之间取得良好平衡。2. KV缓存
在自回归生成中,为了避免为每个新生成的词元重新计算之前所有词元的键和值,模型会缓存之前时间步的键值状态。这被称为KV缓存。它能将生成过程中注意力层的计算复杂度从 O(n3)O(n3) 降低到 O(n2)O(n2),是推理加速的关键技术。
# 推理时使用KV缓存的简化概念 past_key_values = None # 初始化为None generated = [start_token_id] for _ in range(max_length): model_inputs = model.prepare_inputs_for_generation( input_ids=torch.tensor([generated]), past_key_values=past_key_values, use_cache=True # 启用缓存 ) outputs = model(**model_inputs) logits = outputs.logits past_key_values = outputs.past_key_values # 更新缓存,供下一步使用 next_token = sample_from_logits(logits[:, -1, :]) # 采样下一个词元 generated.append(next_token)其他高级优化 :如 FlashAttention,通过利用GPU内存层次结构,避免实例化庞大的注意力分数矩阵,从而在实现近似计算的同时,显著降低内存占用并加速计算。这对于处理超长序列至关重要。
2.4 实践思考
在理论理解和代码实践之外,构建和应用大语言模型还涉及大量工程和策略上的权衡。
-
模型选择与权衡:
-
规模 vs. 效率:更大的模型通常能力更强,但推理延迟高、部署成本大。需要根据实际应用场景(如实时对话 vs. 离线分析)选择合适规模的模型。
-
架构差异:LLaMA、GPT-NeoX、Falcon等不同开源模型在归一化、位置编码、注意力机制上存在细微差别,这些差别会影响微调效果和推理性能。
-
-
长上下文处理:
-
尽管有RoPE等技术,模型在长上下文下的表现依然是一个挑战。需要关注其"大海捞针"的能力,即能否从长文档中准确提取关键信息。
-
对于超长文本,可能需要结合外部向量数据库进行检索增强生成(RAG),而非完全依赖模型的内部上下文。
-
-
推理优化:
-
量化:将FP32的模型权重转换为INT8/INT4,可以大幅减少内存占用和加速推理,但可能带来精度损失。需要探索GPTQ、AWQ等前沿量化技术。
-
模型编译:使用TVM、TorchScript或NVIDIA的TensorRT对计算图进行编译优化,可以提升推理速度。
-
-
生态与工具链:
-
熟练使用HuggingFace
transformers,accelerate,peft(参数高效微调) 等库是现代大模型研发者的必备技能。 -
理解
vLLM,TGI(Text Generation Inference) 等高性能推理服务的原理,对于生产部署至关重要。
-