查看全课大纲(第 85 / 93 节)
- 1.计算机视觉概述
- 2.计算机视觉应用场景
- 3.困难与挑战
- 4.开源库介绍
- 5.图像显示与存储
- 6.CLAHE
- 7.腐蚀膨胀与开闭运算
- 8.滤波与边缘填充
- 9.各种滤波
- 10.图像金字塔
- 11.傅里叶变换
- 12.短时傅里叶变换与小波变换
- 13.颜色特征与颜色直方图
- 14.几何特征_边缘
- 15.几何特征-角点与斑点
- 16.局部特征-SIFT特征描述子
- 17.局部特征-SURF特征描述子
- 18.局部特征-ORB特征描述子
- 19.其他特征描述子
- 20.传统图像分割技术
- 21.GraphCut
- 22.GrabCut
- 23.人脸检测的传统方法
- 24.行人检测的传统方法HOG+SVM
- 25.行人检测DPM
- 26.人工神经网络的架构
- 27.目标函数与梯度下降
- 28.误差反向传播
- 29.可手算的神经网络
- 30.改进目标函数与克服梯度消散
- 31.神经网络之传统神经网络与深度网络的差异
- 32.各种梯度下降算法
- 33.如何选择合适的梯度下降算法
- 34.避免过适应
- 35.CNN的架构
- 36.CNN的误差反向传播_卷积层
- 37.CNN的误差反向传播_池化层
- 38.分类所用的数据集
- 39.Alexnet详解
- 40.VGG详解
- 41.GoogLeNet_v1
- 42.BatchNormalization
- 43.GoogLeNet_v3v4
- 44.ResNet
- 45.ResNeXt
- 46.CNN设计准则
- 47.图像检索与推土机距离
- 48.基于颜色相似性
- 49.基于形状相似性
- 50.基于纹理相似性
- 51.基于局部特征相似性
- 52.DL的二值哈希编码
- 53.高维空间中检索KDTree
- 54.高维空间中检索LSH
- 55.目标识别任务综述
- 56.RCNN
- 57.SPP-Net
- 58.Fast R-CNN
- 59.Faster R-CNN
- 60.R-CNN系列模型回顾
- 61.R-FCN的设计思路
- 62.R-FCN的实现
- 63.YOLOv1
- 64.YOLOv2_9000
- 65.YOLOv3
- 66.图像分割应用场景与数据集
- 67.上采样的实现方式
- 68.FCN网络架构的由来
- 69.FCN构建细节
- 70.DeepLabv1
- 71.CRF
- 72.DeepLabv2
- 73.DeepLabv3
- 74.特定的医学影像分割任务
- 75.U-Net
- 76.3D U-Net
- 77.V-Net
- 78.DenseNet
- 79.病理切片分析任务及数据集
- 80.病理切片分析
- 81.图说任务及其传统处理方法
- 82.深度语言模型与RNN
- 83.LSTM及其变种
- 84.NIC模型
- 85.SAT模型
- 86.图说的性能指标
- 87.判别模型与生成模型
- 88.KL散度与JS散度
- 89.VAE
- 90.GAN的基本原理
- 91.DCGAN与CGAN
- 92.Wasserstein GAN
- 93.SRGAN
SAT模型
SAT模型:注意力机制驱动的图像描述
小象实战讲义 · 基于深度学习的计算机视觉
在上一节我们学习了NIC模型——一个基于编码器-解码器(Encoder-Decoder)框架的图像描述模型。NIC模型将整张图像编码为一个固定长度的语义向量,然后由LSTM解码器生成描述语句。然而,这种”一刀切”的编码方式存在明显局限:生成每个词语时,模型都使用相同的全局图像信息,无法根据当前要描述的词语动态聚焦于图像的不同区域。
本节我们将学习Show, Attend and Tell(SAT)模型,这是第一个将注意力机制引入图像描述任务的里程碑工作。通过注意力机制,SAT模型能够”动态聚焦”——在生成每个词语时,自动关注图像中最相关的区域,从而生成更准确、更细致的描述。
💡 核心导读
- 注意力机制的本质:在编码器-解码器框架中,让解码器在生成每个输出时,能够动态地关注输入序列中不同的部分,而不是使用固定的全局编码。
- SAT模型架构:在NIC模型基础上,增加注意力模块,使LSTM在每个时间步都能接收到基于当前上下文动态计算的图像区域特征。
- 两种注意力机制:硬注意力(Hard Attention)与软注意力(Soft Attention),分别对应离散选择和连续加权两种聚焦方式。
- LSTM的改进:SAT中的LSTM单元增加了第三个输入——上下文向量,用于接收注意力机制提取的视觉信息。
- 训练方式:软注意力可端到端反向传播;硬注意力因采样不可微,需要强化学习(REINFORCE)估计梯度。
注意力机制:从固定编码到动态聚焦
编码器-解码器框架的局限
在传统的编码器-解码器框架中(如NIC模型),编码器将整个输入序列(如图像或句子)压缩为一个固定长度的语义向量C,然后解码器基于这个固定的C生成输出序列。
传统Encoder-Decoder:
输入序列 → Encoder → 固定语义向量C → Decoder → 输出序列这种架构存在一个根本问题:无论解码器生成哪个词语,它都使用完全相同的语义向量C。这意味着图像中所有区域对生成每个词语的”影响力”都是相同的。
注意力机制的引入
注意力机制的核心思想是:让解码器在生成每个输出时,能够动态地关注输入序列中不同的部分。
带注意力的Encoder-Decoder:
输入序列 → Encoder → 多个隐藏状态h₁, h₂, ..., h_T
↓
解码时刻t → 计算注意力权重α_ti → 加权和得到上下文向量c_t → 生成输出y_t以机器翻译为例,考虑将英文句子”Tom chase Jerry”翻译为中文”汤姆追逐杰瑞”:
- 生成”汤姆”时,模型应该重点关注输入中的”Tom”
- 生成”追逐”时,重点关注”chase”
- 生成”杰瑞”时,重点关注”Jerry”
这里的关键不是手工规定”汤姆”必须对齐”Tom”,而是先保留”每个输入位置都可能与当前输出建立关联”这条通路,剩下的事交给训练——只要模型有这个自由度,梯度下降会自己把”Tom”的权重推到最大、把其余两个词的权重压低。若在建模阶段就把这条通路掐断,模型再也不可能学到这种对齐。
注意力机制通过为每个输入位置分配不同的权重来实现这种动态聚焦。权重 表示在生成第 个输出时,第 个输入位置的重要性。
注意力机制的数学表达
在图像描述任务中,注意力机制可以形式化地表示为:
对于图像划分出的 个区域,每个区域提取 维特征向量 ()。在解码时刻 ,模型需要生成第 个词语。注意力机制计算每个区域的重要性权重 :
其中:
- 是第 个图像区域的特征向量
- 是解码器上一时刻的隐藏状态
- 是注意力函数(通常是一个小型神经网络)
- 是归一化的注意力权重(通过 softmax)
基于这些权重,计算上下文向量 :
这里φ是特征融合函数,根据注意力类型的不同有两种实现方式。
SAT模型架构详解
整体框架
SAT模型整体遵循编码器-解码器架构,但在两个关键方面进行了改进:
- 编码器:使用CNN(VGG)提取图像特征,但不是生成单个全局向量,而是保留空间信息,得到L个D维的区域特征向量。
- 解码器:使用改进的LSTM,在每个时间步接收三个输入:上一个词语、上一个隐藏状态、以及基于注意力计算的上下文向量。
# SAT模型组件演示(概念性代码)
print("SAT模型核心组件:")
print("1. 编码器:VGG CNN提取区域特征")
print("2. 注意力模块:计算区域权重")
print("3. 解码器:改进的LSTM生成描述")
print("4. 词表映射:生成词语概率分布")SAT模型核心组件:
1. 编码器:VGG CNN提取区域特征
2. 注意力模块:计算区域权重
3. 解码器:改进的LSTM生成描述
4. 词表映射:生成词语概率分布编码器:图像区域特征提取
SAT模型使用VGG网络的最后一个卷积层(论文实现用VGG-19,即conv5_4层)的输出作为图像特征。该层的输出尺寸为14×14×512:
- 14×14:将图像划分为196个网格区域
- 512:每个区域的特征维度
import numpy as np
# 模拟VGG特征提取结果
np.random.seed(42)
# 14×14×512的特征图
feature_map = np.random.randn(14, 14, 512) * 0.1
# 将特征图展平为区域特征序列
# 形状从(14, 14, 512)变为(196, 512)
height, width, channels = feature_map.shape
region_features = feature_map.reshape(height * width, channels)
print(f"特征形状: {feature_map.shape}")
print(f"展平后: {region_features.shape} (区域数×特征维度)")
print("区域特征示例(第一个区域,前10维):")
print(region_features[0, :10])特征形状: (14, 14, 512)
展平后: (196, 512) (区域数×特征维度)
区域特征示例(第一个区域,前10维):
[ 0.04967142 -0.01382643 0.06476885 0.15230299 -0.02341534 -0.0234137
0.15792128 0.07674347 -0.04694744 0.054256 ]这196个512维向量{a₁, a₂, …, a₁₉₆}就是编码器的输出,每个向量对应图像的一个局部区域。
解码器:改进的LSTM
SAT模型中的LSTM单元在标准LSTM基础上增加了一个输入——上下文向量ž_t:
标准LSTM输入:E(y_{t-1}), h_{t-1}
SAT-LSTM输入:E(y_{t-1}), h_{t-1}, ž_t其中:
- :上一时刻输出词的嵌入向量。 是词表上的 one-hot 向量(论文直接用 one-hot,不必引入 word2vec), 是一个可学习的嵌入矩阵,把它映射为与图像区域特征同维的词向量——这一步正是”把文本编码映射到图像特征空间”,映射矩阵本身由训练得到
- :上一个时刻 LSTM 的隐藏状态
- ž_t:基于注意力机制计算的上下文向量(视觉信息),与区域特征同为D维,每个时刻算一个
LSTM的计算公式相应扩展为:
输入门:
遗忘门:
输出门:
候选记忆:
记忆更新:
隐藏状态:
LSTM初始状态计算
LSTM的初始隐藏状态h₀和初始细胞状态c₀不是随机初始化的,而是通过图像特征计算得到:
其中 和 是两个独立的多层感知机(MLP)。这种设计使得 LSTM 的初始状态包含了图像的全局信息。
注意力模块:软注意力与硬注意力
注意力权重计算
在时刻 ,注意力模块需要计算每个图像区域的权重 。计算过程分为两步:
计算未归一化的注意力得分 : 这里 、 和 是可学习参数, 函数实际上是一个单隐藏层的前馈神经网络。之所以用上一时刻的隐藏状态 而不是 : 已经消化了上一时刻输出的词,正好回答”知道上一个词是什么之后,接下来该看图像哪里”这个问题。
通过softmax归一化得到注意力权重:
import numpy as np
def attention_weights(region_features, h_prev, W_a, W_h, v):
"""对全部 L 个区域计算 e_ti = v^T tanh(W_a a_i + W_h h_{t-1}),再 softmax 归一化"""
scores = np.array([v @ np.tanh(W_a @ a_i + W_h @ h_prev) for a_i in region_features])
scores = scores - scores.max() # 减去最大值只为数值稳定,不改变 softmax 结果
exp_scores = np.exp(scores)
return exp_scores / exp_scores.sum()
# 在本块内构造所有数据,确保自包含
np.random.seed(42)
num_regions, feature_dim, att_dim = 196, 512, 512
region_features = np.random.randn(num_regions, feature_dim) * 0.1
h_prev = np.random.randn(feature_dim) * 0.1
W_a = np.random.randn(att_dim, feature_dim) * 0.01
W_h = np.random.randn(att_dim, feature_dim) * 0.01
v = np.random.randn(att_dim) * 0.01
alpha = attention_weights(region_features, h_prev, W_a, W_h, v)
print("前3个区域的注意力权重(示例):")
print(alpha[:3])
print(f"全部196个权重之和: {alpha.sum():.6f}")前3个区域的注意力权重(示例):
[0.00512877 0.00508258 0.00505132]
全部196个权重之和: 1.000000特征融合:两种注意力机制
得到注意力权重后,需要将区域特征融合为上下文向量ž_t。SAT论文提出了两种不同的融合方式:
1. 软注意力(Soft Attention)
软注意力采用加权求和的方式:
这种方式是可微的,可以直接通过反向传播进行端到端训练。每个区域都对上下文向量有贡献,只是权重不同。
2. 硬注意力(Hard Attention)
硬注意力采用随机采样的方式:
- 根据权重 采样一个区域索引
- 令
- 未被选中的区域权重为0
硬注意力不可微,需要使用强化学习的方法(如REINFORCE算法)进行训练。因为每次只选中一个格子,硬注意力的定位粒度就是196分之一,目标跨多个格子时一次只能顾及其中一块;软注意力则可以同时覆盖多个格子、只是权重不同。不过要如实说明:论文实验中两者性能总体相当,硬注意力在多数BLEU指标上还略高一点;软注意力真正的优势在于可微、能端到端反向传播、训练过程更平滑稳定,因此被后续工作广泛采用。
import numpy as np
# 在本块内构造数据:196个区域、512维特征,alpha 为归一化后的注意力权重
np.random.seed(42)
num_regions, feature_dim = 196, 512
region_features = np.random.randn(num_regions, feature_dim) * 0.1
alpha = np.random.rand(num_regions)
alpha = alpha / alpha.sum()
def soft_attention_fusion(region_features, alpha):
"""软注意力:全部区域加权求和"""
return np.sum(alpha[:, None] * region_features, axis=0)
def hard_attention_fusion(region_features, alpha):
"""硬注意力:按权重采样一个区域,只用该区域的特征"""
sampled_idx = np.random.choice(len(alpha), p=alpha)
return region_features[sampled_idx], sampled_idx
z_soft = soft_attention_fusion(region_features, alpha)
np.random.seed(0) # 固定采样结果,保证每次运行一致
z_hard, sampled_idx = hard_attention_fusion(region_features, alpha)
print("软注意力结果(前5维):", z_soft[:5])
print("硬注意力结果(前5维):", z_hard[:5])
print(f"硬注意力采样区域索引: {sampled_idx}")软注意力结果(前5维): [ 0.00454625 -0.00437575 0.01724027 -0.02173376 0.00981122]
硬注意力结果(前5维): [ 0.00114455 -0.06430687 -0.05325285 -0.08504897 0.05391213]
硬注意力采样区域索引: 109词语生成概率
得到 LSTM 的当前隐藏状态 和上下文向量 后,模型计算词语生成概率:
其中 、、 是线性变换矩阵,三者分别作用于词向量、隐藏状态和上下文向量,相加后得到词表大小 维的得分,再经 softmax 归一化。论文原文把这一式写成”正比于exp(…)”,含义相同;三项相加也等价于把三个向量拼接后过一层线性层,分开写更能看出每一路信息各自的贡献。
这里要注意,上下文向量ž_t被用了两次:一次作为LSTM本时刻的输入(参与门控和状态更新),一次在这里参与输出层的打分。也就是说,注意力既影响”记忆怎么更新”,也直接影响”当前词怎么选”。
SAT模型训练与推理
训练过程
使用软注意力时,SAT模型的训练是端到端的,目标是最小化负对数似然:
对于软注意力,这个损失函数可以直接通过反向传播优化。需要补一句:论文的软注意力目标在负对数似然之外还加了一项“双重随机”正则 ,鼓励每个图像区域在各时间步上的注意力总和接近 1,使注意力在各区域间分配得更均衡;为聚焦主干,上面的式子只写了似然项。
对于硬注意力,采样操作不可微,损失应写成对采样位置的期望:
其中 是按注意力权重采样出的 one-hot 选择向量,实际训练时用蒙特卡洛采样估计该期望;由于采样位置没有梯度,注意力部分的梯度改用 REINFORCE 估计,并以回报的滑动平均作为baseline降低方差。
推理过程
在推理阶段,模型使用beam search生成描述:
- 从开始符号"
"开始 - 在每个时间步,保留概率最高的k个候选序列(beam size=k)
- 对于每个候选序列,计算下一个词的概率分布
- 扩展候选序列,保留总体概率最高的k个
- 重复直到生成结束符号"
"或达到最大长度
可视化效果
SAT模型最直观的贡献是提供了注意力机制的可视化。在生成每个词语时,模型会高亮显示它关注的图像区域:
- 生成”bird”时,注意力集中在鸟的区域
- 生成”water”时,注意力集中在水面区域
- 生成”flying”时,注意力可能集中在鸟的翅膀和天空背景
这种”注意力热图”不仅提高了模型的可解释性,也验证了注意力机制的有效性。
SAT模型的贡献与局限
主要贡献
- 首次将注意力机制引入图像描述:为后续研究奠定了基础
- 可解释的视觉对齐:通过注意力热图展示模型”看哪里”
- 灵活的架构设计:支持软注意力和硬注意力两种机制
- 端到端训练:软注意力下整个系统可以联合优化(硬注意力需强化学习,不属于严格意义上的端到端)
局限性
- 计算复杂度:需要为每个区域计算注意力权重,当区域数量多时计算量大
- 硬注意力训练困难:需要强化学习,训练不稳定
- 空间分辨率受限:注意力在14×14的网格上做选择,VGG的224×224输入下每个格子只覆盖原图16×16像素,小于格子的目标难以被精确定位
- 序列生成速度:LSTM的自回归生成方式较慢
后续发展
SAT模型启发了大量后续工作,包括:
- 自适应注意力:让模型决定何时查看图像
- 自上而下与自下而上注意力:结合物体检测器的区域建议
- Transformer架构:完全基于注意力机制,取代LSTM
- 多模态预训练:如CLIP、BLIP等大规模预训练模型
本章小结
SAT模型是图像描述领域的一个重要里程碑,它通过引入注意力机制,解决了传统编码器-解码器框架中”固定编码”的问题。模型的核心创新在于:
- 动态聚焦机制:在生成每个词语时,自动关注图像中最相关的区域
- 改进的LSTM:增加上下文向量输入,融合视觉信息
- 两种注意力范式:软注意力(可微,端到端训练)和硬注意力(离散,强化学习训练)
- 可解释的可视化:通过注意力热图展示模型的”关注点”
SAT模型不仅提升了图像描述的性能,更重要的是提供了一种可解释的机制,让我们能够理解模型生成描述时的”决策过程”。需要如实说明的是,SAT是2015年的工作:LSTM解码器加软/硬注意力的范式此后已被Transformer解码器和大规模视觉-语言预训练模型(CLIP、BLIP等)取代,今天学习它的价值主要在于理解注意力机制的基本形态,以及”注意力热图”这一可解释性工具的思想来源。
📋 行动清单
- 理解注意力机制在编码器-解码器框架中的作用:为什么需要动态聚焦?
- 掌握SAT模型中LSTM的改进:三个输入分别是什么?如何计算?
- 区分软注意力与硬注意力:各自的实现方式、优缺点是什么?
- 尝试可视化思考:给定一张图像和描述,想象SAT模型生成每个词时的注意力分布
📝 动手练一练
- 注意力权重计算:假设有三个图像区域,特征向量分别为 、、,上一时刻隐藏状态 。使用简化注意力函数 (点积),计算 softmax 归一化后的注意力权重。
👉 点击查看参考答案
import numpy as np
# 给定数据
a1 = np.array([1, 0, 0])
a2 = np.array([0, 1, 0])
a3 = np.array([0, 0, 1])
h = np.array([0.5, 0.5, 0.5])
# 计算注意力得分(点积)
e1 = np.dot(a1, h) # 1*0.5 + 0*0.5 + 0*0.5 = 0.5
e2 = np.dot(a2, h) # 0*0.5 + 1*0.5 + 0*0.5 = 0.5
e3 = np.dot(a3, h) # 0*0.5 + 0*0.5 + 1*0.5 = 0.5
# softmax归一化
scores = np.array([e1, e2, e3])
alpha = np.exp(scores) / np.sum(np.exp(scores))
print("注意力得分:", scores)
print("归一化权重:", alpha)注意力得分: [0.5 0.5 0.5]
归一化权重: [0.33333333 0.33333333 0.33333333]由于三个区域与隐藏状态的点积相同,因此注意力权重均匀分布。
- 软注意力融合:使用上题计算的权重α=[0.2, 0.5, 0.3],对三个区域特征a₁=[1,0], a₂=[0,1], a₃=[1,1]进行加权求和,计算上下文向量ž。
👉 点击查看参考答案
import numpy as np
# 给定数据
a1 = np.array([1, 0])
a2 = np.array([0, 1])
a3 = np.array([1, 1])
alpha = np.array([0.2, 0.5, 0.3])
# 加权求和
z_hat = alpha[0]*a1 + alpha[1]*a2 + alpha[2]*a3
print("上下文向量ž =", z_hat)
print("计算过程:")
print(f" 0.2×[1,0] = {alpha[0]*a1}")
print(f"+ 0.5×[0,1] = {alpha[1]*a2}")
print(f"+ 0.3×[1,1] = {alpha[2]*a3}")
print(f" = {z_hat}")上下文向量ž = [0.5 0.8]
计算过程:
0.2×[1,0] = [0.2 0. ]
+ 0.5×[0,1] = [0. 0.5]
+ 0.3×[1,1] = [0.3 0.3]
= [0.5 0.8]上下文向量ž是三个区域特征的加权组合:第二维由a₂(权重0.5)和a₃(权重0.3)共同贡献,合计0.8;第一维只有a₁(0.2)和a₃(0.3)贡献,合计0.5。
—— 小象教研组