a-PyTorch-Tutorial-to-Super-Resolution

GitHub
707 127 中等 1 次阅读 6天前MIT开发框架图像
AI 解读 由 AI 自动生成,仅供参考

a-PyTorch-Tutorial-to-Super-Resolution 是一个基于 PyTorch 框架的开源教程项目,旨在指导开发者构建能够逼真提升图像分辨率的深度学习模型。它主要解决低分辨率图像模糊、细节缺失的问题,通过算法“幻觉”出原本不存在的像素,将图像尺寸放大四倍(像素量增加 16 倍),同时保持惊人的真实感。

该项目不仅复现了经典的 SRResNet 模型,更重点讲解了如何利用生成对抗网络(GAN)构建 SRGAN 模型。其独特的技术亮点在于引入了残差连接(Residual Connections)以优化深层网络训练,并通过对抗训练机制显著提升了生成图像的纹理细节和视觉自然度,超越了传统仅追求像素误差最小化的方法。

这是一个极佳的学习资源,特别适合具备一定 PyTorch 和卷积神经网络基础的开发者与研究人员。如果你希望深入理解 GAN 的工作原理,或想亲手从零实现前沿的超分辨率算法,这个项目提供了从概念解析、代码实现到训练评估的完整路径。虽然普通用户也可利用其生成的模型处理图片,但其核心价值更偏向于技术教育与算法研究。

使用场景

一家数字档案馆正在处理大量上世纪的低分辨率历史照片,急需将其修复为高清版本以供线上展览和学术研究。

没有 a-PyTorch-Tutorial-to-Super-Resolution 时

  • 画质模糊失真:传统插值算法(如双三次插值)仅能放大像素,导致图像边缘锯齿严重,细节涂抹感强,无法还原纹理。
  • 开发门槛极高:团队若想自研基于生成对抗网络(GAN)的模型,需从零推导复杂的对抗训练逻辑和残差网络结构,耗时数月。
  • 缺乏真实感:现有的开源方案多专注于提升数值指标(如 PSNR),生成的图像虽然清晰但显得过于平滑,丢失了老照片特有的颗粒质感。
  • 试错成本高昂:在没有成熟教程指引的情况下,调整超分辨率模型的超参数如同“盲人摸象”,极易导致模型不收敛或产生伪影。

使用 a-PyTorch-Tutorial-to-Super-Resolution 后

  • 照片级真实复原:利用其内置的 SRGAN 模型,成功将低清图放大 4 倍,不仅清晰度提升,更通过“幻觉”机制合理补全了衣物纹理和面部细节。
  • 快速落地部署:依托详细的 PyTorch 实现教程,团队在数天内便复现了论文模型,无需深究底层数学推导即可直接进行训练和推理。
  • 视觉自然逼真:生成的图像摆脱了机械的平滑感,保留了符合人眼视觉习惯的自然噪点和锐度,完美契合历史照片的修复需求。
  • 流程透明可控:教程清晰拆解了从数据预处理、残差块构建到对抗训练的全过程,让开发人员能轻松针对特定数据集进行微调优化。

a-PyTorch-Tutorial-to-Super-Resolution 将前沿的 GAN 超分技术转化为可执行的代码路径,让低质量图像的瞬间“高清重生”变得触手可及。

运行环境要求

操作系统
  • 未说明
GPU

未说明 (项目基于 PyTorch,通常支持 CUDA GPU 加速,但 README 未指定具体型号或显存要求)

内存

未说明

依赖
notes该项目是一个超分辨率(Super-Resolution)和生成对抗网络(GAN)的教学教程。作者明确声明使用 Python 3.6 和 PyTorch 1.4 版本。由于版本较老,现代环境可能需要调整依赖或使用兼容模式运行。教程假设用户具备 PyTorch 和卷积神经网络的基础知识。
python3.6
PyTorch==1.4
a-PyTorch-Tutorial-to-Super-Resolution hero image

快速开始

这是一个关于**PyTorch 超分辨率的教程**。

同时,这也是一个学习GAN及其工作原理的教程,无论其具体任务或应用是什么。

这是我在一系列教程中的第五篇,旨在教你如何使用强大的 PyTorch 库自行实现各种酷炫的模型。

本教程假定读者已具备 PyTorch 和卷积神经网络的基础知识。

如果你是 PyTorch 的新手,请先阅读 用 PyTorch 进行深度学习:60 分钟速成通过示例学习 PyTorch

如有任何问题、建议或更正,欢迎在问题页面中提出。

我使用的是 PyTorch 1.4Python 3.6

目录

目标

概念

概述

实现

训练

评估

推理

常见问题

目标

构建一个能够真实地提高图像分辨率的模型。

超分辨率(SR)模型本质上是在原本没有像素的地方“幻化”出新的像素。在本教程中,我们将尝试将图像的尺寸四倍放大,即把像素数量增加到原来的16倍!

我们将实现论文中的两种模型——SRResNet,以及在此基础上通过对抗训练进一步改进的 SRGAN。结果不仅非常惊艳,而且也是了解 GAN 的绝佳入门!

我们将训练论文中提到的两个模型:SRResNet 和 SRGAN。在开始之前,不妨先看看一些由训练过程中未见过的低分辨率图像生成的示例。快来体验一下吧!






这是 SRGAN 的视频演示观看链接

由于 YouTube 的压缩可能会降低视频质量,你可以从这里下载原始视频文件,以获得最佳观看效果。

点击观看

请务必以 1080p 分辨率观看,以免 4 倍缩放后的图像被下采样到较低分辨率。


教程的最后还有大型示例查看大型示例


概念

  • 超分辨率。显而易见。

  • 残差连接。残差连接最早出现在 2015 年的开创性论文中,它是一种跨越一层或多层神经网络的捷径,使网络能够学习输入的残差映射——即产生期望输出的扰动——而不是直接学习整个输出。通过在所谓的残差“块”中添加这些连接,可以显著提高深层神经网络的可优化性。

  • 生成对抗网络 (GAN)。源自另一篇具有里程碑意义的论文,GAN 是一种机器学习框架,其中两个网络相互对抗。生成模型(Generator)试图生成与训练数据分布完全一致的数据——在本例中就是更高分辨率的图像;而判别模型(Discriminator)则试图通过学习区分真假来阻止这种伪造行为。随着双方技能的提升,它们可以通过彼此的预测来不断完善对方。最终的目标是让生成器所创造的“虚构”图像在人类眼中与真实图像无异。

  • 亚像素卷积。这是一种替代转置卷积的图像上采样方法。亚像素卷积通过对低分辨率特征图进行常规卷积,生成新的像素,并将其作为新的图像通道,随后再将这些通道“打乱”组合成高分辨率图像。

  • 感知损失。它结合了基于 MSE 的内容损失(在“深度”图像空间中计算,而非通常的 RGB 颜色空间)和对抗损失,从而使生成器能够从判别器的判断中学习。

概述

在这一部分,我将对本模型进行概述。如果你已经熟悉相关内容,可以直接跳转到实现部分或查看带注释的代码。

图像上采样方法

图像上采样本质上是人为地提高其空间分辨率——即增加用于表示图像中“视图”的像素数量的过程。

图像上采样是一种非常常见的应用:每当你在手机上用双指缩放查看图片,或者在1080p显示器上播放480p视频时,都会发生上采样。你可能会认为这其中并没有人工智能的参与,而事实也的确如此——因为一旦你以高于原始编码分辨率的尺寸观看图像,它就会开始显得模糊或出现马赛克效应。

与本教程中我们将尝试的神经网络超分辨率不同,常见的上采样方法并不旨在生成高保真度的、更高分辨率下图像应有的估计结果。相反,它们之所以被使用,是因为图像在显示时经常需要重新采样。例如,当你希望一张图片占据1080p屏幕上的特定区域,或者将其打印成A4纸大小时,显示器或打印机的原生分辨率恰好与图片分辨率一致的可能性微乎其微。尽管上采样在技术上确实提高了分辨率,但显而易见的是,它仍然只是以较高分辨率呈现的一张低分辨率、细节匮乏的图像,或许还经过了一些平滑或锐化处理。

事实上,通过这些方法上采样的图像可以作为低分辨率图像的替代品,用来与超分辨率后的版本进行对比,无论是在论文中还是在本教程中都是如此。如果不以某种方式对低分辨率图像进行上采样(或者反过来对超分辨率图像进行下采样,这显然很荒谬),就无法将低分辨率图像以与超分辨率图像相同的物理尺寸(例如在屏幕上以英寸为单位)显示出来。

那么,让我们来看看一些常见的上采样技术吧?

作为参考图像,我们可以考虑这张来自《赛博朋克2077》的酷炫武士标志由Reddit用户/u/shapanga创作,我在此已获得其许可并加以使用。

现在,我们再来看同一张图像缩小到四分之一尺寸的情况,也就是像素数量减少了16倍:

我们的目标是增加这张低分辨率图像的像素数量,使其能够以与高分辨率版本相同的尺寸显示出来。

最近邻上采样

这是最简单的图像上采样方法,其实质就是直接按原样拉伸图像。

假设有一张小图像,上面有一条黑色对角线,一侧是红色,另一侧是灰色:

首先,我们在已知像素之间按照所需分辨率插入新的空白像素:

然后,我们将每个新像素的值设置为其最近邻已知像素的值

使用最近邻插值法对低分辨率的武士图像进行上采样后,得到的结果会显得块状明显,并且边缘会出现锯齿状:

双线性/双三次上采样

同样地,我们先插入空白像素,使图像达到目标分辨率:

接下来,我们需要为这些空白像素填充颜色。如果我们采用线性插值法,利用距离最近的两个已知像素(即每侧各一个)来计算新像素的值,这就称为双线性上采样

使用双线性插值法对低分辨率的武士图像进行上采样后,结果会比最近邻插值法更加平滑,这是因为像素之间的过渡更为自然:

另外,你也可以采用三次插值法,利用四个已知像素(即每侧各两个)来计算新像素的值,这就是双三次上采样。正如你所想象的那样,由于使用了更多的数据来进行插值,最终结果会更加平滑:

这张维基媒体的示意图很好地展示了这些插值方法。

我猜想,如果你正在用VLC媒体播放器等工具,在高分辨率屏幕上观看低分辨率视频时,你所看到的画面其实就是通过双线性或双三次插值法进行上采样的每一帧。

此外,还有一些更高级的上采样方法,比如Lanczos插值法,不过我对它们的了解相对有限。

神经网络超分辨率

与较为“简单”的图像上采样不同,超分辨率的目标正是从低分辨率版本中生成高分辨率、高保真度、美观且逼真的图像

当一张图像被降为较低分辨率时,细节会不可逆转地丢失。同样地,将图像放大到更高分辨率需要“添加”新的信息

作为人类,你或许能够想象出图像在更高分辨率下会是什么样子——你可能会心想:“这个角落里的模糊一团,其实应该是每一根独立的发丝”,或者“那片沙色的区域很可能就是沙子,看起来应该带有颗粒感”。然而,若要手动完成这样的工作,不仅需要一定的艺术功底,还会耗费大量精力。而本教程的目标,就是训练一个神经网络来完成这项任务

例如,经过超分辨率训练的神经网络可以识别出,上方低分辨率图像中的黑色对角线,在放大后的图像中应当表现为一条平滑但清晰的黑色对角线。

尽管对于一些日常任务而言,使用神经网络进行超分辨率处理可能并不实用,甚至没有必要,但它已经在当今的实际应用中发挥作用。比如,当你玩支持NVIDIA DLSS技术的电子游戏时,屏幕上显示的画面其实是以较低分辨率渲染的,随后通过神经网络“幻化”成更大、更清晰的图像,仿佛一开始就以高分辨率渲染一般。也许不久的将来,你最喜欢的视频播放器就能在你的巨幕电视上自动将影片提升至4K分辨率并播放。

正如本教程开篇所述,我们将训练两种生成式神经网络模型——SRResNetSRGAN

这两种网络都将把图像的尺寸扩大四倍,即像素数量增加16倍!

使用SRResNet超分辨率处理后的低分辨率武士图,其质量已可与原始高分辨率版本相媲美。

而使用SRGAN处理后的低分辨率武士图也同样如此。

就这张武士图而言,我认为SRResNet的效果优于SRGAN。不过,这可能是因为它是一张相对简单的图像,色彩单一且纯色为主——SRResNet在生成过于光滑纹理方面的弱点,在这种情况下反而成了优势。

而在生成具有精细细节的逼真图像方面,由于采用了对抗性训练方式,SRGAN的表现远远超过SRResNet,这一点在本教程中穿插的多个示例中都有所体现。

残差(跳跃)连接

通常来说,更深的神经网络能力更强,但这也存在一个限度。事实证明,增加层数确实能在一定程度上提升性能,然而一旦超过某个临界点,性能反而会下降

这种性能下降并非由过拟合训练数据引起——训练过程中的各项指标同样会受到影响。同时,它也不是由于深度网络常见的梯度消失或爆炸问题所致,因为即便对初始化和各层输出进行了归一化处理,这一现象依然存在。

为了解决深层神经网络难以优化的问题,在2015年发表的一篇开创性论文中,研究人员提出了跳跃连接的概念——这些连接允许信息绕过中间的操作步骤,以未改变的形式直接传递过去,并将其与该操作的输出按元素相加。

这种跳跃连接并不一定只跨越一层。你还可以创建跨多层的快捷路径。

借助跳跃连接,中间层无需学习完整的、未经参考的目标函数,而是学习残差映射——也就是说,它们只需建模输入到期望输出之间需要做出的改变即可。因此,尽管最终结果可能相同,但我们希望这些层学习的内容却发生了根本性的变化。

学习残差映射要容易得多。以极端情况为例:让一组非线性层学习“恒等映射”。乍一看似乎很简单,但实际上,找到合适的权重组合——使输入经过线性变换后,再通过非线性激活仍能恢复原状——并非易事,近似求解也绝非轻而举。相比之下,学习其残差映射则要简单得多:只需将权重调整为零即可,因为此时对应的映射就是“零函数”,即不对输入做任何改变。

事实上,上述例子并没有我们想象得那么极端——网络中的深层层实际上学到的正是接近于恒等函数的行为,因为这些层对输入所做的改动往往非常微小。

跳跃连接使得训练极深的网络成为可能,并能显著提升性能。毫不奇怪,它们被广泛应用于SRResNet(顾名思义,即超分辨率残差网络)以及SRGAN的生成器中。实际上,如今几乎找不到没有跳跃连接的现代神经网络了。

子像素卷积

在卷积神经网络中,如何处理上采样呢?这不仅限于超分辨率任务,也适用于语义分割等应用:在这些应用中,更“全局”的特征图——按定义分辨率较低——必须被上采样到你希望进行分割的分辨率。

一种常见方法是先使用双线性或双三次插值上采样到目标分辨率,然后再应用需要学习的卷积层,以获得更好的结果。事实上,早期的超分辨率网络正是这样做的:在网络的最开始就将低分辨率图像上采样,然后在高分辨率空间中应用一系列卷积层,最终生成超分辨率图像。

另一种流行的方法是转置卷积,你可能已经熟悉它:将完整的卷积核应用于低分辨率图像中的单个像素,生成的多像素块按照设定的步长组合起来,从而得到高分辨率图像。这基本上就是常规卷积过程的逆过程

子像素卷积则是一种替代方案,它通过对低分辨率图像应用常规卷积,使得所需的新增像素以额外通道的形式生成

换句话说,如果要将图像上采样 $s$ 倍,那么对于低分辨率图像中的每个像素,需要生成的 $s^2$ 个新像素,就会通过卷积操作以该位置**$s^2$ 个新通道**的形式产生。你可以为这一操作选择任意大小的卷积核 $k$,而低分辨率图像可以具有任意数量的输入通道 $i$。

随后,这些通道会被重新排列,形成高分辨率图像,这一过程称为像素洗牌

在上面的例子中,高分辨率图像只有一个输出通道。如果你需要 $n$ 个输出通道,只需生成 $n$ 组各 $s^2$ 个通道,然后在每个位置将它们洗牌成 $n$ 组 $s \times s$ 的小块。

在本教程的其余部分,我们将使用如下所示的像素洗牌操作:

正如你所想象的那样,在低分辨率空间中进行卷积比在高分辨率空间中进行卷积更加高效。因此,子像素卷积层通常位于超分辨率网络的末端,在对低分辨率图像应用了一系列卷积之后。

最小化损失函数——回顾

让我们暂时停下来,探讨一下我们为什么要构建损失函数并对其进行最小化。你可能已经了解这些内容,但我觉得再次回顾这些概念很有帮助,因为它们是理解 GAN 训练方式的关键。

  • 损失函数 $L$ 实际上是一个量化我们的网络 $N$ 的输出与期望值 $D$ 之间差异程度的函数。

  • 我们的神经网络输出 $N(θ_N, I)$ 是指在网络当前参数集 $θ_N$ 下,给定输入 $I$ 时产生的输出。

  • 我们称之为“期望值”$D$,而不是“真值”或“标签”,是因为我们期望的值并不一定是真实的,这一点我们稍后会看到。

  • 因此,我们的目标就是最小化损失函数,而这可以通过调整网络参数 $θ_N$ 来实现,使网络输出 $N(θ_N, I)$ 更接近期望值 $D$。

需要注意的是,参数 $θ_N$ 的变化并不是最小化损失函数 $L$ 的结果。相反,最小化损失函数 $L$ 是由于以特定方式改变参数 $θ_N$ 所导致的。我在上面提到“最小化 $L$ 会移动 $θ_N$……”只是为了表明,选择最小化某个特定的损失函数 $L$,就意味着会对 $θ_N$ 进行这些特定的调整

至于如何决定 $θ_N$ 变化的方向和幅度,在这里不是重点,不过为了完整起见:

  • 首先,通过链式法则沿网络反向传播梯度,计算损失函数 $L$ 对参数 $θ_N$ 的梯度,即 $\frac{∂L}{∂θ_N}$,这一过程称为反向传播

  • 然后,根据梯度 $\frac{∂L}{∂θ_N}$ 的大小以及一个称为学习率 $lr$ 的步长,沿着与梯度相反的方向移动参数 $θ_N$,从而沿着损失函数的曲面下降,这一过程称为梯度下降

总结来说,这里的重要启示是:对于给定输入 $I$ 的网络 $N$,通过选择合适的损失函数 $L$ 和期望值 $D$,我们可以调整损失函数上游的所有参数 $θ_N$,从而使网络输出更接近 $D$。

根据具体需求,我们也可以只调整所有参数 $θ_N$ 中的一部分 $θ_n$,同时冻结其他参数 $θ_{N-n}$,从而仅训练整个网络 $N$ 中的一个子网络 $n$,使其输出的变化反过来促使整个网络 $N$ 的输出更接近期望值 $D$。

你可能已经在迁移学习的应用中这样做过——例如,只微调大型预训练 CNN 或 Transformer 模型 $N$ 的最后几层 $n$,以适应新的任务。我们稍后也会做类似的事情,只不过是在完全不同的背景下。

超分辨率残差网络(SRResNet)

SRResNet 是一种 专为 4 倍超分辨率设计的全卷积网络。正如其名所示,它采用了带有跳跃连接的残差块结构,即使网络深度较大,也能提高其可优化性。

SRResNet 可以作为独立网络进行训练和使用,并且如您即将看到的那样,它为 SRGAN 提供了一个 很好的基准模型——既可用于比较,也可用于初始化。

SRResNet 的架构

SRResNet 由以下操作组成:

  • 首先,将低分辨率图像与一个 $9\times9$ 大小、步幅为 1 的卷积核进行卷积,生成与原图分辨率相同但通道数为 64 的特征图。随后应用参数化 ReLU(PReLU)激活函数。

  • 接着,该特征图会依次通过 16 个 残差块,每个残差块包含两个 $3\times3$ 卷积层(步幅均为 1)、批归一化和 PReLU 激活函数,以及第二个类似的卷积层和第二次批归一化。在每一层卷积中,特征图的分辨率和通道数都保持不变。

  • 经过一系列残差块处理后的结果,再经过一个 $3\times3$ 卷积层(步幅为 1)和批归一化处理,分辨率和通道数同样保持不变。除了每个残差块内部的跳跃连接之外,还有一个跨越所有残差块及该卷积层的更大规模的跳跃连接。

  • 然后,通过 2 个 亚像素卷积块,每次将图像尺寸放大 2 倍(之后接 PReLU 激活),最终实现 4 倍的上采样。同时,通道数也保持不变。

  • 最后,在更高分辨率下,再使用一个 $9\times9$ 大小、步幅为 1 的卷积层进行卷积,并通过 Tanh 激活函数输出 超分辨率图像,其 RGB 通道值范围为 $[-1, 1]$。

如果您对上述某些具体数值感到疑惑,请不必担心。通常情况下,这些数值很可能是作者及其论文中引用的其他研究工作根据经验或便利性而设定的。

SRResNet 的更新过程

与任何神经网络一样,SRResNet 的训练也是通过对其参数的一系列更新来完成的。那么,这样的更新具体包括哪些内容呢?

我们的训练数据将由高分辨率(真实)图像及其对应的低分辨率版本组成,后者是通过对高分辨率图像进行 4 倍双三次插值下采样得到的。

在前向传播过程中,SRResNet 会生成一张 分辨率是输入低分辨率图像 4 倍的超分辨率图像

我们使用 均方误差(MSE)作为损失函数,用来比较超分辨率图像与用于生成低分辨率图像的真实高分辨率图像。

选择最小化超分辨率图像与真实图像之间的 MSE,意味着我们会调整 SRResNet 的参数,使得当再次输入相同的低分辨率图像时,它能够 生成更接近原始高分辨率图像外观的超分辨率图像

MSE 损失属于一种 内容损失,因为它仅基于预测图像和目标图像的内容进行计算。

在本例中,我们关注的是它们在 RGB 空间 中的内容——这一点的重要性我们稍后会详细讨论。

超分辨率生成对抗网络(SRGAN)

SRGAN 由 生成器网络判别器网络 组成。

生成器的目标是学习如何以足够逼真的方式进行超分辨率重建,使得专门用于识别此类人工生成痕迹的判别器无法再可靠地区分真实图像和生成图像。

这两部分网络是 同时进行训练的

生成器不仅像 SRResNet 那样通过最小化内容损失来进行学习,还会“窃听”判别器的工作机制。

换句话说,我们就是潜伏在判别器办公室里的“内鬼”!通过让生成器获取判别器在反向传播其输出时所产生的梯度信息,生成器可以调整自身的参数,从而改变判别器的输出结果,使其对自己有利。

随着生成器生成的高分辨率图像越来越逼真,我们也会用这些图像来训练判别器,不断提升其辨别能力。

生成器的架构

从架构上看,生成器与 SRResNet 完全相同。毕竟它们的功能是一样的。这也使得我们可以利用已经训练好的 SRResNet 来初始化生成器,从而获得巨大的优势。

判别器的架构

正如你所料,判别器是一个卷积网络,其功能是作为一个 二分类图像分类器

它的架构由以下步骤构成:

  • 将高分辨率图像(无论是自然图像还是人工图像)与一个 $9\times9$ 大小、步幅为 1 的卷积核进行卷积,生成与原图分辨率相同但通道数为 64 的特征图。随后应用 Leaky ReLU 激活函数。

  • 接着,该特征图会依次经过 7 个 卷积块,每个卷积块包含一个 $3\times3$ 卷积层、批归一化和 Leaky ReLU 激活函数。其中,偶数编号的卷积块会使通道数翻倍;奇数编号的卷积块则通过步幅为 2 的卷积操作使特征图尺寸减半。

  • 经过这一系列卷积块处理后的结果会被展平,并通过线性变换转化为一个 1024 维的向量,随后再次应用 Leaky ReLU 激活函数。

  • 最后,再经过一次线性变换得到一个 logits 值,通过 Sigmoid 激活函数将其转换为概率分数,从而反映出 输入图像为自然(真实)图像的概率

交替训练

首先,让我们来描述一下生成器和判别器是如何相互配合进行训练的。我们应该先训练哪一个呢?

其实,两者并不会一方完全训练好后再开始另一方的训练——它们是 同时进行训练的

通常来说,任何 GAN 都是以 交替方式进行训练的,即生成器和判别器会轮流进行短时间的训练。

在这篇论文中,每个子网络只更新一次,然后就切换到另一个网络。

在其他 GAN 实现中,你可能会发现每更新一次生成器,就会有 $k$ 次更新判别器的过程,其中 $k$ 是一个可以根据最佳效果进行调整的超参数。不过,很多时候 $k$ 的值就是 1。

判别器的更新

在讨论生成器之前,先了解判别器的更新方式会更有帮助。这里并没有什么意外——一切都如你所料。

由于判别器需要学会区分真实的高分辨率图像(“黄金”图像)和由生成器生成的超分辨率图像,因此在训练过程中,它会同时接收到“黄金”图像和超分辨率图像,并附带相应的标签($HR$ 表示真实图像,$SR$ 表示生成图像)。

例如,在前向传播中,判别器会接收一张真实的高分辨率图像,并输出一个概率分数 $P_{HR}$,表示该图像是自然生成的概率

我们希望判别器能够正确地将其识别为“黄金”图像,并且 $P_{HR}$ 尽可能高。为此,我们会使用正确的标签($HR$)来最小化二元交叉熵损失

选择最小化这一损失,将调整判别器的参数,使得当再次输入这张“黄金”高分辨率图像时,它会预测出更高的 $P_{HR}$,即认为该图像是自然生成的概率更高

同样地,在前向传播中,判别器还会接收到由生成器根据原始高分辨率图像的下采样低分辨率版本生成的超分辨率图像,判别器会输出一个概率分数 $P_{HR}$,表示该图像是自然生成的概率

我们希望判别器能够正确地将其识别为超分辨率图像,并且 $P_{HR}$ 尽可能低。因此,我们会使用正确的标签($SR$)来最小化二元交叉熵损失

选择最小化这一损失,将调整判别器的参数,使得当再次输入这张超分辨率图像时,它会预测出更低的 $P_{HR}$,即认为该图像是自然生成的概率更低

综上所述,判别器的训练过程相当直接,与训练任何图像分类器的方式并无不同。

接下来,我们来看看生成器的更新内容。

更好的内容损失

在 SRResNet 中使用的基于均方误差(MSE)的 RGB 空间内容损失,是图像生成领域中常用的手段。

然而,它也存在一些缺点——它会导致生成的图像过于平滑,缺乏实现照片级逼真度所需的精细细节。你可能已经在本教程中的多个示例中观察到了 SRResNet 的这一问题。原因也很容易理解。

在对低分辨率图像或区域进行超分辨率处理时,往往会有多种合理的高分辨率结果。换句话说,低分辨率图像中的一个小模糊区域,可以对应于许多不同的高分辨率区域,而每一种都可以被视为有效的结果。

举个例子,假设低分辨率区域需要在高分辨率的 RGB 空间中以特定间距生成带有蓝色斜线的图案。那么这些斜线的确切位置就有多种可能性。

其中任意一种都可以被认为是令人满意的结果。事实上,真实的高分辨率图像中确实会包含其中之一。

但是,像 SRResNet 这样的网络如果使用 RGB 空间的内容损失进行训练,就会非常不愿意生成这样的结果。相反,它会选择生成一种本质上是所有这些精细高分辨率可能性的平均值。正如你所想象的那样,这种平均后的结果几乎没有任何细节,因为所有的细节都被平均掉了!不过,这种平均结果却是一种“安全”的预测,因为训练时使用的“真实”或“地面真值”图像可能是这几种可能性中的任意一种,而如果生成其他任何一种有效结果,则会导致非常高的 MSE。

换言之,正是由于无法从低分辨率图像准确推断出“地面真值”图像中精确的 RGB 像素值,网络才会避免创造性地生成任何等效的图案,因为这样不仅面临很高的 MSE 风险,而且几乎不可能偶然生成与“地面真值”完全一致的像素。相反,一个过于平滑的“平均”预测通常会具有更低的 MSE!

在模型看来——请记住,模型是通过 RGB 空间的内容损失来“观察”图像的——这些众多的有效可能性其实并不等价。唯一有效的预测就是生成“地面真值”的 RGB 像素,而这些像素又是无法准确知道的。为了解决这个问题,我们需要找到一种方法,让在我们眼中等价的多种可能性,在模型看来也同样等价。

有没有一种方法,可以忽略图像或区域中 RGB 像素的具体排列,而只关注其基本本质或意义呢?有! 训练用于图像分类的卷积神经网络正是这样做的——它们会生成图像或区域的“深层”表征,用来描述其本质特征。由此可以推断出:在 RGB 空间中逻辑上等价的图案,经过训练好的 CNN 处理后,会产生相似的表征。

这种新的“深层”表征空间非常适合用于计算内容损失!我们的超分辨率模型不再需要害怕发挥创造力——只要生成的图案在逻辑上合理、细节丰富,即使与“地面真值”的 RGB 图像不完全相同,也不会受到惩罚。

生成器的更新——第一部分

生成器更新的第一步涉及内容损失

如我们所知,在前向传播中,生成器会根据输入的低分辨率图像生成一张尺寸为原图 4 倍的超分辨率图像

鉴于上一节中提到的原因,我们将不再使用 RGB 空间中的 MSE 作为内容损失,来比较生成的超分辨率图像与用于生成低分辨率图像的原始“黄金”高分辨率图像。

相反,我们会将这两张图像都输入到一个训练好的 CNN 中,具体来说是在 ImageNet 分类任务上预训练过的 VGG19 网络。这个网络被截断至第 5 个最大池化层之后的第 4 层卷积层

然后,我们将在 VGG 空间中使用基于 MSE 的内容损失,间接比较超分辨率图像与原始“黄金”高分辨率图像。

选择在 VGG 特征空间中最小化超分辨率图像与真实高分辨率图像之间的均方误差,意味着我们将以这样的方式调整生成器的参数:当再次输入相同的低分辨率图像时,生成器会生成一张在外观上更接近原始高分辨率版本的超分辨率图像——因为其在 VGG 特征空间中的表示也更加接近,而不会像 SRResNet 那样过度平滑或显得不真实。

生成器更新——第二部分

没有对抗训练的 GAN 算什么?答案是:它就不是 GAN。

内容损失只是生成器更新的一个组成部分。尽管使用 VGG 特征空间而非 RGB 空间确实能带来改进,但相较于 SRResNet,使生成器实现照片级逼真超分辨率效果的最大推动力仍然很可能是对抗损失

在此步骤中,我们将生成的超分辨率图像输入到当前状态下的判别器中,以获得一个表示该图像为“自然图像”的概率分数 $P_{HR}$

显然,生成器希望判别器无法识别出这并非自然图像,并使 $P_{HR}$ 尽可能高。那么,我们该如何更新生成器以提高 $P_{HR}$ 呢?请注意,在这一步中我们的目标仅是训练生成器——判别器的权重保持冻结。

因此,我们**将我们期望的标签(即“自然图像”)——尽管这个标签是错误的或具有误导性——**提供给二元交叉熵损失函数,并利用由此产生的梯度信息来更新生成器的权重!

选择以期望的但错误的标签(“自然图像”)来最小化二元交叉熵损失,意味着我们将调整生成器的参数,使得当再次输入低分辨率图像时,生成器会生成一张在外观和特征上更接近原始高分辨率版本的超分辨率图像,从而让判别器更有可能将其判定为自然图像

换言之,通过这种损失函数的设计,我们利用的是判别器中的梯度信息——即判别器输出 $P_{HR}$ 如何响应判别器自身参数的变化——而不是直接用来更新判别器自身的参数,而是通过反向传播获取生成器中的梯度信息——即判别器输出 $P_{HR}$ 如何响应生成器参数的变化——进而对生成器进行必要的调整!

在教程的之前部分,我们已经看到,可以通过冻结子网络 $N-n$ 的参数,只更新较大网络 $N$ 中的子网络 $n$ 来最小化损失并逐步逼近期望的输出。这里我们同样采用了类似的做法:生成器和判别器共同构成了一个“超网络”$N$,而我们只更新其中的生成器 $n$。诚然,如果同时更新判别器 $N-n$,损失可能会进一步降低,但这样做会直接削弱判别器的鉴别能力,反而得不偿失。

感知损失

由于生成器同时从两种类型的损失——内容损失和对抗损失——中学习,我们可以将它们按权重平均结合起来,形成论文作者所称的感知损失

这种感知损失极大地提升了 SRResNet 的性能,使生成器能够生成更加逼真、细节丰富的图像,这一点也在论文中的人体实验研究中得到了证实!

实现

以下各节简要描述了实现过程。

这些内容旨在提供一些背景信息,但具体的细节最好直接参考代码,因为代码中有非常详尽的注释。

数据集

描述

虽然论文的作者是在 ImageNet 数据集中一个包含 35 万张图像的子集上训练模型的,但我只使用了大约 12 万张 COCO 图像。这些图像更容易获取。

与论文一致,我们会在 Set5、Set14 和 BSD100 数据集上测试训练好的模型,这些数据集是超分辨率任务中常用的基准测试集。

下载

你需要下载 MSCOCO '14 的训练集(13GB)验证集(6GB)图像。

Set5、Set14 和 BSD100 测试数据集的下载链接可以在这里找到:https://github.com/XPixelGroup/BasicSR/blob/master/docs/DatasetPreparation.md#common-image-sr-datasets。在 Google Drive 的链接中,进入 Image Super-Resolution/Classical 文件夹。请注意,在 Set5 和 Set14 的压缩包中,你会看到多个文件夹——你需要的图像位于 original 文件夹中。

请将图像整理到五个独立的文件夹中:train2014val2014 文件夹分别存放训练图像,而 BSDS100Set5Set14 文件夹则用于存放测试图像。

模型输入与目标

模型共有四类输入和目标。所有输入和目标图像均由 RGB 通道组成,且处于 RGB 颜色空间,除非另有说明。

高分辨率(HR)图像

高分辨率图像为训练图像中随机裁剪的 $96\times96$ 大小的图像块。HR 图像用作 SRResNet 和 SRGAN 生成器的目标,同时也作为 SRGAN 判别器的输入。

当 HR 图像用作 SRResNet 的目标时,我们会将其像素值归一化至 $[-1, 1]$ 范围,因为论文中 MSE 损失正是在此范围内计算的。相应地,超分辨率(SR)图像也必须以 $[-1, 1]$ 范围生成。

当 HR 图像用作 SRGAN 生成器的目标时,我们将使用 ImageNet 数据的均值和标准差对其进行归一化,相关参数如下所示:此处 可查阅。这是因为 HR 图像会输入到经过截断的、预训练的 ImageNet VGG19 网络中,用于在 VGG 特征空间中计算 MSE。

mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]

当 HR 图像用作 SRGAN 判别器的输入时,同样需要进行上述归一化处理。因此,判别器接收的输入也必须是经过 ImageNet 归一化的图像。

PyTorch 使用 $NCHW$ 格式,即通道维度 ($C$) 位于尺寸维度之前。

因此,HR 图像是形状为 $N\times3\times96\times96$ 的 Float 张量,其中 $N$ 表示批次大小,像素值要么位于 $[-1, 1]$ 范围内,要么已按 ImageNet 标准归一化。

低分辨率(LR)图像

LR 图像是通过对 HR 图像进行 4 倍双三次下采样得到的。LR 图像是 SRResNet 和 SRGAN 生成器的输入。

根据所使用的下采样库不同,我们可能需要在下采样前使用高斯模糊作为低通滤波器来消除混叠效应(即防止 混叠现象)。我们最终采用的 Pillow 库中的 resize 函数已经内置了抗混叠措施。

论文中将 LR 图像缩放到 $[0, 1]$ 范围,但我们选择使用 ImageNet 数据的均值和标准差对其进行归一化。因此,我们的 SRResNet 和 SRGAN 生成器的输入始终需要按照 ImageNet 标准归一化。

综上所述,LR 图像是形状为 $N\times3\times16\times16$ 的 Float 张量,其中 $N$ 表示批次大小,像素值始终遵循 ImageNet 归一化标准。

超分辨率(SR)图像

超分辨率图像为 LR 图像经智能上采样后的结果。SR 图像是 SRResNet 和 SRGAN 生成器的输出,用于与目标 HR 图像进行比较,并作为 SRGAN 判别器的输入。

在训练 SRResNet 时,内容损失是基于 $[-1, 1]$ 范围内的 RGB 值计算的。因此,SRResNet 生成的 SR 图像也处于同一范围,这通过最后一层的 $\tanh$ 激活函数实现。

由于 SRGAN 生成器与 SRResNet 具有相同的架构,并且初始权重来自训练好的 SRResNet,因此生成器的输出也将保持在 $[-1, 1]$ 范围内。

然而,在训练 SRGAN 生成器时,内容损失是在 VGG 特征空间中计算的,因此其生成的 SR 图像需要从 $[-1, 1]$ 范围转换为 ImageNet 归一化后的空间,以便输入到截断的 VGG19 网络中。这一点与 HR 图像的处理方式相同。

综上所述,SR 图像是形状为 $N\times3\times96\times96$ 的 Float 张量,其中 $N$ 表示批次大小,像素值始终位于 $[-1, 1]$ 范围内。

判别器标签

由于判别器是一个二分类图像分类器,其训练数据同时包含每张 LR 图像对应的 SR 和 HR 对应图像,因此标签分别为 1 和 0,分别代表 HR(自然来源)和 SR(人工生成,来自生成器)。

判别器标签在训练过程中手动构建:

  • 当使用对抗损失训练生成器时,构造一个 形状为 $N$ 的 Long 张量,其中 $N$ 为批次大小,全部填充为 1(HR)。
  • 当使用 HR 和 SR 图像分别训练判别器时,构造一个 形状为 $2N$ 的 Long 张量,其中 $N$ 为批次大小,前 $N$ 个元素为 1(HR),后 $N$ 个元素为 0(SR)。

数据流水线

数据被划分为训练集测试集。没有验证集——我们将直接使用论文中描述的超参数。

解析原始数据

参见utils.py中的create_data_lists()函数。

该函数会解析下载的数据,并保存以下文件:

  • train_images.json:包含所有训练图像的文件路径(即train2014val2014文件夹中的图像)的列表,这些图像的尺寸均大于指定的最小值。

  • Set5_test_images.jsonSet14_test_images.jsonBSDS100_test_images.json:分别包含Set5Set14BSDS100文件夹中所有测试图像的文件路径,且这些图像的尺寸均大于指定的最小值。

图像转换

参见utils.py中的convert_image()函数。

我们将对RGB空间中的像素值使用多种归一化、缩放和表示方法:

  • 作为Pillow (PIL) 图像:即由Python的Pillow库读取的图像。RGB值以$[0, 255]$范围内的整数形式存储,这也是从磁盘读取图像时的格式。

  • 作为**$[0, 1]$范围内的浮点值**,这在不同表示之间转换时用作中间表示。

  • 作为**$[-1, 1]$范围内的浮点值**,这是高分辨率图像的表示方式,也是生成超分辨率图像时使用的格式,并且在SRResNet中,内容损失正是基于这种表示来计算的。

  • 作为ImageNet 归一化后的值,这是低分辨率、超分辨率和高分辨率图像输入到任何模型(SRResNet、生成器、判别器或截断的VGG19)时所采用的格式。

  • 作为y通道,即YCbCr色彩空间中的亮度通道Y,用于计算峰值信噪比(PSNR)和结构相似性指数(SSIM)等评估指标。

从一种形式到另一种形式的转换,都是通过先转换为$[0, 1]$范围内的值来实现的。

图像变换

参见utils.py中的ImageTransforms类。

在训练过程中,高分辨率图像是从训练图像中随机裁剪出的固定大小的$96\times96$区域——每张图像每个epoch随机裁剪一次。

在评估过程中,我们则对每张测试图像进行尽可能大的中心裁剪,使得裁剪后的图像尺寸能够被缩放因子整除。

低分辨率图像则是通过对高分辨率图像进行4倍双三次下采样得到的。 根据所使用的下采样库的不同,我们可能需要在下采样之前使用高斯模糊作为低通滤波器来消除混叠现象(即防止混叠)。而我们最终使用的Pillow库的resize函数已经内置了抗混叠措施。

在训练SRResNet时,高分辨率图像会被转换为$[-1, 1]$范围内的值;而在训练SRGAN时,则会转换为ImageNet归一化的值。低分辨率图像始终是ImageNet归一化的。

PyTorch 数据集

参见datasets.py中的SRDataset类。

这是一个PyTorch Dataset的子类,用于定义我们的训练集和测试集。

它需要定义一个__len__方法,返回数据集的大小;以及一个__getitem__方法,根据上述图像变换步骤,在训练或测试JSON文件中找到第$i$张图像对应的低分辨率和高分辨率图像对并返回。

PyTorch 数据加载器

上述的SRDataset将由train_srresnet.pytrain_srgan.pyeval.py中的PyTorch DataLoader使用,以创建并为模型提供用于训练或评估的数据批次

卷积块

参见models.py中的ConvolutionalBlock类。

这是一个自定义层,由二维卷积、可选的批量归一化以及可选的TanhPReLULeaky ReLU 激活函数组成,用作SRResNet、生成器和判别器网络中的基本构建模块。

超像素卷积块

参见models.py中的SubPixelConvolutionalBlock类。

这是一个自定义层,由一个将通道数扩展到$s^2n$的二维卷积组成,其中$s$为缩放因子,$n$为上采样后图像所需的输出通道数,随后接一个PyTorch 的nn.PixelShuffle(),用于在SRResNet和生成器网络中执行上采样操作。

残差块

参见models.py中的ResidualBlock类。

这是一个由两个卷积块组成的自定义层。第一个卷积块使用PReLU激活,第二个卷积块则不进行激活。两个卷积块都会进行批量归一化。此外,两个卷积块之间还有一条残差(跳跃)连接

SRResNet

参见models.py中的SRResNet类。

该类构建了SRResNet,按照文中描述,使用卷积块、残差块和超像素卷积块。

生成器

参见models.py中的Generator类。

SRGAN的生成器具有与SRResNet相同的架构,按照文中描述,因此无需重新构建。

判别器

请参阅 models.py 中的 Discriminator

该模块构建了 SRGAN 的判别器,如文档所述,使用卷积块和线性层实现。

一个可选的 nn.AdaptiveAvgPool2d 在将特征图展平并传递给线性层之前,会保持图像尺寸固定——这仅在训练时未使用默认的 $96\times96$ 高分辨率/超分辨率图像尺寸时才需要。

截断的 VGG19

请参阅 models.py 中的 TruncatedVGG19

该模块截断了一个在 ImageNet 上预训练的 VGG19 网络,该网络可在 torchvision 中找到,使其输出为论文中描述的“VGG19 网络中第 $i$ 个最大池化层之前的第 $j$ 个卷积层(激活后)所得到的特征图”。

正如作者所做的那样,我们将使用 $i=5$ 和 $j=4$。

训练

在开始之前,请确保已保存用于训练和评估的必要数据文件。为此,在指向训练数据文件夹 train2014val2014 以及测试数据文件夹 Set5Set14BSDS100 后,运行 create_data_lists.py 的内容——前提是您已经[下载了数据](https://github.com/sgrvinod/a-PyTorch-Tutorial-to-Super-Resolution#download):

python create_data_lists.py

训练 SRResNet

请参阅 train_srresnet.py

SRResNet 的参数(以及训练设置)位于文件开头,因此您可以根据需要轻松查看或修改它们。

要从头开始训练 SRResNet,请运行此文件:

python train_srresnet.py

若要从检查点继续训练,请在代码开头通过 checkpoint 参数指定相应的检查点文件。

训练 SRGAN

请参阅 train_srgan.py

只有在训练完 SRResNet 后才能训练 SRGAN,因为 SRGAN 的生成器会使用已训练好的 SRResNet 检查点进行初始化。

模型的参数(以及训练设置)位于文件开头,因此您可以根据需要轻松查看或修改它们。

要从头开始训练 SRGAN,请运行此文件:

python train_srgan.py

若要从检查点继续训练,请在代码开头通过 checkpoint 参数指定相应的检查点文件。

备注

我们使用了论文中推荐的超参数。

对于 SRResNet,我们使用 Adam 优化器,学习率为 $10^{-4}$,训练 $10^6$ 次迭代,批量大小为 $16$。

SRGAN 同样使用 Adam 优化器,前 $10^5$ 次迭代的学习率为 $10^{-4}$,随后的额外 $10^5$ 次迭代学习率为 $10^{-5}$,批量大小仍为 $16$。

我是在单块 RTX 2080Ti GPU 上进行训练的。

模型检查点

您可以从这里下载我的预训练模型。

请注意,这些检查点应直接使用 PyTorch 加载以进行评估或推理——详情见下文。

评估

请参阅 eval.py

要评估选定的模型,请运行该文件:

python eval.py

这将计算所选模型在三个测试数据集上的峰值信噪比(PSNR)和结构相似性指数(SSIM)评估指标。

以下是我的结果(括号内为论文中的结果):

PSNR SSIM PSNR SSIM PSNR SSIM
SRResNet 31.927 (32.05) 0.902 (0.9019) 28.588 (28.49) 0.799 (0.8184) 27.587 (27.58) 0.756 (0.7620)
SRGAN 29.719 (29.40) 0.859 (0.8472) 26.509 (26.02) 0.729 (0.7397) 25.531 (25.16) 0.678 (0.6688)
Set5 Set5 Set14 Set14 BSD100 BSD100

嗯,需要打个大大的折扣。论文反复强调,PSNR 和 SSIM 并不能真正反映超分辨率图像的质量。相比之下,SRResNet 生成的图像虽然更不真实、过于平滑,但其 PSNR 和 SSIM 得分却更高。这也是为什么论文作者进行了主观评分测试,而这种测试显然超出了我们的能力范围。

推理

请参阅 super_resolve.py

请务必在代码开头加载训练好的 SRResNet 和 SRGAN 检查点。

使用您希望处理的高分辨率图像调用 visualize_sr() 函数,即可以网格形式可视化结果,包括原始高分辨率图像、双三次插值上采样后的图像(作为该图像低分辨率版本的近似)、由 SRResNet 超分辨率后的图像以及由 SRGAN 超分辨率后的图像。

本教程开头的示例就是使用该函数生成的。需要注意的是,该函数并不会对输入图像进行上采样,而是先下采样再进行超分辨率,以便与原始高分辨率图像进行对比。如果您希望直接对提供的图像进行上采样或其他操作,就需要修改代码。

请注意输入图像的尺寸。 该函数提供了一个 halve 参数,允许您创建一个尺寸减半的新高分辨率图像。如果原始高分辨率图像的尺寸超过了您的屏幕分辨率,导致您无法体验 4 倍的超分辨率效果,那么这个功能就非常有用。例如,对于 2160p 的高分辨率图像,其低分辨率版本将是 540p(2160p/4)。而在 1080p 的屏幕上,您实际上看到的是 540p 的低分辨率图像(以双三次插值上采样的形式)与 1080p 的超分辨率/高分辨率图像之间的对比,因为您的 1080p 屏幕只能以 1080p 的分辨率显示 2160p 的超分辨率/高分辨率图像。这仅仅是视觉上的 2 倍缩放效果。如果将 halve 设置为 True,那么高分辨率/超分辨率图像将变为 1080p,而低分辨率图像则变为 270p。

大尺寸示例

以下示例中的图像(来自《赛博朋克2077》[https://www.cyberpunk.net/in/en/])非常大。如果您是在 1080p 分辨率的屏幕上查看此页面,那么您需要 点击图片以查看其实际尺寸,才能有效地观察到 4 倍超分辨率的效果。

点击图片以全尺寸查看。


点击图片以全尺寸查看。


点击图片以全尺寸查看。


点击图片以全尺寸查看。


点击图片以全尺寸查看。


点击图片以全尺寸查看。


常见问题解答

我将根据本仓库 Issues 标签下常见的提问,逐步完善本节内容。

为什么生成器输出的超分辨率图像要经过判别器两次?为什么不直接复用第一次经过判别器时的输出呢?

是的,我们确实会对超分辨率图像进行两次判别:

  • 在训练生成器时,我们将超分辨率图像输入判别器,并利用判别器的输出与错误但期望的 $HR$ 标签一起计算对抗损失函数。

  • 在训练判别器时,我们同样将超分辨率图像输入判别器,但这次会使用判别器的输出来计算与正确且期望的 $SR$ 标签之间的二元交叉熵损失。

在第一次过程中,我们的目标是通过损失函数对生成器参数 $\theta_G$ 的梯度来更新 $\theta_G$;而此时生成器确实是计算图的一部分,我们会在该计算图上执行反向传播。

而在第二次过程中,我们的目标仅是更新判别器的参数 $\theta_D$,这些参数在反向传播的方向上位于 $\theta_G$ 的上游。

换句话说,在训练判别器时,并不需要计算损失函数对 $\theta_G$ 的梯度,生成器也无需参与计算图!如果让生成器继续参与计算图,将会增加不必要的开销,因为反向传播本身是非常耗时的。因此,在第二次前向传播中,我们会将超分辨率图像从计算图中分离出来,使其成为一个独立变量,不再保留任何关于生成它的计算图(即生成器)的记忆。

这就是为什么我们要进行两次前向传播:一次是将超分辨率图像保留在完整的 SRGAN 计算图中,从而需要跨过生成器进行反向传播;另一次则是将超分辨率图像从生成器的计算图中分离出来,避免反向传播穿过生成器。显然,进行两次前向传播的成本远低于两次反向传播。

子像素卷积与转置卷积相比如何?

在我看来,两者非常相似,理论上应该能够达到相近的效果。

如果对于给定的上采样因子 $s$ 和子像素卷积使用的卷积核大小 $k$,转置卷积的卷积核大小为 $sk$,那么这两种方法在数学上是可以等价的。在这种情况下,它们的参数量也会相同:前者为 $ns^2 * i * k * k$,后者为 $n * i * sk * sk$。

不过,有一些研究表明,子像素卷积在某些方面确实更具优势,尽管我并不完全理解其中的原因。您可以参考这篇 论文、这个 仓库 以及这个 Reddit 帖子。也许原始的 论文 也能提供一些线索。

当然,数学上的等价性并不意味着它们在优化、学习能力或效率上完全一致。如果您了解子像素卷积为何能取得更好效果,请提交一个问题并告知我,我会将相关信息补充到本教程中。

常见问题

相似工具推荐

openclaw

OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你

349.3k|★★★☆☆|2周前
Agent开发框架图像

n8n

n8n 是一款面向技术团队的公平代码(fair-code)工作流自动化平台,旨在让用户在享受低代码快速构建便利的同时,保留编写自定义代码的灵活性。它主要解决了传统自动化工具要么过于封闭难以扩展、要么完全依赖手写代码效率低下的痛点,帮助用户轻松连接 400 多种应用与服务,实现复杂业务流程的自动化。 n8n 特别适合开发者、工程师以及具备一定技术背景的业务人员使用。其核心亮点在于“按需编码”:既可以通过直观的可视化界面拖拽节点搭建流程,也能随时插入 JavaScript 或 Python 代码、调用 npm 包来处理复杂逻辑。此外,n8n 原生集成了基于 LangChain 的 AI 能力,支持用户利用自有数据和模型构建智能体工作流。在部署方面,n8n 提供极高的自由度,支持完全自托管以保障数据隐私和控制权,也提供云端服务选项。凭借活跃的社区生态和数百个现成模板,n8n 让构建强大且可控的自动化系统变得简单高效。

184.7k|★★☆☆☆|今天
数据工具开发框架Agent

stable-diffusion-webui

stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。

162.1k|★★★☆☆|2周前
开发框架图像Agent

everything-claude-code

everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上

161.1k|★★☆☆☆|今天
开发框架Agent语言模型

ComfyUI

ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。

109.2k|★★☆☆☆|昨天
开发框架图像Agent

gemini-cli

gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。

100.8k|★★☆☆☆|1周前
插件Agent图像