首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >求关于输入的Caffe conv-滤波器的梯度

求关于输入的Caffe conv-滤波器的梯度
EN

Stack Overflow用户
提问于 2015-07-09 17:48:20
回答 2查看 7.2K关注 0票数 37

作为可视化过滤器的一种方法,我需要找到卷积神经网络中单个卷积滤波器的输入层的梯度。

如果卡菲的Python中有一个经过训练的网络,比如这个例子中的网络,那么如何才能找到相对于输入层中数据的conv过滤器的梯度呢?

编辑:

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

代码语言:javascript
复制
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过滤器的梯度,这是另一回事。我怎样才能做到这一点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-06 05:02:05

咖啡豆网杂耍两个“流”的数字。

第一个是数据“流”:通过网络推送的图像和标签。当这些输入通过网络进行时,它们被转换为高级表示,并最终转化为类概率向量(在分类任务中)。

第二个“流”包含不同层的参数、卷积权值、偏差等,这些数/权值在网络的列车阶段被改变和学习。

尽管这两个“流”扮演着根本不同的角色,但caffe仍然使用相同的数据结构blob来存储和管理它们。

但是,对于每个层,有两个不同的小块矢量,每个流一个。

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

代码语言:javascript
复制
import caffe
solver = caffe.SGDSolver( PATH_TO_SOLVER_PROTOTXT )
net = solver.net

如果你现在看看

代码语言:javascript
复制
net.blobs

您将看到字典为网络中的每个层存储一个"caffe“对象。每个blob都有存储数据和梯度的空间。

代码语言:javascript
复制
net.blobs['data'].data.shape    # >> (32, 3, 224, 224)
net.blobs['data'].diff.shape    # >> (32, 3, 224, 224)

对于卷积层:

代码语言:javascript
复制
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的另一个成员

代码语言:javascript
复制
net.layers

这是一个存储不同层参数的caffe矢量。

查看第一层('data'层):

代码语言:javascript
复制
len(net.layers[0].blobs)    # >> 0

输入层没有要存储的参数。

另一方面,对于第一个卷积层

代码语言:javascript
复制
len(net.layers[1].blobs)    # >> 2

网络存储一个水滴用于过滤权重,另一个存储恒定偏差。它们在这里

代码语言:javascript
复制
net.layers[1].blobs[0].data.shape  # >> (64, 3, 7, 7)
net.layers[1].blobs[1].data.shape  # >> (64,)

如您所见,该层对3通道输入图像执行7x7卷积,并具有64个这样的滤波器。

现在,如何得到梯度?好吧,就像你说的

代码语言:javascript
复制
diffs = net.backward(diffs=['data','conv1/7x7_s2'])

返回数据流的梯度。我们可以通过

代码语言:javascript
复制
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中:

代码语言:javascript
复制
net.layers[1].blobs[0].diff.shape # >> (64, 3, 7, 7)
net.layers[1].blobs[1].diff.shape # >> (64,)

为了帮助您在图层名称和它们的索引之间映射到net.layers向量,您可以使用net._layer_names

关于使用梯度可视化过滤器响应的更新

通常为标量函数定义梯度。损失是一个标量,因此您可以说相对于标量损失,像素/滤波器权重的梯度。此梯度为每像素/滤波器权重的单个数字。

如果您希望获得与特定的内部隐藏节点的最大激活相关的输入,则需要一个“辅助”网络,它的损失正是要可视化的特定隐藏节点的激活量。一旦您拥有了这个辅助网,您就可以从任意输入开始,并根据辅助损失的梯度将此输入更改为输入层:

代码语言:javascript
复制
update = prev_in + lr * net.blobs['data'].diff
票数 29
EN

Stack Overflow用户

发布于 2015-07-10 20:42:29

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

代码语言:javascript
复制
net.forward()
diffs = net.backward(diffs=['data', 'conv1'])`
data_point = 16
plt.imshow(diffs['data'][data_point].squeeze())

在某些情况下,您可能希望强制所有层向后执行,请查看模型的force_backward参数。

https://github.com/BVLC/caffe/blob/master/src/caffe/proto/caffe.proto

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31324739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档