Google Deep Dream 艺术:如何在神经网络中选择一个层并对其进行增强

Google Deep Dream art: how to pick a layer in a neural network and enhance it

我对 Google 最近的一篇博客 post 很感兴趣,这篇博客描述了 nn 的艺术创作用途。

我对一种技术特别感兴趣:

'In this case we simply feed the network an arbitrary image or photo and let the network analyze the picture. We then pick a layer and ask the network to enhance whatever it detected. Each layer of the network deals with features at a different level of abstraction, so the complexity of features we generate depends on which layer we choose to enhance. For example, lower layers tend to produce strokes or simple ornament-like patterns, because those layers are sensitive to basic features such as edges and their orientations.'

post 是 http://googleresearch.blogspot.co.uk/2015/06/inceptionism-going-deeper-into-neural.html?m=1

我的问题:post将此描述为一个'simple'案例——是否有可以使用的 nn 的开源实现为此目的,在一个相对即插即用的过程中? 对于所描述的技术,是否需要训练网络?

毫无疑问,对于本文中提到的其他技术,需要一个已经在大量图像上训练过的网络,但对于我描述的那个,是否已经有某种开源网络层可视化包?

UPD:Google 发布了更详细的实施说明:https://github.com/google/deepdream/blob/master/dream.ipynb

还有一个项目:https://317070.github.io/Dream/

如果您从 link 阅读 1、[2]、[3]、[4],您会发现他们使用了 Caffe。该框架已经包含可以使用的训练有素的网络。您不需要手动训练任何东西,只需使用 models/ 文件夹中的 .sh 脚本下载模型。

你想要"plug-and-play process",这并不容易,因为除了框架之外,我们还需要他们使用的脚本代码,可能还需要补丁Caffe。我试着用他们的描述做点什么。 Caffe 有 Python 和 Matlab 接口,但其内部还有更多。

下面的文字描述了我对如何实现它的想法。我不确定我的话,所以它更像是邀请我一起研究,而不是 "plug-and-play process"。但由于仍然没有人回答,让我把它放在这里。也许有人会修复我。

所以

据我了解,他们运行优化

[sum((net.forwardTo(X, n) - enchanced_layer).^2) + lambda * R(X)] -> min

即寻找这样的输入 X 以便网络的特定层产生 "enchanced" 数据而不是 "original" 数据。

有一个正则化约束 R(X)X 应该看起来像 "natural image"(没有高频噪声)。

X 是我们的目标图像。初始点X0为原图。 forwardTo(X, n) 是我们的网络在 n 层中生成的,当我们用 X 提供输入时。如果谈论 Caffe,您可以进行全前向传递(net.forward)并查看 blob您对 (net.blob_vec(n).get_data()).

感兴趣

enchanced_layer - 我们在其中获取原始层 blob 和 "enchance" 信号。这是什么意思,我不知道。也许他们只是将值乘以系数,也许是其他东西。

因此,当您的输入图像在图层 n 中准确生成您想要的内容时,sum((forwardTo(X, n) - enchanced_net).^2) 将变为零。

lambda 是正则化参数,R(X)X 看起来自然的方式。我没有实施它,我的结果看起来很嘈杂。至于它的公式,你可以去[2].

我用Matlab和fminlbfgs优化了。

关键部分是找到上面公式的梯度,因为问题的维度太多,无法用数值计算梯度。

正如我所说,我没能找到 R(X) 的梯度。至于公式的主要部分,我是这样找到的:

  • n 层的 diff blob 设置为 forwardTo(X, n) - enchanced_net。 (set_diffset_data见caffe文档,set_data用于前向和等待数据,set_diff用于反向传播和等待数据错误)。
  • n-1层到输入执行部分反向传播。
  • 输入差异 blob 将包含我们需要的梯度。

Python 和 Matlab 接口不包含部分反向传播,但 Caffe C++ 内部包含它。我在下面添加了一个补丁以使其在 Matlab 中可用。

第四层增强结果:

我对结果不满意,但我认为这篇文章有一些共同点。

在 Dmitry 提供的 link 到 Ipython 笔记本中,它说它 gradient ascent with 最大化 L2 归一化。我相信这就是 Google 从算法角度增强功能的意思。

仔细想想,确实如此,最小化L2可以防止过拟合,也就是让曲线看起来更平滑。如果你反其道而行之,你的特征就会更加明显。

这里有一个很好的link理解gradient ascent,虽然它主要讨论梯度下降。

我对caffe的实现细节不太了解,因为我主要使用theano。希望对您有所帮助!

更新

于是今天看了详细的文章[1],[2],[3],[4],发现[3]居然把算法说的很详细

A locally-optimal I can be found by the back-propagation method. The procedure is related to the ConvNet training procedure, where the back-propagation is used to optimise the layer weights. The difference is that in our case the optimisation is performed with respect to the input image, while the weights are fixed to those found during the training stage. We initialised the optimisation with the zero image (in our case, the ConvNet was trained on the zero-centred image data), and then added the training set mean image to the result.

因此,在classification 上训练网络后,您再次w.r.t 训练输入图像,使用梯度上升以获得更高的分数 class。