任何人都可以确保我的推理吗?
假设我有一个(预训练的)完全连接的层fc
,将bx20x20x10
作为输入和bx64
作为输出层,其中b
是批处理大小。
现在,我有一个cx100x60x10
的输入。高度和高度100x60
可以细分为20x20
的5x3
。我想通过fc
层的本地响应(输出)的5x3
,即`cx5x3x64'。
现在我在想:在用fc weights
的卷积层和宽度20和身高20的卷积层相同。这是正确的吗?可能会有区别吗?
是的,如果执行了密集层重量矩阵的适当重塑,它将相同。
让我们首先查看密集层。您将20 x 20 x 10
矩阵输入到密集层。首先将其扁平化以产生4000 x 1
矢量。您希望输出尺寸为64 x 1
向量。因此,所需的重量矩阵是4000 x 64
和64
偏置参数。然后y = w^T * x + b = [4000 x 64]^T * [4000 x 1] + [64 x 1]
将产生[64 x 1]
矢量。因此,y[i] = w[i][0]*x[0] + ... + w[i][3999]*x[3999] + b[i]
用于i = [0, 63]
。请注意,b
表示偏差参数。
让我们转向卷积。要从大小100 x 60 x 10
的输入中产生5 x 3 x 64
输出,您需要64个过滤器,每个大小(20,20)
,并步行(20,20)
,而没有零盖。但是,每个20 x 20
滤波器都有沿整个深度延伸的局部连接性,即神经元沿输入深度连接到所有10个维度。请阅读此信息以获取有关卷积层本地连接的更多信息。
您的卷积层具有20 x 20
的接收场。卷积层中的每个神经元将连接到20 x 20 x 10
。因此,总共4000个权重(和一个偏置参数)。您有64个这样的过滤器。因此,您的总可学习权重= 4000 x 64 + 64
。x
和w
的一个20 x 20 x 10
块之间的卷积(size = 64 x 20 x 20 x 10
)可以执行为:
convResult = np.sum(np.sum(np.sum(x*w[:,:,::-1,::-1], axis=-1), axis=-1),axis=-1)
这里有一些好处。我之所以做w[:,:,::-1,::-1]
,是因为Theano卷积会翻转卷积内核(嗯,不是那么简单!)。如果您对谁翻转而没有感兴趣,请阅读。
最后,密集的层和卷积层(在这种情况下)实质上是执行相同的操作。它们首先要乘以乘以,然后总结两组4000个元素的向量/矩阵。重复此过程64次以产生64 x 1
矢量。因此,通过正确重塑致密层的重量矩阵,可以通过致密和卷积层达到完全相同的结果。但是,您需要照顾内核翻转以匹配结果。
下面我给出一个代码片段以手动计算卷积(使用numpy)并使用theano。
import theano
from theano import tensor as T
import numpy as np
X = T.ftensor4('X')
W = T.ftensor4('W')
out = T.nnet.conv2d(X,W)
f = theano.function([X, W], out, allow_input_downcast=True)
x = np.random.random((1,10,20,20))
w = np.random.random((64,10,20,20))
# convolution using Theano
c1 = np.squeeze(f(x,w)[0])
# convolution using Numpy
c2 = np.sum(np.sum(np.sum(x*w[:,:,::-1,::-1],axis=-1),axis=-1),axis=-1)
# check that both are almost identical
print np.amax(c2 - c1)