改进3D2DU-NET--添加深度监督deepsupervision【Keras】

更新时间:2023-05-05 12:18:51 阅读: 评论:0

改进3D2DU-NET--添加深度监督deepsupervision【Keras】
前⾔
深度监督deep supervision(⼜称为中继监督intermediate supervision),其实就是⽹络的中间部分新添加了额外的loss,跟多任务是有区别的,多任务有不同的GT计算不同的loss,⽽深度监督的GT都是同⼀个GT,不同位置的loss按系数求和。
深度监督的⽬的是为了浅层能够得到更加充分的训练,避免梯度消失(ps:好像⽬前的技术已经使梯度消失得到了解决,像Relu,BN等等,"避免梯度消失"有待商榷,但是对训练的确有帮助)。
CPM(Convolutional Po 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 = v3d(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)
el:
el:
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 = v3d(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)
el:
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 = v3d(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))
layer = v3d(inputs=layer,
filters=filters[d],
kernel_size=(1,1,1),
strides=1,
padding=PADDING,
activation=lambda x, name=None: BN_Relu(x),
data_format=DATA_FORMAT,
name="lo_conv1_{}".format(d))
if config.DEEP_SUPERVISION:
if d <3and d >0:
pred = v3d(inputs=layer,
filters=config.NUM_CLASS,
kernel_size=(1,1,1),
strides=1,
padding=PADDING,
activation=tf.identity,
data_format=DATA_FORMAT,
name="deep_super_{}".format(d))
if deep_supervision is None:
deep_supervision = pred
el:
deep_supervision = deep_supervision + pred
deep_supervision = Upsample3D(d, deep_supervision)
layer = v3d(layer,
filters=config.NUM_CLASS,
kernel_size=(1,1,1),
padding="SAME",
activation=tf.identity,
data_format=DATA_FORMAT,
name="final")
if config.DEEP_SUPERVISION:
layer = layer + deep_supervision
if DATA_FORMAT =='channels_first':
layer = tf.transpo(layer,[0,2,3,4,1])# to-channel last
print("final", layer.shape)# [3, num_class, d, h, w]
print("final", layer.shape)# [3, num_class, d, h, w]
return layer
def Upsample3D(prefix, l, scale=2):
l = tf.keras.layers.UpSampling3D(size=(2,2,2), data_format=DATA_FORMAT)(l) return l
def UnetUpsample(prefix, l, num_filters):
l = Upsample3D('', l)
l = v3d(inputs=l,
filters=num_filters,
kernel_size=(3,3,3),
strides=1,
padding=PADDING,
activation=lambda x, name=None: BN_Relu(x),
data_format=DATA_FORMAT,
name="up_conv1_{}".format(prefix))
return l
def BN_Relu(x):
if config.INSTANCE_NORM:
l = InstanceNorm5d('ins_norm', x, data_format=DATA_FORMAT)
el:
l = BatchNorm3d('bn', x, axis=1if DATA_FORMAT =='channels_first'el-1)    l = lu(l)
return l
def Unet3dBlock(prefix, l, kernels, n_feat, s):
if config.RESIDUAL:
l_in = l
for i in range(2):
l = v3d(inputs=l,
filters=n_feat,
kernel_size=kernels,
strides=1,
padding=PADDING,
activation=lambda x, name=None: BN_Relu(x),
data_format=DATA_FORMAT,
name="{}_conv_{}".format(prefix, i))
return l_in + l if config.RESIDUAL el l
Code with tensorflow
3D代码可以参考[3]。
2D代码可以参考[2]。
思考
深度监督的形式,⽬前感觉有两种:
第⼀种形式如第⼀张图⽚所⽰。第⼆种形式略微有不同,如下图所⽰:
4个阶段的map及性能concat,然后进⾏卷积得到⼀个map,与gt求loss,也就是说最后只有⼀个loss。这个代码⽐较简单,以2D为例,参考了[2],略做修改,使⽤Keras。
from keras.backend import tf as ktf
def BatchActivate(x):
x = BatchNormalization()(x)
x = Activation('relu')(x)
return x
def convolution_block(x, filters, size, strides=(1,1), padding='same', activation=True):
x = Conv2D(filters, size, strides=strides, padding=padding)(x)
if activation ==True:
x = BatchActivate(x)
return x
def residual_block(blockInput, num_filters=16, batch_activate =Fal):
x = BatchActivate(blockInput)
x = convolution_block(x, num_filters,(3,3))
x = convolution_block(x, num_filters,(3,3), activation=Fal)
x = Add()([x, blockInput])
if batch_activate:
x = BatchActivate(x)
return x
# Build model
def build_model(input_layer, lr, start_neurons, DropoutRatio =0.5):
# 101 -> 50
conv1 = Conv2D(start_neurons *1,(3,3), activation=None, padding="same")(input_layer)
conv1 = residual_block(conv1,start_neurons *1)
conv1 = residual_block(conv1,start_neurons *1,True)
pool1 = MaxPooling2D((2,2))(conv1)
pool1 = Dropout(DropoutRatio/2)(pool1)
# 50 -> 25
conv2 = Conv2D(start_neurons *2,(3,3), activation=None, padding="same")(pool1)
conv2 = residual_block(conv2,start_neurons *2)
conv2 = residual_block(conv2,start_neurons *2,True)
pool2 = MaxPooling2D((2,2))(conv2)
pool2 = Dropout(DropoutRatio)(pool2)
# 25 -> 12
conv3 = Conv2D(start_neurons *4,(3,3), activation=None, padding="same")(pool2)
conv3 = residual_block(conv3,start_neurons *4)
conv3 = residual_block(conv3,start_neurons *4,True)
pool3 = MaxPooling2D((2,2))(conv3)
pool3 = Dropout(DropoutRatio)(pool3)

本文发布于:2023-05-05 12:18:51,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/531902.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:监督   深度   消失   梯度   得到   训练
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图