『cs231n』作业3问题3选讲_通过代码理解图像梯度
Saliency Maps
这部分想探究一下 CNN 内部的原理,参考论文 Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps.
一般我们反向传播 CNN 的时候,是可以得到图片的梯度(Image
Gradient)的,但是因为网络要学习的参数是权重 W,因此都不会用到这个梯度。这篇论文可视化了一下图片的梯度,称作是 saliency map,发现其实是网络对不同处像素值关注的权重。得到的结果甚至可以辅助做 segmentation 问题。
通俗来说就是,给定一张图片X,我们想要知道到底是图片中的哪些部分决定了该图片的最终分类结果,我们可以通过反向传播求出X关于loss function的偏导矩阵,这个偏导矩阵就是该图片的图像梯度,然后计算出类显著度图(class saliency map, csm)。Karen Simonyan论文的3.1节给出了计算方法:如果图片是灰度图,那么csm就取图像梯度的绝对值;如果是RGB图,csm就取图像梯度3个通道中绝对值最大的那个通道。csm中元素值的大小表示对应位置的图片像素对最终分类结果的影响程度。
from cs231n.layers import softmax_loss def compute_saliency_maps(X, y, model): """ Compute a class saliency map using the model for images X and labels y. Input: - X: Input images, of shape (N, 3, H, W) - y: Labels for X, of shape (N,) - model: A PretrainedCNN that will be used to compute the saliency map. Returns: - saliency: An array of shape (N, H, W) giving the saliency maps for the input images. """ saliency = None ############################################################################## # TODO: Implement this function. You should use the forward and backward # # methods of the PretrainedCNN class, and compute gradients with respect to # # the unnormalized class score of the ground-truth classes in y. # ############################################################################## scores, cache = model.forward(X) loss, dscores = softmax_loss(scores, y) dX, grads = model.backward(dscores, cache) saliency = dX.max(axis=1) return saliency
Fooling Images
给定一个类别标签,CNN 希望对应能输入什么样的图片呢?可以考虑把图片当做变量,固定模型中的权重,来优化下面的目标函数,
其中是给定类标签 y 时模型的评分。
def make_fooling_image(X, target_y, model): """ Generate a fooling image that is close to X, but that the model classifies as target_y. Inputs: - X: Input image, of shape (1, 3, 64, 64) - target_y: An integer in the range [0, 100) - model: A PretrainedCNN Returns: - X_fooling: An image that is close to X, but that is classifed as target_y by the model. """ X_fooling = X.copy() ############################################################################## # TODO: Generate a fooling image X_fooling that the model will classify as # # the class target_y. Use gradient ascent on the target class score, using # # the model.forward method to compute scores and the model.backward method # # to compute image gradients. # # # # HINT: For most examples, you should be able to generate a fooling image # # in fewer than 100 iterations of gradient ascent. # ############################################################################## while True: print i scores, cache = model.forward(X_fooling, mode='test') if scores[0].argmax() == target_y: break loss, dscores = softmax_loss(scores, target_y) # 使用目标分类计算分类层梯度 dX, grads = model.backward(dscores, cache) # 逆向传播推导图片梯度 X_fooling -= dX * 1000 # 修改图片,为了fooling的目的学习率设定的超大 return X_fooling