Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 求Caffe-conv滤波器相对于输入的梯度_Python_C++_Neural Network_Deep Learning_Caffe - Fatal编程技术网

Python 求Caffe-conv滤波器相对于输入的梯度

Python 求Caffe-conv滤波器相对于输入的梯度,python,c++,neural-network,deep-learning,caffe,Python,C++,Neural Network,Deep Learning,Caffe,我需要找到卷积神经网络(CNN)中单个卷积滤波器相对于输入层的梯度,作为一种方法。 在的Python接口中给定一个经过训练的网络(如中的网络),我如何才能找到conv过滤器相对于输入层中数据的梯度 编辑: 基于,我添加了下面的代码。我的输入层的尺寸是[8,8,7,96]。我的第一个conv层,conv1,有11个大小为1x5的过滤器,导致维度[8,11,7,92] net = solver.net diffs = net.backward(diffs=['data', 'conv1']) pri

我需要找到卷积神经网络(CNN)中单个卷积滤波器相对于输入层的梯度,作为一种方法。
在的Python接口中给定一个经过训练的网络(如中的网络),我如何才能找到conv过滤器相对于输入层中数据的梯度

编辑:

基于,我添加了下面的代码。我的输入层的尺寸是
[8,8,7,96]
。我的第一个conv层,
conv1
,有11个大小为
1x5
的过滤器,导致维度
[8,11,7,92]

net = solver.net
diffs = 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中我的层的维度。经过一些测试,我发现这个输出是关于
data
层和
conv1
层的损失梯度


然而,我的问题是如何找到单个conv滤波器相对于输入层中数据的梯度,这是另一回事。如何实现这一点?

在运行
backward()
过程时,可以获得任何层的梯度。调用函数时只需指定层列表。要根据数据层显示渐变,请执行以下操作:

net.forward()
diffs = net.backward(diffs=['data', 'conv1'])`
data_point = 16
plt.imshow(diffs['data'][data_point].squeeze())
在某些情况下,您可能希望强制所有层向后执行,请查看模型的
force\u backward
参数

Caffe net处理两个数字“流”。
第一个是数据“流”:通过网络推送的图像和标签。当这些输入通过网络时,它们被转换为高级表示,并最终转换为类别概率向量(在分类任务中)。
第二个“流”包含不同层的参数、卷积的权重、偏差等。这些数字/权重在网络的训练阶段更改和学习

尽管这两个“流”所扮演的角色根本不同,caffe仍然使用相同的数据结构,
blob
,来存储和管理它们。
但是,对于每个层,有两个不同的blob向量,每个流一个

下面是一个我希望能够澄清的例子:

import caffe
solver = caffe.SGDSolver( PATH_TO_SOLVER_PROTOTXT )
net = solver.net
如果你现在看看

net.blobs
您将看到一个字典为网络中的每个层存储一个“caffe blob”对象。每个blob都有存储数据和渐变的空间

net.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

net.layers
这是存储不同层参数的caffe向量。
查看第一层(
'data'
层):

输入层没有可存储的参数。
另一方面,对于第一卷积层

len(net.layers[1].blobs)    # >> 2
网络存储一个blob用于过滤器权重,另一个blob用于恒定偏差。给你

net.layers[1].blobs[0].data.shape  # >> (64, 3, 7, 7)
net.layers[1].blobs[1].data.shape  # >> (64,)
如您所见,该层对3通道输入图像执行7x7卷积,并有64个这样的过滤器

现在,如何获得梯度?正如你所说的

diffs = net.backward(diffs=['data','conv1/7x7_s2'])
返回数据流的渐变。我们可以通过以下方式验证这一点:

np.all( diffs['data'] == net.blobs['data'].diff )  # >> True
np.all( diffs['conv1/7x7_s2'] == net.blobs['conv1/7x7_s2'].diff )  # >> True
TL;DR)如果需要参数的梯度,这些梯度将与参数一起存储在
net.layers
中:

net.layers[1].blobs[0].diff.shape # >> (64, 3, 7, 7)
net.layers[1].blobs[1].diff.shape # >> (64,)

为了帮助您在图层名称及其索引之间映射到
net.layers
vector,您可以使用
net.\u layer\u names


更新有关使用梯度可视化过滤器响应的信息:
梯度通常是为标量函数定义的。损耗是一个标量,因此可以说像素/滤波器权重相对于标量损耗的梯度。此渐变是每个像素/过滤器权重的单个数字。
如果你想获得一个特定的内部隐藏节点的最大激活结果的输入,你需要一个“辅助”网络,它的损失正好是你想要可视化的特定隐藏节点激活的度量。一旦你有了这个辅助网络,你可以从一个任意的输入开始,根据辅助损耗到输入层的梯度改变这个输入:

update = prev_in + lr * net.blobs['data'].diff

太好了,谢谢!如何获得SGD用于调整的完全相同的梯度,例如
conv1
中过滤器的参数?
diffs=net.backward(diffs=['loss','conv1'])
会准确地告诉我,还是caffe会在误差面下一步之前对梯度进行某种操作?权重更新的计算方式取决于解算器。对于SGD,在这一点上,如果动量不为零,它包括先前的更新,以及学习率和权重衰减。然而,根据这里的信息:(更新参数)和这里的代码:我猜
diff
中存储的值是最终的重量更新。我目前正在使用
solver的循环来训练我的CNN。步骤(1)
。我想在每次迭代中找到梯度,我想我可以简单地将
diffs=net.backward(diffs=['loss','conv1'])
添加到该循环中,因为解算器步骤会自动向前传递。你看到它可能会干扰训练的任何原因了吗?运行
net.backward()
只计算梯度并存储它们,但不更新参数,所以这应该不是问题。虽然你要跑两次后传球。是的,所以我想训练会慢一些。你知道我如何在只进行一次向后传球的训练中提取梯度吗?我找不到任何允许这样做的选项。感谢您提供的详细答案,这让我对水滴的工作原理有了更多的了解。然而,你还没有得到关于
update = prev_in + lr * net.blobs['data'].diff