如何在Keras中正确使用批量归一化与U-net?

13

我正在尝试在U-net中使用批归一化层进行分割任务。对于res-net、vgg、xception等相同的层都可以正常运行,我想知道这是否是与体系结构有关的问题?在训练过程中一切都很顺利,指标增长,损失下降,但一旦我尝试评估模型或预测掩模时,它就会生成垃圾。似乎那些层的学习权重在测试和预测期间仍在更新。如何在keras中解决这个问题? keras版本=2.2.2

我尝试仅在编码器部分使用批量规范化层,但没有帮助。 我也尝试设置层参数:trainable = False,但也没有帮助。

from keras.models import Input, Model
from keras.layers import Conv2D, Concatenate, MaxPooling2D
from keras.layers import UpSampling2D, Dropout, BatchNormalization

def conv_block(m, dim, res, do=0):
    n = Conv2D(dim, 3, padding='same')(m)
    n = BatchNormalization()(n)
    n = keras.layers.LeakyReLU(0)(n)
    n = Dropout(do)(n) if do else n
    n = Conv2D(dim, 3, padding='same')(n)
    n = BatchNormalization()(n) 
    n = keras.layers.LeakyReLU(0)(n)
    return Concatenate()([m, n]) if res else n


def conv_block_bn(m, dim, res, do=0):
    n = Conv2D(dim, 3, padding='same')(m)
    n = BatchNormalization()(n)
    n = keras.layers.LeakyReLU(0)(n)
    n = Dropout(do)(n) if do else n
    n = Conv2D(dim, 3, padding='same')(n)
    n = BatchNormalization()(n)
    n = keras.layers.LeakyReLU(0)(n)
    return Concatenate()([m, n]) if res else n

def level_block(m, dim, depth, inc,  do,  mp, up, res):
    if depth > 0:
        n = conv_block_bn(m, dim, res)#(m, dim, acti, bn, res)
        m = MaxPooling2D()(n) if mp else Conv2D(dim, 3, strides=2, padding='same')(n)
        m = level_block(m, int(inc*dim), depth-1, inc,  do,  mp, up, res)
        if up:
            m = UpSampling2D()(m)
            m = Conv2D(dim, 2, padding='same')(m)
            m = BatchNormalization()(m) 
            m = keras.layers.LeakyReLU(0)(m)
        else:
            m = Conv2DTranspose(dim, 3, strides=2, activation='relu', padding='same')(m)
        n = Concatenate()([n, m])
        m = conv_block_bn(n, dim, res)#(n, dim, acti, bn, res)
    else:
        m = conv_block_bn(m, dim, res,do)#(m, dim, acti, bn, res, do)
    return m

def UNet(img_shape, out_ch=1, start_ch=64, depth=4, inc_rate=2., activation='relu', 
         dropout=0.5, batchnorm=False, maxpool=True, upconv=True, residual=False):
    i = Input(shape=img_shape)
    o = level_block(i, start_ch, depth, inc_rate,dropout, maxpool, upconv, residual)
    o = Conv2D(out_ch, 1, activation='sigmoid')(o)
    return Model(inputs=i, outputs=o)


model1 = UNet((512,512,1), out_ch=1, start_ch=64, depth=4, inc_rate=2.,  
         dropout=0.5, maxpool=True, upconv=True, residual=False)
model1 = multi_gpu_model(model1,gpus=6)
model1.compile(Adam(lr = 3.5e-6), loss = custom_losses, metrics = [dice_coef]) ```

请查看此链接以获取一个使用批量归一化的漂亮的Keras实现:https://www.kaggle.com/dingdiego/u-net-batchnorm-augmentation-stratification - user14675723
2个回答

3

在训练后预测输出时,您必须使用以下方式调用模型:

Option1:
prediction = trained_model(input, training=False)

选项2:

prediction = trained_model.call(input, training=False)

选项3:

prediction = trained_model.predict(input)

原因是Normalization和dropout等层在训练过程中表现不同。因此,您必须告诉模型您正在进行推断而非训练。


1

尝试在每个层上应用批量归一化,并消除随机失活层。查看你所得到的结果。在预测中也将training标志设置为False。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接