课程名称:神经网络与深度学习
授课教师:屈桢深老师
周次:第4周

在这里插入图片描述

图注:本周课程以 Transformer 架构为主线,重点理解输入编码、注意力机制、编码器、解码器和输出预测流程;同时结合 DeepLabV3 示例,回顾语义分割模型从图像输入到像素级预测的实践链路。

摘要

第3周课程主要围绕 Transformer 模型展开。Transformer 是现代深度学习中非常重要的基础结构,它用自注意力机制替代传统循环结构,使模型能够并行处理序列,并在自然语言处理、计算机视觉、多模态建模等方向形成广泛影响。

本周学习内容可以概括为两条线索。第一条是 Transformer 理论与代码实现:从词嵌入、位置编码开始,逐步进入 Mask、Scaled Dot-Product Attention、多头注意力、前馈网络、残差连接、LayerNorm、编码器、解码器和最终输出层。第二条是 DeepLabV3 语义分割实践:通过 deeplab.ipynb、离线预训练权重和测试图片,理解一个成熟视觉模型如何完成像素级分类。

通过本周学习,可以把“神经网络结构”从单个层的堆叠理解为完整的数据流:输入如何变成向量,向量如何通过注意力交互,编码器如何抽取上下文,解码器如何生成输出,视觉分割模型又如何把图像映射为类别掩码。

目录

  1. Transformer模型整体认识
  2. 输入部分:Embedding与位置编码
  3. 注意力机制:Mask、Scaled Dot-Product Attention与Multi-Head Attention
  4. 编码器:前馈网络、LayerNorm、残差连接与Encoder堆叠
  5. 解码器与输出部分
  6. Transformer代码实现链路
  7. DeepLabV3语义分割实践
  8. 本周知识点表格总结
  9. 本周学习收获
  10. 总结
  11. CSDN发布建议

1. Transformer模型整体认识

Transformer 最早面向序列建模任务提出。传统 RNN、LSTM、GRU 等循环神经网络按时间步顺序处理序列,天然适合表达前后依赖,但也带来两个问题:一是长距离依赖传播路径较长,二是训练时很难充分并行。CNN 虽然能够并行计算,但卷积核感受野有限,需要堆叠较多层才能覆盖远距离关系。

Transformer 的核心思想是用注意力机制直接建模序列中任意位置之间的关系。对一句话来说,某个词不必只依赖前一个词或局部窗口,而是可以通过 Attention 直接关注句子中所有相关词。这样,模型既能捕捉长距离依赖,也更适合 GPU 并行计算。

在这里插入图片描述

图注:Transformer 由 Encoder 和 Decoder 两大部分组成。输入序列先经过词嵌入和位置编码,再进入编码器;解码器结合已生成目标序列和编码器输出,最后通过 Linear 与 Softmax 得到预测分布。

从结构上看,标准 Transformer 通常包含:

  • 输入部分:词嵌入层和位置编码层。
  • 编码器部分:多头自注意力、前馈全连接网络、残差连接、LayerNorm。
  • 解码器部分:Masked 多头自注意力、编码器-解码器注意力、前馈网络、残差连接、LayerNorm。
  • 输出部分:线性映射和 Softmax,将隐藏向量映射为词表概率。

课程中的 Transformer.ipynb 按模块逐步实现了这些结构。它不是只调用现成库,而是从 EmbeddingsPositionalEncodingattentionMultiHeadedAttention 等模块开始写起,帮助我们理解 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)

如果 QK 的维度很高,点积结果可能变得很大。Softmax 输入过大时,会让概率分布过于尖锐,梯度变小,训练不稳定。除以 sqrt(d_k) 相当于缩放分数,使注意力权重更平滑。

3.4 Multi-Head Attention

单个注意力头只能在一个表示子空间中计算关系。多头注意力把输入映射到多个子空间,让不同头分别关注不同关系。例如,一个头可能关注主谓关系,另一个头可能关注位置邻近关系,还有一个头可能关注长距离依赖。

在这里插入图片描述

图注:多头注意力将 Q、K、V 分成多个头并行计算,再拼接和线性映射。编码器中使用自注意力,解码器中既有 Masked 自注意力,也有与编码器输出交互的注意力。

课程中 MultiHeadedAttention 的实现思路可以概括为:

  1. 使用多个线性层分别生成 Q、K、V。
  2. 将张量 reshape 为多头形式。
  3. 对每个头执行 Scaled Dot-Product Attention。
  4. 将多个头的输出拼接。
  5. 再通过线性层得到最终输出。

多头注意力是 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)=astd+ϵxmean+b

其中 ab 是可学习参数,\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_modeldata_generatorLabelSmoothingSimpleLossComputerun 等函数或类,用于构造完整模型、生成示例数据、定义损失和训练流程。

其中 make_model 是一个重要封装,它将编码器、解码器、嵌入层、位置编码、输出层等组装成完整模型,并使用 Xavier 初始化参数。这样可以把前面分散实现的模块合并为可训练网络。

7. DeepLabV3语义分割实践

第3周文件夹中还包含 image_segmentation 实践材料。该部分包括:

  • deeplab.ipynb:使用 DeepLabV3-ResNet101 进行语义分割的程序文件。
  • deeplabv3_resnet101_coco-586e9e4e.pth:离线预训练模型权重。
  • runner.jpgdog.jpgathletes.jpg:测试用图片。
  • readme.txt:说明模型权重需要放入 PyTorch cache 目录。

在这里插入图片描述

图注:DeepLabV3 推理流程包括输入图像、预处理归一化、模型前向传播、类别得分图、argmax 获取像素类别、调色板上色和分割结果可视化。

7.1 DeepLabV3实践流程

deeplab.ipynb 的执行流程较清晰:

  1. 导入 PyTorch。
  2. 通过 torch.hub.load 加载 deeplabv3_resnet101 预训练模型。
  3. 调用 model.eval() 进入推理模式。
  4. 使用 PIL 读取本地图像。
  5. 使用 torchvision.transforms 将图像转为张量并归一化。
  6. 使用 unsqueeze(0) 增加 batch 维度。
  7. 如果可用,将模型和输入转移到 GPU。
  8. torch.no_grad() 下执行前向传播。
  9. model(input_batch)['out'][0] 得到输出。
  10. argmax(0) 得到每个像素的预测类别。
  11. 构造调色板,将类别图转为彩色分割图。

核心推理代码如下:

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模块功能表

模块输入输出核心作用
Embeddingtoken id词向量将离散文本转为连续向量
Positional Encoding词向量带位置的词向量提供序列顺序信息
Scaled Dot-Product AttentionQ、K、V上下文向量按相关性汇总序列信息
Multi-Head Attention多组Q/K/V融合后的表示从多个子空间捕捉关系
Feed Forward每个位置的表示非线性变换后表示提升单位置表达能力
LayerNorm隐藏向量规范化向量稳定训练
Residual Connection输入与子层输出相加后的表示缓解深层网络训练困难
Encoder源序列表示源端上下文表示编码输入序列
Decoder目标前缀与源端上下文目标端隐藏表示自回归生成输出
Generator隐藏表示词表概率得到最终预测 token

8.2 Q/K/V含义表

符号名称直观理解在Attention中的作用
QQuery当前词提出的问题与 Key 计算匹配程度
KKey每个词提供的索引特征被 Query 检索
VValue每个词携带的信息内容按注意力权重加权求和
QK^T注意力分数位置之间的相关性Softmax前的原始权重
Softmax权重归一化把分数变为概率决定各位置关注比例
Mask遮蔽矩阵禁止关注某些位置避免看未来或看padding

8.3 Encoder与Decoder对比表

对比项EncoderDecoder
主要目标理解输入序列根据输入和已生成内容产生输出
注意力类型Self-AttentionMasked 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、多模态模型和复杂视觉应用打下基础。

更多推荐