我正在尝试复制一个神经网络。我试图理解标准层类型的工作原理。特别是,我在任何地方都找不到关于跨通道归一化层在反向传递中的行为的描述。
由于归一化层没有参数,我可以猜测两种可能的选项:
-
来自下一层(即后续层)的误差梯度直接向后传递,不做任何处理。
-
误差梯度以与前向传递中跨通道激活归一化相同的方式进行归一化处理。
我无法基于任何直觉想出为什么要选择其中一种方式,因此我希望能得到一些帮助。
编辑1:
该层是caffe中的标准层,如这里所述 http://caffe.berkeleyvision.org/tutorial/layers.html(参见“局部响应归一化(LRN)”)。
该层在前向传递中的实现描述在alexNet论文的第3.3节:http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf
编辑2:
我认为前向和反向传递算法在Torch库中描述如下:https://github.com/soumith/cudnn.torch/blob/master/SpatialCrossMapLRN.lua
以及在Caffe库中描述如下:https://github.com/BVLC/caffe/blob/master/src/caffe/layers/lrn_layer.cpp
请熟悉这些库中的任何一个或两个的人将反向传递阶段的方法翻译成简单的英语?
回答:
它使用链式法则通过局部响应归一化层向后传播梯度。从这个意义上说,它有点类似于非线性层(本身没有可训练的参数,但确实影响向后的梯度)。
从你链接的Caffe代码中,我看到他们将每个神经元的误差作为参数,并通过以下方式计算前一层的误差:
首先,在前向传递中,他们缓存了一个所谓的scale,根据alexNet论文(见第3.3节的公式)计算为:
scale_i = k + alpha / n * sum(a_j ^ 2)
这里和下文中的sum
是按j
索引的和,从max(0, i - n/2)
到min(N, i + n/2)
(请注意,论文中没有按n
归一化,所以我假设这是Caffe与alexNet不同的地方)。然后前向传递计算为b_i = a_i + scale_i ^ -beta
。
为了反向传播误差,假设来自下一层的误差是be_i
,我们需要计算的误差是ae_i
。那么ae_i
计算为:
ae_i = scale_i ^ -b * be_i - (2 * alpha * beta / n) * a_i * sum(be_j * b_j / scale_j)
由于你计划手动实现它,我还将分享Caffe在其代码中使用的两个技巧,使实现更简单:
-
当你计算和的加数时,分配一个大小为
N + n - 1
的数组,并在每一端填充n/2
个零。这样你可以计算从i - n/2
到i + n/2
的和,而不必担心低于零和超过N
的情况。 -
你不需要在每次迭代中重新计算
sum
,而是提前计算加数(前向传递中的a_j^2
,反向传递中的be_j * b_j / scale_j
),然后计算i = 0
时的sum
,然后对于每个连续的i
,只需添加addend[i + n/2]
并减去addend[i - n/2 - 1]
,它将以恒定时间为新的i
值提供和的值。