省流结论
concat是通道数叠加
add为简单的像素叠加,通道不变
图示表达
concat作用
concat是通道数的增加,也就是说描述图像本身的特征数(通道数)增加了,而每一特征下的信息是没有增加;横向或纵向空间上的叠加。
add作用
add为简单的像素叠加,是描述图像的特征下的信息量增多了,但是描述图像的维度本身并没有增加,只是每一维下的信息量在增加,这显然是对最终的图像的分类是有益的。
数学表达
对于两路输入来说,如果是通道数相同且后面带卷积的话,add等价于concat之后对应通道共享同一个卷积核。下面具体式子解释一下,由于每个输出通道的卷积核是独立的,我们可以只看单个通道的输出。假设两路输入的通道分别为 X 1 , X 2 , . . . , X c 和 Y 1 , Y 2 , . . . , Y c . \mathrm{X}_{1},\mathrm{X}_{2},...,\mathrm{X}_{\mathrm{c}}和\mathrm{}Y_{1},\mathrm{Y}_{2},...\mathrm{,Y}_{\mathrm{ {c}}}. X1,X2,...,Xc和Y1,Y2,...,Yc.
那么concat单个输出通道为:
add单个输出通道为:
联系
add相当于加了一种prior,当两路输入可以具有“对应通道的特征图语义类似”(可能不太严谨)的性质的时候,可以用add来替代concat,这样更节省参数和计算量(concat是add的2倍
代码
class Concat(nn.Module):
# Concatenate a list of tensors along dimension
def __init__(self, dimension=1):
super().__init__()
self.d = dimension
def forward(self, x):
return torch.cat(x, self.d)
t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]]
tf.concat([t1, t2], 0) ==> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
tf.concat([t1, t2], 1) ==> [[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]]
# tensor t3 with shape [2, 3]
# tensor t4 with shape [2, 3]
tf.shape(tf.concat([t3, t4], 0)) ==> [4, 3]
tf.shape(tf.concat([t3, t4], 1)) ==> [2, 6]
import tensorflow as tf
x = tf.random.normal([1, 28, 28, 3]) # 输入张量
conv1 = tf.keras.layers.Conv2D(16, (3, 3), strides=2) # 卷积层1
conv2 = tf.keras.layers.Conv2D(16, (3, 3), strides=2) # 卷积层2
out1 = conv1(x) # 输出张量1
out2 = conv2(out1) # 输出张量2
out = tf.keras.layers.add([out1, out2]) # add操作