我修改了 http://www.deeplearningbook.org/contents/convnets.html 中的方程 9.12将 MxN 卷积核居中。
这给出了以下梯度表达式(暂时相信它),假设有 1 个输入和 1 个输出 channel (为了简化):
dK(krow, kcol) = sum(G(row, col) * V(row+krow-M/2, col+kcol-N/2); row, col)
为了阅读上面的内容,dK 在 krow、kcol 处的单个元素等于 G 乘以移位的 V 的乘积的所有行和列的总和。注意 G 和 V 具有相同的维度。我们将定义超出 V 的结果为零。
例如,在一维中,如果 G 为 [a b c d],V 为 [w x y z],M 为 3,则第一个和为 dot(G, [0 w x y]),第二个和为 dot(G ,[w x y z]),第三个和是点(G,[x y z 0])。
ArrayFire有移位操作,但它是循环移位,而不是零插入移位。此外,内核大小 MxN 通常很小,例如 7x7,因此似乎更优化的实现仅在 G 和 V 中读取一次,并在内核上累积。
对于该一维示例,我们将读入 a 和 w,x 并从 [a*0 aw ax] 开始。然后我们读入 b,y 并添加 [bw bx by]。然后读入c,z并添加[cx cy cz]。然后读入d,最后加上[dy dz d*0]。
在 ArrayFire 中是否有直接计算 dK 的方法?我忍不住认为这是某种卷积,但我一直无法理解卷积会是什么样子。
最佳答案
啊,原来如此。对于 3x3 dK 数组,我使用 unwrap 将 MxN 输入数组转换为两个 MxN 列向量。然后我对两个列向量的移位子集进行 9 点积。不,这不起作用,因为移位是二维的。
因此,我需要创建大小为 1 x (MxN) 和 (MxN) x 9 的中间数组,其中后者的每一列都是原始窗口的移位 MxN 窗口,其填充边框大小为 0,并且然后进行矩阵乘法。
嗯,这需要太多的内存(有时)。所以最终的解决方案是对输出 3x3 执行 gfor,并且对于每个循环,对一次展开的 G 和重复展开的 V 进行点积。
同意吗?
关于arrayfire - 在ArrayFire中实现卷积神经网络反向传播(梯度计算),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36392677/