神经风格转化

深入到神经风格转换的领域。你就会发现尽管NST在概念上很容易理解,但要生成高质量图像却出奇地困难。为了获得良好的结果,必须正确实施许多复杂的细节和未提及的技巧。在本文中,我们将深入研究神经风格转换的知识,并详细研究这些技巧。
在网上有大量有关NST的扎实介绍,因此本篇文章不会花时间来巩固学习基础知识。如果您不知道NST是什么(或者想跟着本文一起学习),一个很好的入门方法是查看官方PyTorch教程。

本文的所有随附代码都可以在GitHub上找到。
两种不同实现的神经风格转换质量比较。(左下)要匹配其内容的图像。(左上)我们要匹配其样式的图像。(中)使用PyTorch教程实现的样式转换结果。(右)使用本文详细介绍的实现的样式转移结果。生成的图像在视觉上具有较高的质量,并且更加忠实地匹配样式图像的样式。
为什么Gram矩阵会衡量样式?
书中介绍的神经式转换是简单明了的。但是,一个尚未解决的问题是,为什么Gram是一种用自然的方式来表示样式的矩阵?
在较高的层次上,Gram矩阵可测量同一层中不同特征图之间的相关性。特征图只是卷积层的激活后输出。例如,如果一个卷积层有64个滤镜,它将输出64个特征图。然后,Gram矩阵可测量图层中每个特征图与每个其他特征图之间的相关性(相似性),而不必关心确切的像素位置。

为了说明为什么这是对纹理的合理衡量,假设我们有两个过滤器,一个过滤器检测蓝色物体,另一个检测螺旋体。我们可以将这些滤镜应用于输入图像,以生成2个滤镜图并测量其相关性。如果滤镜图高度相关,则图像中存在的任何螺旋形状几乎可以肯定是蓝色的。
尽管这种解释仍然让我有些不安,但正如本文所解释的那样,在Gram矩阵对应于样式的情况下,这是纹理合成领域中一个广为接受的事实。此外,我们不能否认使用Gram矩阵获得的结果是令人印象深刻的。
修复PyTorch实现
实施修复PyTorch教程的第一步是改善传输质量。一方面,论文作者用代替MaxPool2d,AvgPool2d因为他们发现可以产生更高质量的结果。另一个细节是本教程用于计算卷积的是ContentLoss和StyleLoss,而不是ReLU激活。这更像是一种无须有的替换,因为在实验中,并未发现使用卷积与ReLU之间有很大的差异。

VGG19网络及其层(源)
教程与论文之间最令人震惊的区别在于,“错误”层分别用于ContentLoss和StyleLoss。由于层的选择在很大程度上是主观的,并且在很大程度上取决于产生最令人愉悦的样式的方式。我们可以使用一些经验法则来做出最后的决定。在测量内容相似度时,当content_img和生成的像素之间存在像素完美匹配时,下层往往会激活得最高input_img。我们进入网络的深度越深,各层对精确匹配的关注就越少,而当要素通常位于正确的位置时,它们就会激活得更多。为了可视化每个层最关注的内容,我们可以style_weight=0随机设置和运行训练过程input_img使用不同的图层作为content_layer。

可视化VGG19网络的不同层响应什么内容。右侧更远的层在网络中更深。
教程使用第4卷积作为内容层。正如我们在上图中可以看到的那样,由于网络仍然关心在此深度精确匹配像素,因此该层可能太低而无法用于内容。请conv4_2改用,而不是单个像素,而是更多地关注整体特征的布置。
就样式而言,较低的层响应较小的重复特征,而较高的层捕获更抽象的全局特征。因此,为了将整个样式(style_img从低级细节转变为总体主题),我们应包括网络中各个深度的图层。本教程使用前5个卷积层,但是它们在网络中都相当低,并且不太可能捕获全局特征。Gatys等。使用conv1_1,conv2_1,conv3_1,conv4_1,和conv5_1,层的整个网络中的层次结构中的很好的分布。我们可以使用与内容相同的方法来可视化每个图层选择正在优化的样式。为此,我们设置content_weight=0,指定style_layers我们要使用的内容,并随机运行训练过程input_img。

(左)由PyTorch教程中选择的图层产生的样式。(右)由研究人员选择的图层产生的样式
正如预期的那样,由教程层优化的样式可以捕获低级的重复性功能,但是无法捕获高级的全局性功能。
提高传输质量
到目前为止,我们已经实施的修复程序应该使我们相当接近研究人员所见的质量。从这里开始,我们将更深入地研究如何采取进一步的步骤来生成更好的图像。
我从本文中更改的第一件事就是将优化器从切换L-BFGS为Adam。在这篇论文中,作者声称可以带来L-BFGS更高的质量转移,但是Adam在实验中使用时,我没有发现任何区别。此外,它Adam似乎更稳定,尤其是在训练大量步骤或使用大踏板进行训练时style_weight。在这些情况下,可能L-BFGS似乎NaN是由于梯度爆炸(尽管我对它的了解并不深)。
另一个较小的调整是将mse_loss(即L2损耗)切换为l1_loss。我想不出有充分的理由使用L2损失进行样式转移(除了0处的可微性),因为平方项会严重影响离群值。正如上一节所提到的,我们并不十分在乎精确匹配像素,而是可以容忍所生成图像中的一些离群值。确实,将样式和内容特征融合在一起,离群值甚至可能导致视觉效果更好。
实际上,用于生成高质量特征可视化的许多技巧可以优雅地转换为神经样式转换。实际上,FV和NST在概念上非常相似,只是它们的生成方式不同input_img。在NST中,input_img经过优化以与content_img和相同的方式激活网络中的不同层style_img。另一方面,FV不使用content_img和style_img而是生成一个input_img,最大程度地激发不同层的神经元。

由激进的数据扩充引起的生成图像右上角的旋转伪像。
使用数据增强input_img。这与常规分类任务的工作原理完全相同:在每个步骤中,我们都会对模型进行一些扩充input_img(例如旋转,裁剪,调整大小等),然后再对其进行遍历并计算损失。通过input_img在每个步骤中增加,我们强制input_img生成对较小扰动具有鲁棒性的特征。这些健壮的功能应包含较少的高频伪像,并且通常看起来更具视觉吸引力。“功能可视化”文章中使用的增强功能非常激进,因此必须适当缩小比例。即使这样,仍然在生成的图像的边缘周围形成一些旋转伪像,如上图。消除这些伪像的最简单方法是将图像裁剪几像素。
最后,我所做的最后修改是将切换content_layer为conv3_2而不是conv4_2Gatys等。
进一步提高质量
现在,我们已经讨论了在神经风格转换代码中实现的所有技巧。至此,我们已经在原始PyTorch教程的基础上大大提高了传输质量。此外,content_weight和style_weight对特定的图像选择更为强大。例如,在PyTorch教程中,我发现如果style_weight没有适当的调整,一组图像上的好图像不会轻易转移到另一组图像上。
结论
如果到此为止,您现在应该对使用Neural Style Transfer生成漂亮的图像有很多了解。虽然从概念上讲很简单,但要获得高质量的结果需要多加注意。我的最初目标是使用机器学习来生成中型个人资料图片。经过多次尝试和错误,我认为我偶然发现了一些看起来很惊人的东西。对我来说,整个过程中最令人兴奋的部分是神经网络的端到端可区分性。只需很少的努力,我们就可以“反转”最初训练用来区分猫和狗的模型,并使用它来生成无数种不同样式的图像。尝试使用随机森林进行操作。

你可能感兴趣的:(神经网络)