☰
【图像增强】Restormer 模型详解 笔记 CVPR2022
2026/10/14 10:39:53 网站建设 项目流程

【参考:[2111.09881] Restormer: Efficient Transformer for High-Resolution Image Restoration】

注意点:
所有橙色 Transformer Block 都包含有 MDTA 和 GDFN。

注意力多头:每个头学习一个特征,多个头学习多个特征!

学习点

MDTA:根据全图信息,动态组合不同特征通道。

  • 怎么做:通过 1 × 1 卷积和 3 × 3 深度卷积生成 Q、K、V,再利用全部空间位置的响应,计算通道注意力A = softmax(t · Q̄ · K̄ᵀ),最后用O = A · V加权组合特征。
  • 主要作用:建立通道之间的依赖关系,让特征组合方式随输入内容变化;同时结合局部邻域信息和全图统计信息。
  • 复用场景:希望网络利用全图信息,又不想建立巨大的像素 × 像素注意力矩阵时。
  • 注意点:每头注意力矩阵是d × d,不是HW × HW;输入通道数必须能被头数整除。

GDFN:通过局部处理和乘法门控,进一步变换特征。

  • 怎么做:先扩张通道并执行深度卷积,再拆成两条分支,计算G = GELU(Z₁) ⊙ Z₂,最后将通道投影回原大小。
  • 主要作用:引入局部空间信息和非线性,让一条分支调制另一条分支,对特征进行抑制、放大或其他调整。
  • 复用场景:需要增强普通前馈网络或卷积模块的特征变换能力时,可以用它替换简单的“两层投影 + 激活”结构。
  • 注意点:门控没有 sigmoid,数值不限于[0,1],因此不是概率开关。
模块方便记忆的作用核心操作
MDTA决定不同通道如何协同全图响应计算通道关系,再加权混合
GDFN对混合后的特征进一步加工局部卷积、非线性、逐元素门控

复用接口:两者都能保持[B,C,H,W] → [B,C,H,W]。在你的可读版代码中,它们本身不包含 LayerNorm 和残差相加;组合成完整 Block 时使用X₁ = X + MDTA(LN₁(X)),再使用X₂ = X₁ + GDFN(LN₂(X₁))。

Restormer 模型

图中的Restormer 是一种用于图像恢复的四级编码器—解码器网络。它将退化图像转换为特征,通过不同分辨率的 Transformer Block 提取信息,再逐级恢复分辨率,预测图像残差,得到清晰图像。

它的主要特点是:使用 MDTA 建立由全图信息决定的通道注意力,使用 GDFN 对特征进行门控变换,同时通过多尺度结构与跳跃连接保留图像细节。

下面按图中的数据流详细解释。公式使用行内代码和 Unicode 符号,避免 LaTeX 渲染问题。具体计算对应项目中的 …/basicsr/models/archs/restormer_arch.py

第 1 步:先找到输入和输出,确定读图方向

图左上角的照片,下面写着Degraded(I),是输入图像。“Degraded”表示图像存在退化,例如模糊、噪声或者雨纹。I 是这张输入图像的符号。

图右上角的照片,旁边写着Restored(Î),是网络输出的恢复图像。Î 表示网络对清晰图像的预测。

中间的大部分结构,就是将左边的退化图像转换为右边恢复图像的处理过程。

整张图的主要路线是:从左上角进入,沿左侧向下,到达底部,再沿中间偏右的位置向上,最后向右输出。

你可以先把它想成一条 U 形路线。左边向下的部分负责提取特征,右边向上的部分负责恢复图像。

第 2 步:明确哪里是编码器,哪里是解码器

你问的“哪里是解码器”,先直接定位:

编码器在图的左侧。从最上方第一个橙色Transformer Block × L₁开始,沿红色向下箭头,经过Transformer Block × L₂、Transformer Block × L₃,最后到图底部的Transformer Block × L₄。

解码器在图的中间偏右,沿绿色向上箭头排列。从底部的 L₄ 模块输出开始,经过绿色上采样箭头、圆圈 C、1 × 1 卷积和橙色 Block,逐级向上,直到最上方中间的Transformer Block × L₁。

具体来说,解码器的三个处理层,从下往上是:

  1. 中间偏下的Transformer Block × L₃。
  2. 中间位置被展开为MDTA + GDFN的橙色 Block。它代表二级解码器中的 Transformer Block,内部结构被画出来了。
  3. 最上方中间的Transformer Block × L₁,它是一级解码器。

最上方更靠右、下面写着Refinement的 Block 是后续精炼阶段。

图底部的Transformer Block × L₄是连接编码器和解码器的最低分辨率部分,通常叫作瓶颈层。项目代码将它命名为latent。

所以,读这张图时可以先划出四块:左侧编码器、底部瓶颈层、中间偏右解码器、右上方精炼与输出。

第 3 步:理解“编码”和“解码”在这里是什么意思

这里的“编码”不是把图片压缩成 JPEG 文件,也不是加密。

编码器做的是:将图片转换成网络内部的特征表示,并逐步在更低分辨率上处理这些特征。

解码器做的是:将低分辨率特征逐步恢复到原始分辨率,并融合编码器保留下来的信息,为生成恢复图像做准备。

还有一点很重要:解码器的中间输出通常仍然是“特征”,不是可以直接显示的 RGB 图片。直到最后一个输出卷积,网络才把这些特征转换成 3 通道图像。

第 4 步:先搞懂 H、W、C,后面才能看懂每条箭头

图中反复出现H × W × C:

  • H:特征图的高度。
  • W:特征图的宽度。
  • C:特征图的通道数。

输入 RGB 图像有三个通道,即红、绿、蓝,所以图中的输入和输出都是H × W × 3。

经过网络卷积后,通道数可以变成 48、96、192、384。这些通道已经不是红、绿、蓝了,而是网络学习得到的不同特征响应。

例如,一些通道可能对边缘变化比较敏感,一些可能对某种纹理或颜色组合比较敏感。不过每个通道的意义由训练决定,并没有人为规定“第一个通道必须检测边缘”。

你可以把一个通道想成一张二维数值图。48 个通道,就是 48 张高度为 H、宽度为 W 的数值图叠在一起。

图中采用H × W × C的写法;代码采用[B,C,H,W]。其中 B 是一次同时输入多少张图像。如果只输入一张,B = 1。

比如一张 256 × 256 的 RGB 图片,在代码中就是[1,3,256,256]。后面我们一直用这张图作为例子。

第 5 步:看懂图左侧的图例

图中的符号分别表示:

图中符号含义对数据做什么
3 × 3方框普通卷积从局部邻域计算新特征
1 × 1方框点卷积在每个位置混合不同通道
3 × 3 Dconv深度卷积分别处理每个通道的局部邻域
红色向下箭头下采样降低空间分辨率
绿色向上箭头上采样提高空间分辨率
圆圈 CConcatenation,拼接将两份特征沿通道接起来
圆圈 RReshape,重排改变数据的维度组织方式
圆圈加号逐元素相加对应位置的数值相加
实心点乘号逐元素相乘对应位置的数值相乘
圆圈叉号矩阵乘法按矩阵规则进行加权组合
NormLayer Normalization归一化特征
弯曲符号GELU 激活对数值进行非线性变换

先记住两个容易混淆的操作:

拼接会增加通道数。两份[1,48,256,256]特征沿通道拼接,得到[1,96,256,256]。

相加不会增加通道数。两份[1,48,256,256]特征逐元素相加,结果仍是[1,48,256,256]。

第 6 步:输入先经过第一个 3 × 3 卷积

从左上角的输入照片出发,向右遇到一个绿色的3 × 3方框。这个卷积负责生成浅层特征 F₀。

什么是卷积?可以先理解为:在图像上取一个局部窗口,使用一组可学习的权重进行加权求和,计算出一个新的数值,再移动窗口继续计算。

3 × 3 表示窗口的空间大小。对于 RGB 输入,实际计算还会使用输入的三个通道。

这个模块默认生成 48 个输出通道。因此,输入[1,3,256,256]经过它后,变成[1,48,256,256]。

计算可以写成F₀ = Conv₃×₃(I)。

这里高度和宽度没有变化。代码中卷积的步长为 1,并在边缘进行 padding,所以输出空间尺寸仍为 256 × 256。

代码将这个模块叫作OverlapPatchEmbed。它先把原始像素转换成后续网络可以处理的特征。

第 7 步:进入第一级编码器

F₀ 向右进入图左上方第一个橙色方框:Transformer Block × L₁。

这里的“× L₁”表示连续执行 L₁ 个 Transformer Block。默认 L₁ = 4,所以这个方框实际上包含四个连续的 Block。

这里的 L₁ 表示 Block 数量,不是 L1 损失。

每个 Block 都会改变特征中的数值,但保持高度、宽度、通道数不变。所以一级编码器输入是[1,48,256,256],输出仍是[1,48,256,256]。

把它的输出叫作 E₁,计算为E₁ = Encoder₁(F₀)。

E₁ 的输出分成两条路线:

一条沿红色箭头向下,继续进入更深的编码器。
另一条沿横向黑线向右,保留给最上层解码器使用这条横向路线就是跳跃连接,后面会详细讲。

第 8 步:第一次下采样,进入二级编码器

从一级编码器向下,遇到第一个红色箭头。这个箭头表示下采样。

默认情况下,这一步把[1,48,256,256]变成[1,96,128,128]。

可以分开看:

  • 高度:256 → 128。
  • 宽度:256 → 128。
  • 通道:48 → 96。

因此,图中写的是H/2 × W/2 × 2C。

代码里的下采样不是直接缩放图片,而是两步操作。

第一步,用普通 3 × 3 卷积将通道从 48 减少到 24,得到[1,24,256,256]。

第二步,使用PixelUnshuffle(2),把每个 2 × 2 空间块中的四个位置搬到通道维。空间尺寸减半,通道乘以 4,因此得到[1,96,128,128]。

整个过程是[1,48,256,256] → [1,24,256,256] → [1,96,128,128]。

PixelUnshuffle 只是重排元素,没有可训练参数;前面的卷积负责学习特征变换。

随后,特征进入Transformer Block × L₂。默认 L₂ = 6,连续处理六个 Block,输出仍为[1,96,128,128]。把这份输出叫作 E₂。

E₂ 同样分成两路:一路继续向下,一路横向保留给二级解码器。

第 9 步:第二次下采样,进入三级编码器

从二级编码器继续沿红色箭头向下。

这次输入为[1,96,128,128],经过下采样得到[1,192,64,64]。

变化规律和上一步一致:空间尺寸减半,通道数翻倍。

图中对应H/4 × W/4 × 4C。因为已经连续下采样两次,所以高度和宽度都变成最初的四分之一。

随后进入Transformer Block × L₃。默认 L₃ = 6,经过六个 Block 后,shape 仍为[1,192,64,64]。把输出叫作 E₃。

E₃ 也保留一条横向跳跃连接,供三级解码器使用。

第 10 步:第三次下采样,到达底部瓶颈层

继续沿红色箭头向下,输入[1,192,64,64]变成[1,384,32,32]。

图中对应H/8 × W/8 × 8C。

接下来进入图底部的Transformer Block × L₄。默认 L₄ = 8,所以这里连续执行八个 Block。

输出叫作 Fₗ,代码将这组 Block 命名为latent。它的 shape 为[1,384,32,32]。

到这里,编码路径已经完成。

原始图像有 256 × 256 个空间位置,现在只有 32 × 32 个空间位置,但每个位置拥有更多通道。网络在这样的特征表示上继续进行信息处理。

需要注意:低分辨率特征并不是一张简单缩小的照片,它是经过多层卷积、注意力和前馈变换得到的数值表示。

第 11 步:从瓶颈层向上,正式进入解码器

现在从图底部的 Fₗ 出发,沿线向右,再沿第一个绿色箭头向上。

这就是解码器的起点。

绿色箭头表示上采样。第一次上采样将[1,384,32,32]变成[1,192,64,64]。

空间尺寸翻倍,通道数减半。

代码里的上采样也有两步。

第一步,用普通 3 × 3 卷积将通道从 384 扩展到 768,得到[1,768,32,32]。

第二步,使用PixelShuffle(2),将每四个通道重新组织成一个 2 × 2 空间区域,得到[1,192,64,64]。

完整过程是[1,384,32,32] → [1,768,32,32] → [1,192,64,64]。

PixelShuffle 本身是重排操作,不是凭空生成新信息。上采样前的卷积会学习如何生成适合重排的通道特征。

第 12 步:在圆圈 C 处,与三级编码器特征拼接

第一次上采样后,向上会遇到一个圆圈 C。

这里有两条输入:

一条从下面来,是刚上采样得到的[1,192,64,64]。

另一条从左边来,是三级编码器之前保留的 E₃,shape 同样为[1,192,64,64]。

圆圈 C 将它们沿通道拼接,得到[1,384,64,64]。

可以写成Z₃ = Concat(Up(Fₗ), E₃)。

为什么要把编码器的特征拿过来?

因为编码器在这个分辨率上已经提取过信息。解码器恢复到相同分辨率时,可以直接使用这些保留下来的特征,不必完全依赖底部特征重新构造所有细节。

这条横向路线叫作skip connection,跳跃连接。它跨过了更深的处理路径,将某一级的信息直接送到对应的解码级。

第 13 步:通过 1 × 1 卷积,再进入三级解码器

拼接后向上,会遇到一个蓝色的1 × 1方框。

这是一个 1 × 1 卷积,负责将通道从 384 压缩回 192,shape 从[1,384,64,64]变成[1,192,64,64]。

1 × 1 卷积虽然不直接查看周围像素,但会在每个位置混合全部输入通道。可以把它理解为:在一个位置上,将 384 个特征数值重新组合成 192 个数值。

随后进入橙色Transformer Block × L₃。这就是三级解码器,默认包含六个 Block。

经过处理后,输出 D₃ 为[1,192,64,64]。

把刚才三个操作连起来,就是:上采样 → 与编码特征拼接 → 1 × 1 压缩通道 → Transformer Block。

第 14 步:继续上采样,进入二级解码器

D₃ 向上经过第二个绿色箭头。

shape 从[1,192,64,64]变成[1,96,128,128]。

随后在第二个圆圈 C 处,与二级编码器保留的 E₂ 拼接。E₂ 的 shape 为[1,96,128,128],因此拼接结果为[1,192,128,128]。

再通过上面的 1 × 1 卷积,将通道从 192 压缩到 96,得到[1,96,128,128]。

随后进入图中间那个内部写着MDTA 和 GDFN的橙色方框。

这个方框属于二级解码路径。画图时,作者把一个 Transformer Block 展开,让你看到里面的两个核心模块。

并不是只有这里才有 MDTA 和 GDFN。前面所有橙色 Transformer Block 都包含它们。

项目实际的二级解码器默认仍然堆叠六个 Block,输出 D₂ 为[1,96,128,128]。

第 15 步:最后一次上采样,进入一级解码器

D₂ 继续沿第三个绿色箭头向上。

shape 从[1,96,128,128]变成[1,48,256,256],恢复到原始图像的空间尺寸。

随后在最上方圆圈 C 处,与一级编码器保留的 E₁ 拼接。两份特征都是[1,48,256,256],拼接后得到[1,96,256,256]。

这里与前面两级不同:拼接后没有再通过 1 × 1 卷积将通道压回 48。

网络直接使用 96 个通道进入最上方中间的Transformer Block × L₁。这就是一级解码器,默认包含四个 Block。

输出是图中标记的 Fᵈ,shape 为[1,96,256,256]。

这时解码器已经完成了三次上采样。空间尺寸回到了原始的 256 × 256,但数据仍然是 96 通道的特征,不是最终图片。

第 16 步:进入右上方的 Refinement

FᵈF d F_dFd​向右进入下方写着Refinement的橙色方框。

Refinement 可以理解为“精炼阶段”:在已经恢复到原始分辨率的特征上,继续进行处理。

默认包含四个 Transformer Block。它不再上采样,也不再下采样,输入输出都是[1,96,256,256]。

输出叫作 Fʳ,可以写成Fʳ = Refinement(Fᵈ)。

这一阶段处理的是已经融合浅层编码信息和深层解码信息的特征。

第 17 步:将特征转换成三通道残差图像

Fʳ 继续向右,通过最后一个绿色的3 × 3方框。

这个普通卷积将 96 个特征通道转换为 3 个输出通道,shape 从[1,96,256,256]变成[1,3,256,256]。

图中把这份三通道输出叫作 R,可以写成R = Conv₃×₃(Fʳ)。

R 是网络预测的图像残差,也就是“输入图像需要怎样修改”。

它还不是右侧最终的恢复图像,因为后面还要进行一次相加。

第 18 步:与原始输入相加,得到恢复结果

注意图最上方有一条很长的黑线。它从输入 I 出发,跨过几乎整个网络,最终进入输出前的圆圈加号。

这个圆圈加号有两个输入:

一个是原始退化图像 I。

另一个是刚才预测的残差 R。

它们逐元素相加,得到Î = I + R。

例如,某个像素的输入数值是 0.4,网络预测该位置的修正量是 0.1,那么输出就是 0.5;如果修正量是 −0.1,输出就是 0.3。

这表示网络学习在原图基础上进行调整。R 可以为正,也可以为负。

这里的输入残差相加,与编码器和解码器之间的通道拼接不同。最后相加不会改变 shape,所以恢复结果仍为[1,3,256,256]。

到这里,整张图的外部路线已经走完。

第 19 步:现在再打开橙色 Transformer Block

前面我们把 Transformer Block 当作一个“输入输出尺寸不变、但会处理特征”的盒子。

现在打开这个盒子。

每个 Block 按顺序包含两个主要处理阶段:

  1. LayerNorm → MDTA → 加回输入。
  2. LayerNorm → GDFN → 加回该阶段输入。

对于输入 X,第一个阶段计算X₁ = X + MDTA(LN₁(X))。

第二个阶段接着计算X₂ = X₁ + GDFN(LN₂(X₁))。

这里的 X、X₁、X₂ shape 都相同。

为什么要“加回输入”?因为模块输出可以作为对原特征的修正,而输入本身能够直接保留下来。这就是特征层面的残差连接。

它与最终的图像残差连接原理相似,但这里相加的是网络内部特征,而不是 RGB 图像。

第 20 步:先理解 LayerNorm

MDTA 和 GDFN 前面都有 Norm,它表示 Layer Normalization。

在这个项目中,LayerNorm 对每个像素位置的通道向量进行处理。

假设某一层有 48 个通道,那么在一个空间位置上,就有 48 个特征数值。LayerNorm 根据这 48 个数值计算均值和方差,再进行归一化。

它不是把整张图所有位置混在一起归一化。

代码先将[B,Cᵢ,Hᵢ,Wᵢ]重排成[B,N,Cᵢ],其中 N = Hᵢ × Wᵢ,再沿最后的通道维处理。

普通WithBias版本的计算是y = γ ⊙ (x−μ)/√(σ²+ε) + β。

这里:

  • μ 是当前位置的通道均值。
  • σ² 是当前位置的通道方差。
  • ε 是一个很小的数,用来保持数值稳定。
  • γ 是可学习的缩放参数。
  • β 是可学习的平移参数。

项目还提供BiasFree版本,计算为y = γ ⊙ x/√(σ²+ε)。它没有 β,并且分子不减均值,但仍然计算方差。

Block 中前后两次 LayerNorm 使用各自独立的参数。

第 21 步:找到右下角的 MDTA 展开图

右下角浅黄色区域,标记为(a),就是 MDTA 的内部结构。

从左到右看,它的主线是:

输入 X → Norm → 生成 Q、K、V → reshape → 计算注意力 → 与 V 做矩阵乘法 → reshape → 1 × 1 卷积 → 加回 X。

MDTA 的全称是 Multi-DConv Head Transposed Attention。

可以先不记全称,先记它要做的事情:根据整幅特征图的响应,决定不同特征通道之间如何相互组合。

第 22 步:Q、K、V 是什么,从哪里来

Norm 的输出在图中叫作 Y。

Y 分成三条路线,每条路线都有一个 1 × 1 卷积和一个 3 × 3 深度卷积,分别生成 Q、K、V。

Q 是 Query,通常翻译为查询;K 是 Key,通常翻译为键;V 是 Value,通常翻译为值。

它们不是额外输入的图片,也不是人为指定的数据。它们都是同一份输入特征 Y,经过三组不同的可学习变换生成的。

可以写成Q = DWConvQ(PWConvQ(Y)),K、V 的生成方式相同,但使用不同参数。

Q 和 K 用来计算通道之间的关系,V 提供后面被加权组合的特征数值。

为什么先用 1 × 1 卷积?

因为它在每个空间位置混合通道,把已有通道转换成适合 Q、K、V 的表示。

为什么再用 3 × 3 深度卷积?

因为它让每个通道的响应包含附近像素的信息。

“深度卷积”与普通卷积的区别是:深度卷积分别处理各个通道,不在这一步混合不同通道。通道间的混合主要由前后的 1 × 1 卷积完成。

代码为了方便,将三条路线合并计算:先生成 3Cᵢ 个通道,再进行深度卷积,最后拆成三份。因此 Q、K、V 各自都有 Cᵢ 个通道。

第 23 步:理解“多头”

假设当前特征有 96 个通道,设置两个注意力头。

网络就把通道分成两组,每组 48 个通道,各自计算自己的注意力矩阵。

这里 a = 2,d = 96/2 = 48。

多头不是把图片切成左右两半,也不是每个头负责图像中的一个区域。这里是沿通道维分组,每个头仍然使用当前特征图的全部空间位置。

不同头可以在不同通道子空间中学习不同的组合关系。最后将各头输出重新合并,并用输出卷积继续混合信息。

因此要求 Cᵢ 能够被 a 整除。

第 24 步:理解 reshape 后的数据长什么样

Q、K、V 最初都是[B,Cᵢ,Hᵢ,Wᵢ]。

代码将通道分成 a 个头,并把二维空间展开,变成[B,a,d,N]。

例如,在二级编码器中,shape 为[1,96,128,128],头数为 2,则 reshape 后得到[1,2,48,16384],因为 128 × 128 = 16,384。

对于一个头中的某个通道,现在可以把它看成一个长度为 16,384 的向量。这个向量包含了该通道在所有空间位置上的响应。

Reshape 没有学习新权重,也没有改变这些数值本身,只是换一种方式组织它们,方便后面的矩阵运算。

随后,代码还会对 Q 和 K 的每个空间响应向量进行 L2 归一化,即Q̄ᵢ = Qᵢ/max(‖Qᵢ‖₂,ε),K̄ 同理。

这一步与前面的 LayerNorm 不同:LayerNorm 在每个像素位置沿通道处理;这里沿每个通道的全部空间位置处理。

第 25 步:计算通道之间的关系

接下来,Q̄ 与转置后的 K̄ 做矩阵乘法,计算S = t · Q̄ · K̄ᵀ。

shape 变化是[B,a,d,N] @ [B,a,N,d] → [B,a,d,d]。

这里 K̄ᵀ 表示交换最后两个维度。这样 Q̄ 和 K̄ 相乘时,空间位置维 N 被求和,留下两个通道维。

对于矩阵中的一个元素,计算为Sᵢⱼ = t · Σn(Q̄ᵢₙK̄ⱼₙ)。

它的含义是:取第 i 个查询通道和第 j 个键通道,比较它们在全部空间位置上的响应,再把比较结果汇总成一个分数。

因此,S 中的每一个元素描述的是两个通道之间的相关关系。

t 是可学习的温度乘子,每个头有自己的 t。它调整 softmax 前分数的幅度。

第 26 步:Softmax 将关系分数变成权重

图中 Q、K 矩阵乘法之后有 Softmax。

它将每一行的分数转换成权重,计算为Aᵢⱼ = exp(Sᵢⱼ)/Σk exp(Sᵢₖ)。

同一行的所有权重都为正,并且总和为 1。

例如,某一行最后得到[0.1,0.7,0.2],可以理解为:这一输出通道在组合 value 特征时,对三个通道分别使用 0.1、0.7、0.2 的权重。

图中的灰色方格就是注意力矩阵 A。

这个矩阵的大小是每头 d × d,不是像素数量 N × N。

第 27 步:用注意力权重组合 V

图中注意力矩阵 A 向下,与 V 在圆圈叉号处进行矩阵乘法,得到O = A · V。

shape 为[B,a,d,d] @ [B,a,d,N] → [B,a,d,N]。

对于空间位置 n,输出通道 i 的计算是Oᵢₙ = Σj(AᵢⱼVⱼₙ)。

也就是说:在同一个空间位置,把不同 V 通道的响应按权重组合起来,生成新的通道响应。

注意力矩阵 A 是根据整幅特征图计算得到的,所以它包含当前图像的全局信息;随后,这组权重应用于各个空间位置的通道组合。

这也解释了它的特点:权重的生成使用全图响应,而输出阶段主要进行通道混合。

最后,O 经过 reshape 合并各个头,恢复成[B,Cᵢ,Hᵢ,Wᵢ],再通过 1 × 1 输出卷积。

图最右侧的加号将这份变换结果与原始 X 相加,得到第一个残差子层的输出 X₁。

第 28 步:为什么 MDTA 没有建立巨大的像素关系矩阵

如果对每个像素与其他全部像素建立关系,那么 N 个位置需要 N × N 的注意力矩阵。

对于 256 × 256 的特征图,N = 65,536,N × N 约有 42.9 亿个元素。

MDTA 改为建立通道关系。如果 Cᵢ = 48、a = 1,那么注意力矩阵只有 48 × 48,共 2,304 个元素。

这只是在比较注意力矩阵的规模,不代表整个模型只需要这么少的计算或显存。Q、K、V 仍然包含全部空间位置,计算它们的相关性也需要遍历这些位置。

但它避免了显式保存一个巨大 N × N 矩阵。这是其能够处理高分辨率特征的重要原因。

第 29 步:接着进入右上角的 GDFN

MDTA 子层得到 X₁ 后,接下来执行 GDFN 子层。

图右上角浅蓝色区域,标记为(b),就是 GDFN 的展开结构。

主线是:输入 → Norm → 两条卷积分支 → 一条分支执行 GELU → 两条分支逐元素相乘 → 1 × 1 输出卷积 → 加回输入。

GDFN 的全称是 Gated-DConv Feed-Forward Network,可以理解为“包含深度卷积和门控操作的前馈网络”。

这里的“前馈”表示特征继续向前经过一组变换。“门控”则表示一条特征分支的数值会调制另一条分支。

第 30 步:GDFN 先增加内部通道

设 GDFN 的输入通道为 Cᵢ,扩张因子为 r,内部每条分支的通道数为D = int(Cᵢ·r)。

默认 r = 2.66。比如 Cᵢ = 48 时,D = int(127.68) = 127。

代码先使用一个 1 × 1 卷积,将输入通道从 Cᵢ 扩展到 2D。

因此,对于[B,48,Hᵢ,Wᵢ]的输入,这一步得到[B,254,Hᵢ,Wᵢ]。

接着执行 3 × 3 深度卷积,shape 保持不变。

再沿通道拆成两份 Z₁ 和 Z₂,每份都有 127 个通道,即[B,127,Hᵢ,Wᵢ]。

图中把这两份数据画成两条并行路线。代码用一次扩张卷积、一次深度卷积和一次通道拆分完成它们。

第 31 步:GELU 和逐元素乘法形成门控

在图中的两条路线里,一条经过 GELU,另一条不经过激活。随后两条路线在实心点乘号处相乘。

计算为G = GELU(Z₁) ⊙ Z₂。

GELU 是一种非线性函数,其形式为GELU(z) = z·Φ(z),Φ 是标准正态分布的累积分布函数。学习这张结构图时,先把它理解为“对输入数值进行平滑的非线性调整”即可。

⊙ 表示逐元素乘法。例如,两条分支在某个相同位置的数值分别为 0.5 和 2,那么乘积就是 1;如果其中一条接近零,乘积也会接近零。

因此,一条分支的响应可以抑制、放大或改变另一条分支的响应,这就是“门控”的含义。

这里没有 sigmoid,所以门控数值不限定在[0,1]。它不是只能“打开或关闭”的开关。

乘法前后 shape 不变,两份[B,D,Hᵢ,Wᵢ]相乘,得到一份[B,D,Hᵢ,Wᵢ]。

第 32 步:GDFN 恢复通道,并完成第二次残差相加

乘法得到的 G 经过最后一个 1 × 1 卷积,将通道从 D 压回 Cᵢ。

对于刚才的例子,就是[B,127,Hᵢ,Wᵢ] → [B,48,Hᵢ,Wᵢ]。

于是 GDFN 的变换结果与输入 shape 相同,可以进行残差相加。

第二个子层的输出为X₂ = X₁ + GDFN(LN₂(X₁))。

到这里,一个完整 Transformer Block 执行结束。

前面所有橙色方框中的每个 Block,都会执行这两次特征更新:先用 MDTA 处理通道关系,再用 GDFN 进行门控特征变换。

第 33 步:将所有位置与默认代码参数对应起来

默认网络的各层配置如下。这里“每头通道数”决定了注意力矩阵的大小。

位置通道数注意力头数每头通道数Block 数量
一级编码器481484
二级编码器962486
三级编码器1924486
底部瓶颈层3848488
三级解码器1924486
二级解码器962486
一级解码器961964
Refinement961964

一级解码器有 96 个通道,是因为它与一级编码特征拼接后,没有再压缩通道。

所以,虽然四级编码器每头都是 48 个通道,但一级解码器和 refinement 每头是 96 个通道。

第 34 步:把一张图的完整 shape 路线再走一遍

对于输入[1,3,256,256],每个关键位置如下:

顺序图中位置shape
1左上角退化图像 I[1,3,256,256]
2第一个 3 × 3 卷积输出 F₀[1,48,256,256]
3左上方一级编码器 E₁[1,48,256,256]
4第一次红色箭头下采样[1,96,128,128]
5左侧二级编码器 E₂[1,96,128,128]
6第二次红色箭头下采样[1,192,64,64]
7左侧三级编码器 E₃[1,192,64,64]
8第三次红色箭头下采样[1,384,32,32]
9底部瓶颈层 Fₗ[1,384,32,32]
10第一次绿色箭头上采样[1,192,64,64]
11与 E₃ 在圆圈 C 处拼接[1,384,64,64]
121 × 1 卷积压缩[1,192,64,64]
13三级解码器 D₃[1,192,64,64]
14第二次绿色箭头上采样[1,96,128,128]
15与 E₂ 在圆圈 C 处拼接[1,192,128,128]
161 × 1 卷积压缩[1,96,128,128]
17二级解码器 D₂[1,96,128,128]
18第三次绿色箭头上采样[1,48,256,256]
19与 E₁ 在圆圈 C 处拼接[1,96,256,256]
20一级解码器输出 Fᵈ[1,96,256,256]
21Refinement 输出 Fʳ[1,96,256,256]
22最后的 3 × 3 卷积输出 R[1,3,256,256]
23与输入 I 相加,得到 Î[1,3,256,256]

这张表对应的就是图中从左上进入、向下编码、向上解码、向右输出的完整路线。

第 35 步:这些卷积和注意力为什么能学会恢复图像

图中卷积的权重、LayerNorm 的缩放和平移参数、注意力的温度参数等,都是通过训练学习的。

训练时,网络接收退化图像 I,生成恢复结果 Î,再与对应的清晰图像 GT 比较。

项目常用 L1 损失,可以理解为Loss = mean(|Î−GT|),即计算预测图像与清晰目标在所有像素和通道上的平均绝对误差。

通过反向传播,程序计算哪些参数影响了误差,再由优化器调整这些参数。经过大量退化图像和清晰图像对的训练,网络逐渐学会合适的特征提取、通道组合、门控变换和残差预测方式。

图中没有人为指定“这一层删除雨滴”或者“那个通道补充边缘”。这些处理方式由训练数据与损失共同决定。

第 36 步:图中的输出路线与双像素任务有什么不同

图中展示的是普通单图 RGB 恢复:输入是 3 通道,输出残差也是 3 通道,所以能够执行Î = I + R。

项目中的双像素去散焦任务输入不同。它将左右两张 RGB 图像沿通道拼接,形成 6 通道输入,最终仍生成 3 通道恢复图像。

6 通道输入不能直接与 3 通道输出逐元素相加。因此,代码在这个任务中改为使用浅层特征跳跃连接:先将 F₀ 从 C 通道投影到 2C 通道,与 refinement 特征 Fʳ 相加,再通过输出卷积生成 RGB 图像,计算为Î = Convout(Fʳ + Convskip(F₀))。

它仍然使用前面讲过的编码器、瓶颈、解码器、MDTA 和 GDFN,只是输入通道与最后的跳跃连接方式发生了变化。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询