🍨 本文为:[🔗365天深度学习训练营] 中的学习记录博客
🍖 原作者:[K同学啊 | 接辅导、项目定制]
要求:
- 阅读给出代码,判断是否存在错误,正确与否都请给出你的思考;
- 查找相关资料、逐步推理模型、写下思考过程
# 定义残差单元
def block(x, filters, strides=1, groups=32, conv_shortcut=True):if conv_shortcut:
shortcut = Conv2D(filters * 2, kernel_size=(1, 1), strides=strides, padding='same', use_bias=False)(x)
# epsilon为BN公式中防止分母为零的值
shortcut = BatchNormalization(epsilon=1.001e-5)(shortcut)
else:
# identity_shortcut
shortcut = x
# 三层卷积层
x = Conv2D(filters=filters, kernel_size=(1, 1), strides=1, padding='same', use_bias=False)(x)
x = BatchNormalization(epsilon=1.001e-5)(x)
x = ReLU()(x)
# 计算每组的通道数
g_channels = int(filters / groups)
# 进行分组卷积
x = grouped_convolution_block(x, strides, groups, g_channels)x = Conv2D(filters=filters * 2, kernel_size=(1, 1), strides=1, padding='same', use_bias=False)(x)
x = BatchNormalization(epsilon=1.001e-5)(x)
x = Add()([x, shortcut])
x = ReLU()(x)
return x# 堆叠残差单元
def stack(x, filters, blocks, strides, groups=32):
# 每个stack的第一个block的残差连接都需要使用1*1卷积升维
x = block(x, filters, strides=strides, groups=groups)
for i in range(blocks):
x = block(x, filters, groups=groups, conv_shortcut=False)
return x
问题:如果conv_shortcut=False,那么执行“x=Add()…”语句时,通道数不一致的,为什么不会报错?
思考分析
在ResNext网络中,将conv_shortcut参数设置为False,表示使用identity_shortcut而不是Conv2D层作为快捷连接。
对于定义残差单元block模块,Add()是x和shortcut相加,x通道数是filter*2。对于shortcut,conv_shortcut为True则是filters*2,否则是原始输入通道数。
最后对于堆叠残差模块stack,第二次调用block时,conv_shortcut参数是False,使用的是identity_shortcut,这种情况下,快捷连接将直接传递输入x给块的最后一层。因此,在执行“x=Add()…”语句时,快捷连接的通道数与该层的通道数不一致。
但是,由于Add()层在通道数不同时会自动对快捷连接进行零填充,所以不会出现尺寸不匹配的错误。此外,这种零填充不会对训练产生任何影响,因为填充的值不会接收任何梯度更新。
总之,Add 层具有自动广播机制,可以在计算时自动扩展较小张量的形状以匹配较大张量的形状,因此即使通道数不一致也不会报错。