科技刀▲使用神经风格转移NST得到绚丽惊奇的图片

尽管神经风格转移(NeuralStyleTransfer,NST)在概念上很容易理解 , 但要生成高质量图像却十分的困难 。 为了获得良好的结果 , 必须正确应用许多复杂的细节和未提及的技巧 。 在本文中 , 我们将深入探讨神经风格转换 , 并详细研究这些技巧 。
科技刀▲使用神经风格转移NST得到绚丽惊奇的图片
文章图片
科技刀▲使用神经风格转移NST得到绚丽惊奇的图片
文章图片
科技刀▲使用神经风格转移NST得到绚丽惊奇的图片
文章图片
如果你不知道什么是NST , 一个很好的NST入门方法是查看官方的PyTorch教程https://pytorch.org/tutorials/advanced/neural_style_tutorial.html 。 很遗憾 , 与许多其他入门文章一样 , NST充其量最终也只能产生中等程度的结果(图1) 。 我们将在接下来的几节中更新教程代码以提高转变质量 。
科技刀▲使用神经风格转移NST得到绚丽惊奇的图片
文章图片
图1:两种不同实现的神经风格转换质量比较 。 (左下)要匹配其内容的图像 。 (左上)我们要匹配其样式的图像 。 (中)使用PyTorch教程实现的样式转换结果 。 (右)使用本文详细介绍的方法实现的样式转移结果 。 生成的图像在视觉上具有较高的质量 , 并且更加如实匹配样式图像的样式 。
旁白:为什么Gram矩阵会衡量样式?
Gatys等人的介绍神经风格转换的论文大部分是通俗易懂的 。 但是 , 一个尚未解决的问题是为什么Gram矩阵是一种自然的方式来表示样式(即纹理)?
在较高的层次上 , Gram矩阵可测量同一层中不同特征图之间的相关性 。 特征图只在卷积层激活后输出 。
例如 , 如果一个卷积层有64个滤镜 , 它将输出64个特征图 。 然后 , Gram矩阵可测量图层中每个特征图与每个其他特征图之间的相关性(相似性) , 而不需关心像素的确切位置 。 为了说明为什么这是对纹理进行合理衡量的原因 , 让我们假设有两个过滤器 , 一个滤波器检测蓝色物体 , 另一个检测螺旋体 。 我们可以将这些滤波器应用于输入图像 , 以生成2个图并测量其相关性 。 如果滤波图高度相关 , 则图像中存在的任何螺旋几乎可以肯定是蓝色的 。 这意味着图像的纹理由蓝色螺旋组成 , 而不是红色、绿色或黄色螺旋 。
尽管这种解释仍不足以完全说服我 , 但本文解释的Gram矩阵与样式相对应的方法 , 似乎为纹理合成社区广为接受 。 此外 , 我们不能否认使用Gram矩阵获得的结果非常有效 。
修复PyTorch实现
改善转移质量的第一步是修复PyTorch教程实施 。 本教程尽量忠实于Gatys等人的论文内容 , 但在借鉴中也遗漏了部分内容 。 一方面 , 论文的作者发现用AvgPool2d代替MaxPool2d可以产生更高质量的结果 。 另一个细节是本教程在卷积的输出上计算了ContentLoss和StyleLoss , 而不是ReLU激活 。 这更像是一种挑剔 , 因为在我们的实验中 , 我并未发现使用卷积与ReLU之间有很大的差异 。
科技刀▲使用神经风格转移NST得到绚丽惊奇的图片
文章图片
教程和论文之间最令人震惊的区别是 , ContentLoss和StyleLoss分别使用了“错误”的层 。 可能我引用称呼不当 , 因为层的选择在很大程度上是主观的 , 并且取决于产生有效的样式的方式 。 话虽如此 , 我们仍可以借用一些经验来指导我们的决定 。 当测量内容相似度时 , content_img与生成的input_img之间存在像素完美匹配时 , 较低层往往会激活得最高 。 我们进入网络的深度越深 , 各层对精确匹配的关注就越少 , 而当特征通常位于正确的位置时 , 它们就会激活得更多 。 为了可视化每个图层最关注的内容 , 我们可以设置style_weight=0并使用不同的图层作为content_layer在随机的input_img上运行训练过程 。


推荐阅读