需要澄清 Google 的 deep dream 脚本的 make_step 功能

数据挖掘 机器学习 Python 神经网络 深度学习
2022-02-24 18:34:01

来自https://github.com/google/deepdream/blob/master/dream.ipynb

def objective_L2(dst):          # Our training objective. Google has since release a way to load
    dst.diff[:] = dst.data      # arbitrary objectives from other images. We'll go into this later.

def make_step(net, step_size=1.5, end='inception_4c/output', 
              jitter=32, clip=True, objective=objective_L2):
    '''Basic gradient ascent step.'''

    src = net.blobs['data'] # input image is stored in Net's 'data' blob
    dst = net.blobs[end]

    ox, oy = np.random.randint(-jitter, jitter+1, 2)
    src.data[0] = np.roll(np.roll(src.data[0], ox, -1), oy, -2) # apply jitter shift

    net.forward(end=end)
    objective(dst)  # specify the optimization objective
    net.backward(start=end)
    g = src.diff[0]
    # apply normalized ascent step to the input image
    src.data[:] += step_size/np.abs(g).mean() * g

    src.data[0] = np.roll(np.roll(src.data[0], -ox, -1), -oy, -2) # unshift image

    if clip:
        bias = net.transformer.mean['data']
        src.data[:] = np.clip(src.data, -bias, 255-bias)

如果我正确理解发生了什么,输入图像 innet.blobs['data']将插入到 NN 中,直到 layer end一次,前向传递完成,直到end,它会计算 处的 blobend与“某物”的“关闭”程度。

问题

  • 这是什么“东西”?dst.data吗?我逐步调试了一个调试器,发现它dst.data在赋值之后只是一个零矩阵,然后在反向传递之后填充了值。

  • 无论如何,假设它发现前向传播的结果有多“偏离”,为什么它会尝试进行反向传播?我认为深度梦想的重点不是进一步训练模型,而是将输入图像“变形”为原始模型层所代表的任何内容。

  • 具体是src.data[:] += step_size/np.abs(g).mean() * g做什么的?似乎将上面所做的任何计算应用于原始图像。这条线实际上是“变形”图像吗?

我已经阅读过的链接

我会对接受答案的作者的意思感兴趣

我们在其中获取原始层 blob 和“增强”信号。什么意思,我不知道。也许他们只是将值乘以系数,也许是别的。

在这篇博文中,作者在旁边评论src.data[:] += step_size/np.abs(g).mean() * g:“更接近我们的目标数据。” 我不太清楚这里的“目标数据”是什么意思。

请注意,正如我在评论中建议的那样,我从https://stackoverflow.com/q/40690099/2750819交叉发布此内容。

1个回答

这是什么“东西”?是 dst.data 吗?我逐步调试了一个调试器,发现 dst.data 在赋值之后只是一个零矩阵,然后在反向传递之后填充了值。

是的。dst.data是您试图最大化的 CNN 内层的工作内容。这个想法是,您希望通过更改输入来生成在该层中具有高神经元激活的图像。如果我理解正确的话,它应该在前向传递之后立即填充:net.forward(end=end)

无论如何,假设它发现前向传播的结果有多“偏离”,为什么它会尝试进行反向传播?我认为深度梦想的重点不是进一步训练模型,而是将输入图像“变形”为原始模型层所代表的任何内容。

这不是训练。然而,与训练一样,我们无法直接衡量我们想要更改的源与理想值的“偏离”程度,因此我们通过采用梯度来计算如何向更好的值移动。反向传播是计算 CNN 中参数梯度的常用方法。训练有一些主要区别:

  • 我们不是试图最小化成本,而是想增加一个指标来总结目标层的兴奋程度——我们不是试图找到任何静止点(例如最大可能值),而是 Deep Dream 通常只是在一个固定的迭代次数。

  • 我们比平时更进一步地反向传播,一直到输入层。这不是你在训练期间通常会做的事情。

  • 我们不对权重使用任何梯度。神经网络中的权重永远不会改变。我们只对输入处的梯度感兴趣——但要得到它们,我们需要先计算所有其他的。

src.data[:] += step_size/np.abs(g).mean() * g 到底是做什么的?似乎将上面所做的任何计算应用于原始图像。这条线实际上是“变形”图像吗?

沿着我们计算的梯度在图像数据中采取一个步骤将触发目标层中的更多活动。是的,这会改变输入图像。根据您希望 Deep Dream 效果的极端程度,应重复几次。