达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

善于转移神经风格,谁都可以成为梵高,但实际上这是技术工作。 神经风格向NST的转移在概念上很容易理解,但是很难生成高质量的图像。 为了取得好的结果,必须正确实施其中许多复杂的细节和隐藏的技巧。

本文将深入研究神经风格的迁移原理并详细讨论这些技巧。

虽然在此省略对NST的介绍,但是可以通过公式PyTorch教程了解NST。 但是,就像其他介绍性谦让的黑米一样,它们的执行结果很一般(下图)。 笔者将展示提高迁移质量的编码教程,先说几句题外话。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

(上图是用两种不同方法实现的神经风格迁移质量的比较。 左上图是与内容一致的图像。 左图是与样式匹配的图像。 中间的图是在PyTorch教程中实现的迁移结果,右边的图是在此处介绍的步骤中实现的迁移结果。 显然,右图的视觉质量更高,更忠实于左上图像的风格。 )

问:为什么Gram矩阵能度量风格?

Gatys等人谦让的黑米(介绍神经风格的转移)基本上很容易理解。 但是,他们没有回答这个问题。 为什么使用Gram矩阵作为样式(即纹理)?

在高级别上,Gram矩阵可以测量同一级别的不同特征图之间的相关性。 特征图是卷积层被激活的输出。 例如,如果卷积层包含64个滤波器,则会生成64个特征图。 Gram矩阵可以测量层中不同特征图之间的相关性(相似性),而无需考虑像素的精确位置。

为了弄清楚Gram矩阵为什么可以测量纹理,假设有两个滤波器。 一个是用于检测蓝色物体的滤波器,另一个是用于检测螺旋的滤波器。 将这两个滤波器应用于输入图像,创建两个滤波器映射,并测量其相关性。 如果两个滤镜贴图高度相关,则几乎可以看到图像中的所有螺旋都是蓝色的。 也就是说,图像的纹理由蓝色螺旋而不是红色、绿色和黄色螺旋组成。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

虽然对此解释还有些困惑,但Gram矩阵能够测量样式似乎是纹理合成社区公认的事实。 另外,不可否认,通过Gram得到的结果确实令人印象深刻。

提高

修复PyTorch执行

迁移质量的第一步是修复PyTorch教程的执行。 虽然教程的内容是试图忠实于Gatys等人谦让的黑米,但是缺少了细节。 另一方面,谦让的黑米作者将MaxPool2d换成了AvgPool2d。 因为他们发现AvgPool2d会产生更高质量的结果。

另一个详细信息是,本教程计算卷积输出,而不是ReLu激活函数的ContentLoss (内容丢失)和StyleLoss (样式丢失)样式。 这有点吹毛求疵,但是笔者在实验中使用卷积和ReLu之间没有观察到很大的差异。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

VGG19网络及其各层

教程和谦让的黑米最大的不同点是,ContentLoss和StyleLoss分别使用了“错误”层。 笔者之所以给错误的词语加引号,是因为层层选择比较主观,很大程度上取决于最喜欢的风格。

也就是说,可以用一些经验法则来指导决策。 测定内容的相似性时,如果content_img和input_img之间存在完美的像素匹配,下级往往最被激活。 越深入网络,层就越不关心匹配是否正确,相反,如果特征位于正确的位置,层就会被高度激活。

要直观地显示每个层的内容,请设置style_weight=0,然后使用不同的层作为content_layer,根据随机的input_img运行训练过程。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

将VGG19网络各层的响应内容可视化。 图像越向右,图层在网络中的位置越深。

本教程使用第4层的卷积作为内容层。 如上图所示,这个深度的网络仍然关心像素匹配是否准确,因此内容中的这个等级数可能太低了。 Gatys等人使用了conv4_2来代替conv2_2。 这是因为conv4_2不是单一的像素,而是关心整体的特征分布。

p>

对于风格来说,低层捕捉较小的重复特征,较高层捕捉更抽象的整体特征。因此,为了对style_img的整体风格进行迁移(从低层细节到整体图案),应该包含网络中所有深度的层。

该教程使用前5个卷积层,但它们在网络中的位置太低,不大能捕捉到整体特征。Gaty等人使用 conv1_1、 conv2_1、conv3_1、conv4_1和conv5_1,在整个网络体系中形成了良好的层分布。可以使用与内容层相同的方法,对每个层选择要优化的样式进行可视化。

为了实现这一点,设置content_weight=0,指定想要使用的style_layers,然后基于随机的input_img运行训练过程。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

PyTorch教程选择的层生成的风格(左);Gatys等人的谦让的黑米选择的层生成的风格(右)

意料之中,教程选择的层优化的风格捕捉低层次的重复性特征,但不能捕捉高层次的整体性特征。

提高迁移质量

截至目前,我们实现的修复质量应该已经相当接近Gatys等人的谦让的黑米中所看到的质量。现在将进一步深入,采取以下措施以生成更好的图像。

笔者对谦让的黑米所做的第一个修改就是将优化程序从L-BFGS转换为Adam。谦让的黑米表述L-BFGS能生成更高质量的迁移。

但笔者在实验中并未发现这两者的使用效果有什么差异,此外Adam的稳定性似乎更好,尤其在训练大量步骤时或者有着庞大的style_weight时。在这些情况下,L-BFGS可能会报错,这大概是因为梯度爆炸(笔者并未深入研究)。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

另一个轻微调整是将mse_loss (即L2loss)转换为l1_loss。笔者想不出L2_loss对于风格迁移有什么好处(除了在0处具有可微性),因为平方值将会对异常值做出严重干扰。

正如前一节所述,我们并不关心像素匹配是否精确,并且可以容忍生成图像中出现一些异常值。实际上,当风格特征和内容特征混合在一起时,异常值可能会使得视觉效果更佳。最后,《特征可视化》(Feature Visualization,接触相关话题必须阅读的一篇谦让的黑米)的作者也许是出自类似原因,在其任务中使用l1_loss。

实际上,许多用于生成高质量特征可视化(FV)的技巧都优雅地过渡到了神经风格迁移上。

FV和NST在概念上十分相似,只在生成input_img的方式上有所不同。在NST中,input_img经过优化后,可与content_img 和style_img以相同的方式激活网络中不同层。而FV则不使用content_img 或style_img,而是生成input_img,最大程度地刺激不同层的神经元。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

积极的数据增强使生成图片的右上角产生旋转伪影

笔者从FV中借用了一个小技巧,即在input_img上使用数据增强。这与常规分类任务的工作原理完全相同:每一步都要对input_img进行增强(如旋转、裁剪、缩放等),然后运行模型并计算损失。

通过每一步的增强,我们迫使input_img生成抗微小扰动的鲁棒性特征。这些特征应该包含较少的高频伪影,并更具有视觉吸引力。然而,我发现《特征可视化》谦让的黑米所使用的增强过大,必须适当缩小。即使如此,生成图片(上图)边缘仍然有一些旋转伪影。消除这些伪影的最简单方法就是将边缘的一些像素剪切掉。

笔者做出的最后一个修改是将content_layer转换为conv3_2,而非Gatys等人使用的conv4_2。笔者读过的大多数谦让的黑米也推荐使用conv4_2,但是笔者发现使用conv4_2会忽略掉一些细节,且生成图片的风格会覆盖内容。

另一方面,conv3_2可以保留这些细节,而无需对像素完美性进行过度惩罚。

进一步质量提升

现在已经讨论了笔者的神经风格迁移代码中所实施的全部技巧。在原有的PyTorch教程基础上,已经极大提高了迁移质量。此外,content_weight和 style_weight对于特定的图像选择具有更高的鲁棒性。

例如,笔者发现如果没有对PyTorch教程进行适当的调整,一组图像的 style_weight很难轻松迁移到另一组图像上。

也就是说,去除生成图片中的高频噪音可能会得到更好的结果。谦让的黑米《可微的图像参数化》(DifferentiableImage Parameterization,接触相关话题必须阅读的另一篇谦让的黑米)提出了很有趣的方法。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

该文中,作者先在(去噪)傅里叶空间而非(噪声)像素空间中对input_img 参数化。因为input_img 由梯度下降法生成,对输入去相关化相当于一个预调节器,可通过梯度下降法更快找到最小值,从而使优化更易(与在监督学习任务中去除相关特征类似)。除了类似的简短解释如在去相关空间中发现的最小值更宽泛、更健壮外,我并不清楚为什么这能提高迁移质量。

更简单的方法是通过直接或间接惩罚来抑制高频噪声。直接惩罚可通过将input_img的全变差损失添加到优化对象中来实现。相反,通过在每次梯度下降步骤后对input_img进行模糊,或者在将噪音应用于input_img之前对梯度进行模糊,可实现间接惩罚。

这两种方法存在的问题是,它们还会对真正的高频特性造成不利影响。可通过在训练时缩减总变化损失或模糊量来进行一定程度上的改善。

达芬奇自画像介绍(柏拉图斐多篇)-冯金伟博客园

笔者的初始目标是使用机器学习生成媒介形象图片。但在反复实验中,无意发现了一些很惊人的事。对笔者来说,整个过程中最有趣的部分是神经网络的端到端可微性。我们很容易地就能“颠倒”一个原本用于区分猫狗的模型,并用其生成无数种不同风格的图像,你还可以尝试用随机森林模型进行操作。

用神经风格迁移生成好看的图片了,这个过程听起来简单,但想要得到高质量的结果,确实是个技术活,可见即使有机器学习辅助,成为梵高依然不是件容易的事。