当前位置: 首页 > 面试题库 >

查找关于输入的Caffe转换滤波器的梯度

楚彦
2023-03-14
问题内容

我需要找到卷积神经网络(CNN)中单个卷积过滤器相对于输入层的梯度,以可视化过滤器。
给定Caffe的Python界面中经过训练的网络(例如本示例中的网络),那么我如何才能找到conv过滤器相对于输入层中数据的梯度?

编辑:

根据cesans的回答,我添加了以下代码。我的输入层的尺寸为[8,8, 7, 96]。我的第一个转换层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层的损耗的梯度。

但是,我的问题是如何针对输入层中的数据找到单个转换滤波器的梯度,这是另一回事。我该如何实现?


问题答案:

Caffe网玩杂了两个“数字流”。
第一个是数据“流”:通过网络推送的图像和标签。当这些输入通过网络进行时,它们将转换为高级表示,并最终转换为类概率向量(在分类任务中)。
第二个“流”保存不同层的参数,卷积的权重,偏差等。在网络的训练阶段更改并获知这些数字/权重。

尽管这两个“流”扮演的角色根本不同,但是caffe使用相同的数据结构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'layer):

len(net.layers[0].blobs)    # >> 0

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

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矢量,可以使用net._layer_names

更新 关于使用梯度来可视化滤波器响应:
梯度通常用于定义 标量 函数。损失是一个标量,因此您可以说像素/滤镜权重相对于标量损失的梯度。该梯度是每个像素/滤镜权重的一个数字。
如果要获得最大程度激活 特定
内部隐藏节点的输入,则需要一个“辅助”网,其损失恰好是要可视化特定隐藏节点的激活的量度。一旦有了该辅助网,就可以从任意输入开始,并根据辅助损耗到输入层的梯度来更改此输入:

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


 类似资料:
  • 我有一个文本输入,我不想允许用户使用空格,所有键入的都会变成小写。 我实际上是在尝试创建“标记”特性,它的工作原理与StackOverflow上的特性类似。

  • 我想要一种影响swagger输出留档的方法。问题是询问文档的用户只能对swagger中描述的一些方法拥有权限,所以我想从输出中排除特定方法。我认为最糟糕的方法是通过中间件捕获swagger.json请求,然后检查被请求的用户可以访问哪些方法并排除必要的路径。但是我不太喜欢它,所以可能有内置功能来做到这一点?

  • 我在keras建立了一个ConvNet,这是其中的两层 第一层大小的输出,我完全理解,因为有8个大小为3x3的过滤器,每个过滤器都被应用于生成单独的特征图,因此 第二层的输出大小为24x24x16,我不理解。由于第二层的每个过滤器将作用于第一层输出的每个特征映射,因此输出的大小不应该是24x24x128吗? 基本上,我不明白一层的输出是如何馈送到另一层的输入的

  • 有人能帮我定义jolt规范,把输入json转换成输出json吗..我在一个文件中输入了json,像{"filename":"test1 "," value":"10"} {"filename":"test2 "," value":"10"}。转换后的输出json应该如下所示:{"filename":"test "," overallvalue":"20 "," filename":[{"filen

  • 我从几篇文章中了解到,要计算滤波器的梯度,只需以输入体积为输入,以误差矩阵为核进行卷积。之后,只需将过滤器权重减去梯度(乘以学习率)。我实现了这个过程,但它不起作用。 我甚至试着自己用笔和纸做反向传播过程,但我计算的梯度并没有使过滤器的性能更好。那么,我对整个过程的理解是否有误? 编辑:我将提供一个例子,说明我对CNN中反向传播及其问题的理解。 考虑卷积层的随机输入矩阵: 1,0,1 0、0、1

  • 如何在我当前的android代码中实现IIR带通滤波器?我有一个android应用程序,它可以录制音频(实际上是频率)并将其保存在一个文件夹中。wav文件。 我已经设法在网上找到了一个IIR过滤器库,但我不确定如何在代码中实现它。 https://github.com/ddf/Minim/blob/master/src/ddf/minim/effects/BandPass.java https:/