Path: blob/master/site/zh-cn/tutorials/generative/deepdream.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
DeepDream
本教程包含 DeepDream 的最小规模实现,如此篇由 Alexander Mordvintsev 发布的博文所述。
DeepDream 是一项将神经网络学习模式予以可视化展现的实验。与孩子们观察云朵并尝试解释随机形状相类似,DeepDream 会过度解释并增强其在图像中看到的图案。
该技术的原理是通过网络转发图像,然后计算图像相对于特定层激活的梯度。随后,图像将被修改以增加这些激活,从而增强网络可识别到的图案,并生成梦境般的图像。该过程被称为“盗梦”(引用自 InceptionNet,以及电影《盗梦空间》)。
让我们演示如何帮助神经网络“造梦”并增强其在图像中识别到的超现实图案。
选择要梦境化的图像
在本教程中,我们使用了拉布拉多寻回犬的图片。
准备特征提取模型
下载并准备预训练的图像分类模型。您将使用 InceptionV3,它与 DeepDream 中最初使用的模型相似。请注意,任何预训练模型均可使用,但如果对其进行了更改,则您需要调整下方的层名称。
DeepDream 的方案是选择一个或多个层,并以使图像渐增式“激发”层的方式最大化“损失”。融入特征的复杂性取决于您选择的层,即较低的层会产生笔触或简单的图案,而较深的层则会使图像甚至整个对象呈现出复杂的特征。
InceptionV3 架构十分庞大(有关模型架构的图表,请参见 TensorFlow 的研究仓库)。对于 DeepDream,目标层是将卷积串联在一起的层。InceptionV3 中有 11 层,名为“mixed0”至“mixed10”。使用不同的层将产生不同的梦幻图像。较深的层响应较高级的特征(例如,眼睛和面部),而较浅的层则响应较简单的特征(例如,边缘、形状和纹理)。请随意尝试以下选择的层,但请记住,由于梯度计算的深度较大,较深的层(索引较高的层)将需要较长的训练时间。
计算损失
损失是所选层中激活的总和。损失在每一层均会进行归一化,因此较大层的贡献不会超过较小层。通常,您会希望通过梯度下降来实现损失量最小化。但在 DeepDream 中,您将通过梯度上升使这种损失最大化。
梯度上升
所选层的损失一旦计算完成,只需相对于图像计算梯度,并将梯度添加到原始图像即可。
将梯度添加到图像后,网络可以更清晰地识别图案。在每个步骤中,您都将创建一个图像,从而渐增式地激发网络中某些层的激活。
下文提供了执行此操作的方法,即包装在 tf.function
中,从而提升性能。它使用 input_signature
来确保不会因图像大小不一或 steps
/step_size
值不同而回溯函数。有关详细信息,请参阅具体函数指南。
主循环
调高八度
很好,但是首次尝试会有一些问题:
输出有噪声(可以使用
tf.image.total_variation
损失加以解决)。图像分辨率低。
图案看起来粒度全部相同。
一种可以解决所有上述问题的方法是以不同比例应用梯度上升。这将使在较小比例下生成的图案能够融合到较大比例的图案中,并附加其他细节。
为此,您可以执行以前的梯度上升方法,然后增大图像尺寸(称为八度),并对多个八度重复此过程。
可选:按比例增加图块
需要考虑的是,随着图像尺寸增大,执行梯度计算所需时间和内存也将随之增加。上文的八度实现不适用于非常大的图像或许多个八度。
为避免此问题,您可以将图像拆分为图块并为每个图块计算梯度。
在每次图块计算之前对图像应用随机偏移可防止出现图块缝隙。
首先实现随机偏移:
以下为此前定义的 deepdream
函数的图块式等效项:
将此组合到一起可提供能够感知八度的可扩展 Deepdream 实现:
好多了!调整八度数量、八度范围和激活层,以更改 DeepDream 图像的外观。
读者可能还会有兴趣了解 TensorFlow Lucid,其中对本教程中介绍的用于可视化和解释神经网络的理念进行了扩展。