我在阅读关于对抗性图像和破坏神经网络的文章。尝试逐步理解文章内容,但由于经验不足,我很难理解以下说明。
目前,我有一个针对MNIST
数据集的逻辑回归模型。如果你提供一张图像,它会预测这张图像最可能是哪个数字…
saver.restore(sess, "/tmp/model.ckpt")# 数字7的图像x_in = np.expand_dims(mnist.test.images[0], axis=0)classification = sess.run(tf.argmax(pred, 1), feed_dict={x:x_in})print(classification)
现在,文章指出,为了破坏这张图像,我们首先需要做的是获取神经网络的梯度。换句话说,这将告诉我需要朝哪个方向调整图像,使其看起来更像数字2或3,尽管它实际上是7。
文章指出,使用反向传播
来实现这一点相对简单。因此,你可以定义一个函数…
compute_gradient(image, intended_label)
…这基本上告诉我们神经网络在那个点上寻找的是什么样的形状。
对于经验丰富的人来说,这可能很容易实现,但对我来说逻辑上难以理解。
从compute_gradient
函数的参数来看,我可以看出你需要输入一张图像和一个标签数组,其中目标标签的值设为1。
但我不明白这是如何返回神经网络的形状的。
无论如何,我想了解如何实现反向传播
算法以返回神经网络的梯度。如果答案不是很直接,我希望得到一些逐步的指导,关于如何让我的反向传播
按文章建议的方式工作。
换句话说,我不希望有人只是给我一些可以复制的代码,我还想理解如何实现它。
回答:
反向传播涉及计算网络输出中的误差(成本函数)作为输入和网络参数的函数,然后计算成本函数相对于每个参数的偏导数。这里详细解释太复杂了,但这本免费在线书籍的一章解释了反向传播在训练深度神经网络的常规应用中的过程。
生成能够欺骗神经网络的图像仅仅是将这个过程进一步扩展到输入层之外,到图像本身。不是稍微调整网络中的权重来减少误差,而是稍微调整像素值来增加误差,或者减少错误类别的误差。
有一个简单(但计算量大)的方法可以通过Calc 101中的技术来近似梯度:对于足够小的e,df/dx大约是(f(x + e) – f(x)) / e。
同样,要用这种技术计算相对于图像的梯度,计算在对单个像素进行微小更改后损失/成本的变化,将该值保存为相对于该像素的近似偏导数,并对每个像素重复此操作。
然后,相对于图像的梯度大约是:
( (cost(x1+e, x2, ... xn) - cost(x1, x2, ... xn)) / e, (cost(x1, x2+e, ... xn) - cost(x1, x2, ... xn)) / e, . . . (cost(x1, x2, ... xn+e) - cost(x1, x2, ... xn)) / e)