神经网络与深度学习第4周课程总结:Transformer模型与DeepLab语义分割实践
课程名称:神经网络与深度学习
授课教师:屈桢深老师
周次:第4周

图注:本周课程以 Transformer 架构为主线,重点理解输入编码、注意力机制、编码器、解码器和输出预测流程;同时结合 DeepLabV3 示例,回顾语义分割模型从图像输入到像素级预测的实践链路。
摘要
第3周课程主要围绕 Transformer 模型展开。Transformer 是现代深度学习中非常重要的基础结构,它用自注意力机制替代传统循环结构,使模型能够并行处理序列,并在自然语言处理、计算机视觉、多模态建模等方向形成广泛影响。
本周学习内容可以概括为两条线索。第一条是 Transformer 理论与代码实现:从词嵌入、位置编码开始,逐步进入 Mask、Scaled Dot-Product Attention、多头注意力、前馈网络、残差连接、LayerNorm、编码器、解码器和最终输出层。第二条是 DeepLabV3 语义分割实践:通过 deeplab.ipynb、离线预训练权重和测试图片,理解一个成熟视觉模型如何完成像素级分类。
通过本周学习,可以把“神经网络结构”从单个层的堆叠理解为完整的数据流:输入如何变成向量,向量如何通过注意力交互,编码器如何抽取上下文,解码器如何生成输出,视觉分割模型又如何把图像映射为类别掩码。
目录
- Transformer模型整体认识
- 输入部分:Embedding与位置编码
- 注意力机制:Mask、Scaled Dot-Product Attention与Multi-Head Attention
- 编码器:前馈网络、LayerNorm、残差连接与Encoder堆叠
- 解码器与输出部分
- Transformer代码实现链路
- DeepLabV3语义分割实践
- 本周知识点表格总结
- 本周学习收获
- 总结
- CSDN发布建议
1. Transformer模型整体认识
Transformer 最早面向序列建模任务提出。传统 RNN、LSTM、GRU 等循环神经网络按时间步顺序处理序列,天然适合表达前后依赖,但也带来两个问题:一是长距离依赖传播路径较长,二是训练时很难充分并行。CNN 虽然能够并行计算,但卷积核感受野有限,需要堆叠较多层才能覆盖远距离关系。
Transformer 的核心思想是用注意力机制直接建模序列中任意位置之间的关系。对一句话来说,某个词不必只依赖前一个词或局部窗口,而是可以通过 Attention 直接关注句子中所有相关词。这样,模型既能捕捉长距离依赖,也更适合 GPU 并行计算。

图注:Transformer 由 Encoder 和 Decoder 两大部分组成。输入序列先经过词嵌入和位置编码,再进入编码器;解码器结合已生成目标序列和编码器输出,最后通过 Linear 与 Softmax 得到预测分布。
从结构上看,标准 Transformer 通常包含:
- 输入部分:词嵌入层和位置编码层。
- 编码器部分:多头自注意力、前馈全连接网络、残差连接、LayerNorm。
- 解码器部分:Masked 多头自注意力、编码器-解码器注意力、前馈网络、残差连接、LayerNorm。
- 输出部分:线性映射和 Softmax,将隐藏向量映射为词表概率。
课程中的 Transformer.ipynb 按模块逐步实现了这些结构。它不是只调用现成库,而是从 Embeddings、PositionalEncoding、attention、MultiHeadedAttention 等模块开始写起,帮助我们理解 Transformer 内部每一步到底在做什么。
2. 输入部分:Embedding与位置编码
Transformer 的输入不是原始文本,而是张量。文本通常先通过词表映射为整数 token id,再通过 Embedding 层变成连续向量。
课程代码中定义了 Embeddings 类:
class Embeddings(nn.Module):
def __init__(self, d_model, vocab):
super(Embeddings, self).__init__()
self.lut = nn.Embedding(vocab, d_model)
self.d_model = d_model
def forward(self, x):
return self.lut(x) * math.sqrt(self.d_model)
这里有两个关键参数:
vocab:词表大小,表示模型可以识别多少个不同 token。d_model:词向量维度,也是 Transformer 中大多数模块使用的统一隐藏维度。
代码中把 Embedding 输出乘以 sqrt(d_model)。这样做的目的,是调整词向量数值尺度,使嵌入向量与后续位置编码相加时更加稳定。

图注:文本输入先被映射为 token id,再通过 Embedding 矩阵得到词向量;词向量经尺度调整后与位置编码相加,形成包含词义和位置信息的序列表示。
2.1 为什么需要位置编码
Transformer 没有 RNN 的时间步顺序,也没有 CNN 的局部滑动结构。如果只输入词向量,模型能够知道“有哪些词”,却不知道“词出现在哪里”。例如“我喜欢深度学习”和“深度学习喜欢我”包含相同词,但语义完全不同。
因此,Transformer 需要显式加入位置信息。课程中实现的 PositionalEncoding 使用正弦和余弦函数构造位置编码:
PE(pos,2i)=sin(pos100002i/d) PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i)=sin(100002i/dpos)
PE(pos,2i+1)=cos(pos100002i/d) PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i+1)=cos(100002i/dpos)
其中:
pos表示词在序列中的位置。i表示向量维度索引。d表示词向量维度,也就是d_model。
这种设计让不同位置拥有不同编码,同时不同频率的正弦余弦函数可以表达多尺度位置信息。模型不需要额外学习位置参数,也能利用相对位置关系。
2.2 Dropout作用
位置编码层中还使用了 nn.Dropout(p=dropout)。Dropout 会在训练时随机置零部分神经元输出,降低模型对某些局部特征的过度依赖,从而缓解过拟合。课程中演示了 nn.Dropout(p=0.2) 的效果,也说明了 PyTorch 中张量维度变化和 unsqueeze 的使用方式。
3. 注意力机制:Mask、Scaled Dot-Product Attention与Multi-Head Attention
注意力机制是 Transformer 的核心。它解决的问题是:当模型处理某个位置的 token 时,应该重点关注序列中哪些位置。
3.1 Mask张量
课程中先实现了 subsequent_mask(size)。这个函数用于生成后续位置遮蔽矩阵,常用于解码器。解码时,模型只能看到当前位置及其之前的 token,不能提前看到未来答案。
例如目标序列长度为 5 时,第 1 个位置只能看第 1 个位置,第 2 个位置可以看第 1、2 个位置,第 5 个位置才能看完整前缀。这种三角 Mask 保证训练过程符合自回归生成规则。
Mask 还可以用于屏蔽 padding 位置。如果一句话被补齐到固定长度,补齐部分不应该参与注意力计算,否则模型会把无意义 token 当作上下文。
3.2 Scaled Dot-Product Attention
Scaled Dot-Product Attention 是最基础的注意力计算形式:
Attention(Q,K,V)=softmax(QKTdk)V Attention(Q, K, V) = softmax\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
其中:
Q是 Query,表示当前位置发出的查询。K是 Key,表示各位置可被匹配的索引特征。V是 Value,表示各位置真正要被加权汇总的信息。d_k是 Key 向量维度,用于缩放点积结果。

图注:Attention 先用 QK^T 计算位置相关性,再除以 sqrt(d_k) 控制数值尺度,经过 Mask 和 Softmax 得到权重,最后对 V 加权求和。
课程代码中的 attention 函数实现了这一过程:
def attention(query, key, value, mask=None, dropout=None):
d_k = query.size(-1)
scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
p_attn = F.softmax(scores, dim=-1)
if dropout is not None:
p_attn = dropout(p_attn)
return torch.matmul(p_attn, value), p_attn
这里 masked_fill(mask == 0, -1e9) 很关键。它把被遮蔽位置的分数设为极小值,使这些位置经过 Softmax 后权重接近 0。
3.3 为什么要除以sqrt(d_k)
如果 Q 和 K 的维度很高,点积结果可能变得很大。Softmax 输入过大时,会让概率分布过于尖锐,梯度变小,训练不稳定。除以 sqrt(d_k) 相当于缩放分数,使注意力权重更平滑。
3.4 Multi-Head Attention
单个注意力头只能在一个表示子空间中计算关系。多头注意力把输入映射到多个子空间,让不同头分别关注不同关系。例如,一个头可能关注主谓关系,另一个头可能关注位置邻近关系,还有一个头可能关注长距离依赖。

图注:多头注意力将 Q、K、V 分成多个头并行计算,再拼接和线性映射。编码器中使用自注意力,解码器中既有 Masked 自注意力,也有与编码器输出交互的注意力。
课程中 MultiHeadedAttention 的实现思路可以概括为:
- 使用多个线性层分别生成 Q、K、V。
- 将张量 reshape 为多头形式。
- 对每个头执行 Scaled Dot-Product Attention。
- 将多个头的输出拼接。
- 再通过线性层得到最终输出。
多头注意力是 Transformer 强表达能力的重要来源。它不是简单重复计算,而是让模型从多个角度理解同一序列。
4. 编码器:前馈网络、LayerNorm、残差连接与Encoder堆叠
Transformer Encoder 由多个相同结构的 EncoderLayer 堆叠而成。每个 EncoderLayer 主要包含两个子层:
- Multi-Head Self-Attention。
- Position-wise Feed Forward Network。
两个子层外部都配有残差连接和 LayerNorm。
4.1 Position-wise Feed Forward Network
课程中实现了 PositionwiseFeedForward 类。它对序列中每个位置独立应用同一组全连接网络,一般形式为:
FFN(x)=max(0,xW1+b1)W2+b2 FFN(x) = max(0, xW_1 + b_1)W_2 + b_2 FFN(x)=max(0,xW1+b1)W2+b2
注意力层负责混合不同位置的信息,前馈网络负责对每个位置的表示进行非线性变换。二者组合后,模型既能进行全局关系建模,也能提升单个位置表示能力。
4.2 LayerNorm
LayerNorm 用于规范化每个样本内部的特征分布。课程代码中实现了 LayerNorm,核心思想是对最后一个维度求均值和标准差,再进行标准化:
LayerNorm(x)=a⋅x−meanstd+ϵ+b LayerNorm(x) = a \cdot \frac{x - mean}{std + \epsilon} + b LayerNorm(x)=a⋅std+ϵx−mean+b
其中 a 和 b 是可学习参数,\epsilon 用于防止除零。
4.3 残差连接与SublayerConnection
残差连接可以写成:
x+Sublayer(x) x + Sublayer(x) x+Sublayer(x)
它让梯度更容易向前传播,也让深层模型更容易训练。课程中的 SublayerConnection 将残差连接、Dropout 和 LayerNorm 组合起来,用于包裹注意力层和前馈层。
从学习角度看,SublayerConnection 是理解 Transformer 工程实现的关键。很多模型结构图只画出 Add & Norm,但代码中需要明确处理输入、子层函数、Dropout 和规范化顺序。
4.4 EncoderLayer与Encoder
课程中的 EncoderLayer 把自注意力层和前馈层组合起来;Encoder 再通过 clones(layer, N) 复制多个 EncoderLayer,形成深层编码器。
这说明 Transformer 的深度来自模块堆叠。一个 EncoderLayer 已经具备自注意力和非线性变换能力,但多个层堆叠后,模型可以逐层形成更抽象的上下文表示。
5. 解码器与输出部分
Decoder 和 Encoder 类似,也由多个 DecoderLayer 堆叠。但 Decoder 每层通常包含三个子层:
- Masked Multi-Head Self-Attention。
- Encoder-Decoder Attention。
- Position-wise Feed Forward Network。
5.1 Masked Self-Attention
解码器第一个注意力层必须使用 Mask。原因是生成任务通常从左到右预测目标序列。如果训练时允许当前位置看到未来 token,就会信息泄露,模型推理时无法复现训练条件。
例如翻译任务中,模型预测第 3 个词时,只能使用已经生成的第 1、2 个词,不能看到第 4 个词。
5.2 Encoder-Decoder Attention
Decoder 第二个注意力层使用来自 Decoder 的 Query,以及来自 Encoder 输出的 Key 和 Value。这样,解码器在生成每个目标 token 时,都可以回看源序列编码结果。
这一步可以理解为“目标端正在问问题,源端编码结果提供答案依据”。它让模型在生成过程中动态对齐输入序列不同部分。
5.3 输出层Generator
课程中定义了 Generator 类,用线性层把 d_model 维隐藏向量映射到词表大小,再通过 log_softmax 得到对数概率:
class Generator(nn.Module):
def __init__(self, d_model, vocab):
super(Generator, self).__init__()
self.project = nn.Linear(d_model, vocab)
def forward(self, x):
return F.log_softmax(self.project(x), dim=-1)
如果词表大小为 1000,那么每个位置的输出就是 1000 个类别上的概率分布。模型会选择概率最高的 token,或在生成任务中结合搜索策略产生最终序列。
6. Transformer代码实现链路
Transformer.ipynb 的价值在于,它把 Transformer 从局部模块一直搭到完整模型。课程中涉及的主要模块如下:
| 模块 | 代码名称 | 作用 |
|---|---|---|
| 文本嵌入 | Embeddings |
将 token id 映射为 d_model 维向量,并乘以 sqrt(d_model) |
| 位置编码 | PositionalEncoding |
给序列加入位置信息,弥补 Transformer 无循环结构的问题 |
| 掩码张量 | subsequent_mask |
屏蔽未来位置或无效位置 |
| 注意力计算 | attention |
实现 Scaled Dot-Product Attention |
| 多头注意力 | MultiHeadedAttention |
并行计算多个注意力头并融合 |
| 前馈网络 | PositionwiseFeedForward |
对每个位置进行非线性变换 |
| 规范化层 | LayerNorm |
稳定特征分布,提升训练稳定性 |
| 子层连接 | SublayerConnection |
封装残差、Dropout、LayerNorm |
| 编码器层 | EncoderLayer |
组合自注意力和前馈网络 |
| 编码器 | Encoder |
堆叠多个编码器层 |
| 解码器层 | DecoderLayer |
组合 Masked 自注意力、源端注意力和前馈网络 |
| 解码器 | Decoder |
堆叠多个解码器层 |
| 输出层 | Generator |
将隐藏向量映射到词表概率 |
| 完整模型 | EncoderDecoder |
串联编码器、解码器、嵌入层和输出层 |
课程后半部分还出现了 make_model、data_generator、LabelSmoothing、SimpleLossCompute、run 等函数或类,用于构造完整模型、生成示例数据、定义损失和训练流程。
其中 make_model 是一个重要封装,它将编码器、解码器、嵌入层、位置编码、输出层等组装成完整模型,并使用 Xavier 初始化参数。这样可以把前面分散实现的模块合并为可训练网络。
7. DeepLabV3语义分割实践
第3周文件夹中还包含 image_segmentation 实践材料。该部分包括:
deeplab.ipynb:使用 DeepLabV3-ResNet101 进行语义分割的程序文件。deeplabv3_resnet101_coco-586e9e4e.pth:离线预训练模型权重。runner.jpg、dog.jpg、athletes.jpg:测试用图片。readme.txt:说明模型权重需要放入 PyTorch cache 目录。

图注:DeepLabV3 推理流程包括输入图像、预处理归一化、模型前向传播、类别得分图、argmax 获取像素类别、调色板上色和分割结果可视化。
7.1 DeepLabV3实践流程
deeplab.ipynb 的执行流程较清晰:
- 导入 PyTorch。
- 通过
torch.hub.load加载deeplabv3_resnet101预训练模型。 - 调用
model.eval()进入推理模式。 - 使用 PIL 读取本地图像。
- 使用
torchvision.transforms将图像转为张量并归一化。 - 使用
unsqueeze(0)增加 batch 维度。 - 如果可用,将模型和输入转移到 GPU。
- 在
torch.no_grad()下执行前向传播。 - 取
model(input_batch)['out'][0]得到输出。 - 用
argmax(0)得到每个像素的预测类别。 - 构造调色板,将类别图转为彩色分割图。
核心推理代码如下:
with torch.no_grad():
output = model(input_batch)['out'][0]
output_predictions = output.argmax(0)
这里 output 可以理解为类别得分图。对每个像素位置,模型都会输出多个类别的得分;argmax(0) 则选择得分最高的类别,得到最终语义分割结果。
7.2 图像预处理
DeepLabV3 使用了标准 ImageNet 归一化参数:
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)
这一步与模型预训练条件一致。如果输入图像没有按同样方式归一化,模型看到的数据分布会偏离训练分布,预测效果可能下降。
7.3 离线权重说明
readme.txt 提到,原模型约 233MB,从 PyTorch 网站下载可能较慢,因此课程材料提供了对应离线 .pth 文件。权重需要拷贝到:
C:\Users\<username>\.cache\torch\hub\checkpoints
其中 <username> 为当前 Windows 登录用户名。这样执行 torch.hub.load(..., pretrained=True) 时,PyTorch 可以直接使用本地缓存权重。
7.4 与第2周语义分割内容的衔接
第2周学习过 FCN 和语义分割基本概念,第3周的 DeepLabV3 实践相当于把概念落到代码。语义分割不是输出一个类别,也不是输出目标框,而是输出每个像素的类别。
DeepLabV3 的优势在于能够结合深层特征和多尺度上下文,对人、动物、道路、背景等区域进行像素级识别。课程示例中建议使用人、动物等模型训练过的典型目标进行测试,这也说明预训练模型的效果依赖于训练数据类别范围。
8. 本周知识点表格总结
8.1 Transformer模块功能表
| 模块 | 输入 | 输出 | 核心作用 |
|---|---|---|---|
| Embedding | token id | 词向量 | 将离散文本转为连续向量 |
| Positional Encoding | 词向量 | 带位置的词向量 | 提供序列顺序信息 |
| Scaled Dot-Product Attention | Q、K、V | 上下文向量 | 按相关性汇总序列信息 |
| Multi-Head Attention | 多组Q/K/V | 融合后的表示 | 从多个子空间捕捉关系 |
| Feed Forward | 每个位置的表示 | 非线性变换后表示 | 提升单位置表达能力 |
| LayerNorm | 隐藏向量 | 规范化向量 | 稳定训练 |
| Residual Connection | 输入与子层输出 | 相加后的表示 | 缓解深层网络训练困难 |
| Encoder | 源序列表示 | 源端上下文表示 | 编码输入序列 |
| Decoder | 目标前缀与源端上下文 | 目标端隐藏表示 | 自回归生成输出 |
| Generator | 隐藏表示 | 词表概率 | 得到最终预测 token |
8.2 Q/K/V含义表
| 符号 | 名称 | 直观理解 | 在Attention中的作用 |
|---|---|---|---|
| Q | Query | 当前词提出的问题 | 与 Key 计算匹配程度 |
| K | Key | 每个词提供的索引特征 | 被 Query 检索 |
| V | Value | 每个词携带的信息内容 | 按注意力权重加权求和 |
| QK^T | 注意力分数 | 位置之间的相关性 | Softmax前的原始权重 |
| Softmax | 权重归一化 | 把分数变为概率 | 决定各位置关注比例 |
| Mask | 遮蔽矩阵 | 禁止关注某些位置 | 避免看未来或看padding |
8.3 Encoder与Decoder对比表
| 对比项 | Encoder | Decoder |
|---|---|---|
| 主要目标 | 理解输入序列 | 根据输入和已生成内容产生输出 |
| 注意力类型 | Self-Attention | Masked Self-Attention + Encoder-Decoder Attention |
| 是否看未来位置 | 可看完整源序列 | 不能看目标端未来位置 |
| 输入来源 | 源序列Embedding与位置编码 | 目标序列Embedding与位置编码 |
| 输出用途 | 提供源端上下文memory | 送入Generator预测词表概率 |
8.4 DeepLabV3推理流程表
| 步骤 | 对应代码/文件 | 作用 |
|---|---|---|
| 加载模型 | torch.hub.load('pytorch/vision', 'deeplabv3_resnet101', pretrained=True) |
获取预训练DeepLabV3模型 |
| 设置推理模式 | model.eval() |
关闭训练特有行为 |
| 读取图片 | Image.open(local_fn) |
加载测试图像 |
| 预处理 | transforms.ToTensor()、Normalize(...) |
转张量并匹配预训练分布 |
| 增加batch维 | unsqueeze(0) |
适配模型输入格式 |
| 前向传播 | model(input_batch)['out'][0] |
得到类别得分图 |
| 像素分类 | argmax(0) |
为每个像素选择最高得分类别 |
| 可视化 | putpalette(colors)、plt.imshow(r) |
将类别图显示为彩色分割结果 |
8.5 本周知识点与实践收获表
| 学习内容 | 关键问题 | 收获 |
|---|---|---|
| Transformer输入 | 模型如何接收文本 | token id 需要先转为词向量,再加入位置编码 |
| 位置编码 | 无RNN时如何表达顺序 | 正弦余弦编码提供可泛化位置信息 |
| 注意力机制 | 模型如何找上下文重点 | Q/K/V与Softmax实现动态加权 |
| 多头注意力 | 为什么不只用一个注意力 | 多个子空间能捕捉不同关系 |
| Encoder | 如何理解输入序列 | 自注意力和前馈网络反复提炼上下文 |
| Decoder | 如何生成目标序列 | Mask保证自回归,源端注意力提供输入依据 |
| DeepLabV3 | 如何做像素级分类 | 预训练模型输出类别得分图,argmax得到分割掩码 |
9. 本周学习收获
本周最重要的收获是理解 Transformer 的“整体数据流”。以前看 Transformer 结构图时,容易只记住 Encoder、Decoder、Multi-Head Attention 等名称,但通过代码逐层实现后,可以看到每个模块都有明确输入、输出和功能。
Embedding 和位置编码说明,模型输入不是自然语言本身,而是经过词表映射和向量化后的张量。位置编码解决了 Transformer 缺少天然顺序结构的问题。
Attention 机制说明,模型不必按顺序一步步传递信息,而是可以直接计算任意两个位置之间的相关性。QK^T / sqrt(d_k)、Mask、Softmax 和对 V 加权求和,是理解 Transformer 的核心公式。
多头注意力说明,模型可以并行从多个角度理解序列。残差连接和 LayerNorm 则说明,深层网络不仅要有表达能力,还要能稳定训练。
DeepLabV3 实践帮助我们把课程内容与真实视觉任务连接起来。语义分割的输出是像素级类别,而不是整图类别或目标框。模型推理流程中的预处理、GPU判断、torch.no_grad()、类别得分图和调色板可视化,都是实际使用深度学习模型时必须掌握的工程细节。
10. 总结
第3周课程以 Transformer 模型为核心,系统讲解了从输入编码到注意力机制、编码器、解码器和输出预测的完整流程。通过 Transformer.ipynb,可以看到模型不是黑箱,而是由 Embedding、PositionalEncoding、Attention、MultiHeadedAttention、FeedForward、LayerNorm、EncoderLayer、DecoderLayer 等模块一步步搭建而成。
与此同时,image_segmentation 文件夹提供了 DeepLabV3 语义分割实践材料,让本周内容不只停留在序列模型,也延伸到视觉任务。DeepLabV3 示例展示了预训练模型如何读取图像、完成归一化、输出像素类别并生成分割可视化结果。
总体来看,本周学习建立了两个重要认识:第一,Transformer 的强大来自注意力机制、并行建模和稳定的深层结构设计;第二,深度学习模型的学习不能只看理论公式,还需要结合代码、输入输出张量形状和真实推理流程进行理解。
这些内容为后续继续学习大模型、视觉Transformer、多模态模型和复杂视觉应用打下基础。
更多推荐




所有评论(0)