本文介绍了找到关于输入的Caffe转换滤波器的梯度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我需要在卷积神经网络(CNN)中找到单个卷积滤波器的输入层的梯度,作为显示过滤器。 在 Caffe 的Python界面中提供了受过培训的网络例如此示例中的示例,如何然后,我会根据输入图层中的数据找到转换过滤器的渐变?I need to find the gradient with regards to the input layer for a single convolutional filter in a convolutional neural network (CNN) as a way to visualize the filters.Given a trained network in the Python interface of Caffe such as the one in this example, how can I then find the gradient of a conv-filter with respect to the data in the input layer? 编辑:根据 cesans的回答,我添加了下面的代码。我的输入图层的尺寸为 [8,8,7,96] 。我的第一个转换层 conv1 有11个过滤器,大小为 1x5 ,导致尺寸 [8,11,7,92] 。Based on the answer by cesans, I added the code below. The dimensions of my input layer is [8, 8, 7, 96]. My first conv-layer, conv1, has 11 filters with a size of 1x5, resulting in the dimensions [8, 11, 7, 92].net = solver.netdiffs = net.backward(diffs=['data', 'conv1'])print diffs.keys() # >> ['conv1', 'data']print diffs['data'].shape # >> (8, 8, 7, 96)print diffs['conv1'].shape # >> (8, 11, 7, 92)从输出中可以看出, net.backward()返回的数组等于Caffe中我的图层的尺寸。经过一些测试,我发现这个输出是分别关于数据层和 conv1 layer。As you can see from the output, the dimensions of the arrays returned by net.backward() are equal to the dimensions of my layers in Caffe. After some testing I've found that this output is the gradients of the loss with regards to respectively the data layer and the conv1 layer.然而,我的问题是如何找到一个单一的conv-filter相对于输入层中的数据的梯度,这是别的。如何实现这一目标?However, my question was how to find the gradient of a single conv-filter with respect to the data in the input layer, which is something else. How can I achieve this?推荐答案 Caffe net篡改了两个数字流。 是数据流:通过网络推送的图像和标签。当这些输入通过网络前进时,它们被转换为高级表示,最终转换为类概率向量(在分类任务中)。 第二个流保存不同层的参数,卷积,偏差等。这些数字/权重在网络的训练阶段期间改变和学习。Caffe net juggles two "streams" of numbers.The first is the data "stream": images and labels pushed through the net. As these inputs progress through the net they are converted into high-level representation and eventually into class probabilities vectors (in classification tasks).The second "stream" holds the parameters of the different layers, the weights of the convolutions, the biases etc. These numbers/weights are changed and learned during the train phase of the net.尽管这两个流发挥了根本不同的作用, caffe仍然使用相同的数据结构 blob 来存储和管理它们。 然而,对于每一层,有两个不同Despite the fundamentally different role these two "streams" play, caffe nonetheless use the same data structure, blob, to store and manage them.However, for each layer there are two different blobs vectors one for each stream.这里有一个例子,我希望澄清:Here's an example that I hope would clarify:import caffesolver = caffe.SGDSolver( PATH_TO_SOLVER_PROTOTXT )net = solver.net如果您现在查看net.blobs您将看到一个字典存储网络中每个图层的caffe blob对象。每个blob都有数据和渐变的存储空间。You will see a dictionary storing a "caffe blob" object for each layer in the net. Each blob has storing room for both data and gradientnet.blobs['data'].data.shape # >> (32, 3, 224, 224)net.blobs['data'].diff.shape # >> (32, 3, 224, 224)对于卷积层:net.blobs['conv1/7x7_s2'].data.shape # >> (32, 64, 112, 112)net.blobs['conv1/7x7_s2'].diff.shape # >> (32, 64, 112, 112) net.blobs 保存第一个数据流,其形状与输入图像的形状匹配,直到生成的类概率向量。net.blobs holds the first data stream, it's shape matches that of the input images up to the resulting class probability vector.另一方面,您可以看到另一个 net 的会员On the other hand, you can see another member of netnet.layers这是一个存储不同图层参数的caffe向量。 查看第一层c $ c>'data' layer):This is a caffe vector storing the parameters of the different layers.Looking at the first layer ('data' layer):len(net.layers[0].blobs) # >> 0没有要为输入图层存储的参数。 另一方面,对于第一卷积层There are no parameters to store for an input layer.On the other hand, for the first convolutional layerlen(net.layers[1].blobs) # >> 2网络存储一个blob用于过滤器权重,另一个存储常量偏差。这里是The net stores one blob for the filter weights and another for the constant bias. Here they arenet.layers[1].blobs[0].data.shape # >> (64, 3, 7, 7)net.layers[1].blobs[1].data.shape # >> (64,)如您所见,此图层在3通道输入图像上执行7x7卷积,有64个这样的过滤器。As you can see, this layer performs 7x7 convolutions on 3-channel input image and has 64 such filters.现在,如何获得渐变?Now, how to get the gradients? well, as you noteddiffs = net.backward(diffs=['data','conv1/7x7_s2'])返回 data 流的渐变。我们可以通过Returns the gradients of the data stream. We can verify this bynp.all( diffs['data'] == net.blobs['data'].diff ) # >> Truenp.all( diffs['conv1/7x7_s2'] == net.blobs['conv1/7x7_s2'].diff ) # >> True( TL; DR )您需要参数的渐变,这些存储在具有参数的 net.layers 中:(TL;DR) You want the gradients of the parameters, these are stored in the net.layers with the parameters:net.layers[1].blobs[0].diff.shape # >> (64, 3, 7, 7)net.layers[1].blobs[1].diff.shape # >> (64,) 层的名称及其索引到 net.layers 向量中,可以使用 net._layer_names 。关于使用渐变来显示筛选器回应的To help you map between the names of the layers and their indices into net.layers vector, you can use net._layer_names. 更新: 通常为标量函数定义渐变。损失是一个标量,因此你可以说一个相对于标量损失的像素/滤波器权重的梯度。这个渐变是每个像素/过滤器权重的单个数字。 如果你想得到最大激活一个特定内部隐藏节点的结果,你需要一个辅助net其中的损失恰恰是对想要可视化的特定隐藏节点的激活的度量。一旦你有这个辅助网,你可以从任意输入开始,并根据辅助损失的梯度改变输入到输入层:Update regarding the use of gradients to visualize filter responses:A gradient is normally defined for a scalar function. The loss is a scalar, and therefore you can speak of a gradient of pixel/filter weight with respect to the scalar loss. This gradient is a single number per pixel/filter weight.If you want to get the input that results with maximal activation of a specific internal hidden node, you need an "auxiliary" net which loss is exactly a measure of the activation to the specific hidden node you want to visualize. Once you have this auxiliary net, you can start from an arbitrary input and change this input based on the gradients of the auxilary loss to the input layer:update = prev_in + lr * net.blobs['data'].diff 这篇关于找到关于输入的Caffe转换滤波器的梯度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-25 12:21