多输入多输出通道

2.a 计算量主要取决于输出的feature map尺寸(即卷积的次数)和卷积核的个数(即输出通道数),另ho,wo分别为输出的高宽,有
ho = (h - kh + ph)/sh + 1
hw = (w - kw + pw)/sh + 1
一次卷积需要的乘法计算数为khkwci;
加法计算数为ci*(kwkh-1)+(ci-1)+1,即cikwkh;
输出的feature map为ho
hwco,因此,前向计算乘法和加法总计算成本:
(kh
kwci+cikwkh)hohwco,即2khkwcihohwco
2.b,内存占用,先计算参数量,为卷积的权重和偏置,一个卷积核的权重有
kh
kwci,偏置为1,总共有khkwci+1个参数,有co个卷积核,因此总参数量为:
(kh
kwci+1)co
一般使用的是float16进行计算,占两个字节,因此需要(kh
kw
ci+1)co2 bytes。

6.4.5 练习中当卷积窗口不是1X1时,如何使用矩阵乘法实现卷积:
主要思想是将2X2的实现考虑成多个1X1的卷积窗口的和,需要注意对X的切割,这样2X2和多X多其实是一样的
def corr2d_multi_in_out_2x2(X, K):
c_i, h, w = X.shape
c_o,c_i,k_h,k_w = K.shape
Y = 0
for i in range (k_h):
for j in range (k_w):
Y += corr2d_multi_in_out_1x1(X[:,i:h-1+i,j:w-1+j],K[:,:,i,j])
return Y
不太会python,求问为啥上述实现中torch.abs(Y1 - Y2).sum()误差为1.2219e-06,是数据类型需要变一下吗?

第6题
我不知道我这么写符不符合要求…只用了矩阵乘法,没有用corr2d开头的相关函数
def convolution(X, K):
c_i, h, w = X.shape
c_o, kh, kw = K.shape[0], K.shape[2], K.shape[3]
h1, w1 = h - kh + 1, w - kw + 1
X1 = torch.zeros((c_o, h1, w1))

for l in range(c_o):
    for i in range(h1):
        for j in range(w1):
            cur = 0
            for x in range(c_i):
                cur += torch.sum(K[l, x] * X[x, i: i + kh, j: j + kw])
            X1[l, i, j] = cur

return X1

我觉得这个有点像三维卷积层呢,是我搞错了吗,二维确实应该是个标量

第一问不能简单写成k1+k2-1吧如果大小一样还要padding的。可以参考https://dsp.stackexchange.com/questions/10605/kernels-to-compute-second-order-derivative-of-digital-image

你好,请问第一题第一问中,为什么最后感受野大小一致就能证明两次卷积可以用一次卷积替代?
虽然感受野大小一致,但是如何证明一次卷积的输出能够与两次卷积的输出值相等?
本人数学比较差,望大佬解答:grinning:

1 Like

输出图像尺寸应该是(h-kh+2ph+sh)/sh + 1以及(w-kw+2pw+sw)/sw + 1吧

1.输入通道数决定了你的一个卷积核的高度。
2.输出通道数决定了该层有几个卷积核。
3.一个卷积核的一层有一个偏差。
根据题目:
有Ci个输入通道,一个卷积核就有Ci个偏差。
有Co个输出通道就代表有Co个卷积核
那么偏差的数量就是:Co * Ci

第2题(1):

多输入多输出,每个输出卷积核们(针对每个输入的卷积核)输入们对应运算得到的结果进行相加或别的运算得到的,几个输出就需要几套针对输出的 卷积核们,而在一个输出中,它又需要针对每个输入的卷积核们,所以此处卷积核是二维,而与此对应的偏差也应该是二维的。因为在前面证明移不变时,证明的范畴是单个输出单个输入,对每个像素核都应该一致,同时偏差也应该一个常数(也就是你说的核里的参数都共用一个偏差)。

"""Q6"""
def corr2d_matmul_channels(X, K): 
    """矩阵乘法实现多通道卷积"""
    (Xh, Xw), (Co, Ci, Kh, Kw) = X.shape[-2:], K.shape
    Yh, Yw = Xh - Kh + 1, Xw - Kw + 1
    Y = torch.zeros((Yh, Yw, Ci * Kh * Kw))
    for i in range(Yh):
        for j in range(Yw):
            Y[i, j] = X[:, i:i + Kh, j:j + Kw].reshape(-1)
    return torch.stack([Y @ k.reshape(-1) for k in K], 0)

X = torch.normal(0, 1, (3, 3, 3))
K = torch.normal(0, 1, (2, 3, 2, 2))
Y1 = corr2d_matmul_channels(X, K)
Y2 = corr2d_multi_in_out(X, K)
Y1.shape, float(torch.abs(Y1 - Y2).sum()) < 1e-6

结果
(torch.Size([2, 2, 2]), True)

1 Like

有一个问题:上面很多答案中提到加法计算次数的时候,似乎只考虑了卷积计算这一步骤中的加法次数,但是要得到输出结果,应该在得到每个输入通道的卷积结果后将每个卷积后的输入通道加起来,这一步是不是同样要考虑在加法次数内,所以还有一项为 Co*(C1-1)总乘法次数表达式/(C1C0)

因为卷积计算本质是仿射变换(当bias为0时,为线性变换),仿射变换的嵌套仍为仿射变具体来说,假设卷积层A对感受野Fi做仿射变换,结果为A(F1),…,A(Fn),使用卷积层B再对上述结果做仿射变换,即B(A(Fj)U,…,UA(F_k))。我们知道该变换对于FjU,…,UFk仍然是仿射变换,这里 FjU,…,UFk就是对应感受野。即我们可以采用卷积层C,C(FjU,…,UFk)=B(…)
这里U是空间的并运算