前言
深度监督deep supervision(又称为中继监督intermediate supervision),其实就是网络的中间部分新添加了额外的loss,跟多任务是有区别的,多任务有不同的GT计算不同的loss,而深度监督的GT都是同一个GT,不同位置的loss按系数求和。
深度监督的目的是为了浅层能够得到更加充分的训练,避免梯度消失(ps:好像目前的技术已经使梯度消失得到了解决,像Relu,BN等等,"避免梯度消失"有待商榷,但是对训练的确有帮助)。
CPM(Convolutional Pose Machines)[2]中使用中继(深度)监督是最典型的一个例子。CPM的问题是为了解决人体姿态估计问题,分4个阶段,每个stage都会进行监督训练,使最终得到的人体姿态估计的关键点优化效果达到最佳状态。
下面?这张图来自论文,箭头处是每次要优化的map。注意⚠️:是使用同一个GT对各个stage的map进行优化。
3D U-Net with deep supervision
图片来自[1],网络结构示意图如下:
红色的方框内为两次的中继监督。此网络三次下采样,三次上采样,上采样的过程中进行中继监督。
[3]代码中的网络结构实现的深度监督的方式,如下图所示:
实现的代码[Code with tensorflow][3]:
def unet3d(inputs):
depth = config.DEPTH
filters = []
down_list = []
deep_supervision = None
layer = tf.layers.conv3d(inputs=inputs,
filters=BASE_FILTER,
kernel_size=(3,3,3),
strides=1,
padding=PADDING,
activation=lambda x, name=None: BN_Relu(x),
data_format=DATA_FORMAT,
name="init_conv")
for d in range(depth):
if config.FILTER_GROW:
num_filters = BASE_FILTER * (2**d)
else:
num_filters = BASE_FILTER
filters.append(num_filters)
layer = Unet3dBlock('down{}'.format(d), layer, kernels=(3,3,3), n_feat=num_filters, s=1)
down_list.append(layer)
if d != depth - 1:
layer = tf.layers.conv3d(inputs=layer,
filters=num_filters*2,
kernel_size=(3,3,3),
strides=(2,2,2),
padding=PADDING,
activation=lambda x, name=None: BN_Relu(x),
data_format=DATA_FORMAT,
name="stride2conv{}".format(d))
print("1 layer", layer.shape)
for d in range(depth-2, -1, -1):
layer = UnetUpsample(d, layer, filters[d])
if DATA_FORMAT == 'channels_first':
layer = tf.concat([layer, down_list[d]], axis=1)
else:
layer = tf.concat([layer, down_list[d]], axis=-1)
#layer = Unet3dBlock('up{}'.format(d), layer, kernels=(3,3,3), n_feat=filters[d], s=1)
layer = tf.layers.conv3d(inputs=layer,
filters=filters[d],
kernel_size=(3,3,3),
strides=1,
padding=PADDING,
activation=lambda x, name=None: BN_Relu(x),
data_format=DATA_FORMAT,
name="lo_conv0_{}".format(d