建立用于多类别语义分割的u-net模型

时间:2018-07-31 20:29:52

标签: keras

我正在尝试在keras中构建u-net以进行多类语义细分。我在下面的模型没有学到任何东西。它总是只预测背景(第一类)。

我对最后一个“ softmax”层的使用正确吗? documentation显示一个axis参数,但是我不确定如何设置该参数或应设置为什么。

def unet(input_shape=(572, 572, 1), classes=2):

    input_image = KL.Input(shape=input_shape)

    contracting_1, pooled_1 = blocks.contracting(input_image,   filters=64, block_name="block1")
    contracting_2, pooled_2 = blocks.contracting(pooled_1,      filters=128, block_name="block2")
    contracting_3, pooled_3 = blocks.contracting(pooled_2,      filters=256, block_name="block3")
    contracting_4, pooled_4 = blocks.contracting(pooled_3,      filters=512, block_name="block4")
    contracting_5, _ = blocks.contracting(pooled_4,             filters=1024, block_name="block5")

    dropout = KL.Dropout(rate=0.5)(contracting_5)

    expanding_1 = blocks.expanding(dropout,     merge_layer=contracting_4, filters=512, block_name="block6")
    expanding_2 = blocks.expanding(expanding_1, merge_layer=contracting_3, filters=256, block_name="block7")
    expanding_3 = blocks.expanding(expanding_2, merge_layer=contracting_2, filters=128, block_name="block8")
    expanding_4 = blocks.expanding(expanding_3, merge_layer=contracting_1, filters=64, block_name="block9")

    class_output = KL.Conv2D(classes, kernel_size=(1, 1), activation='softmax', name='class_output')(expanding_4)

    model = KM.Model(inputs=[input_image], outputs=[class_output])

    return model

块:

def contracting(input_layer, filters, kernel_size=(3, 3), padding='same',
                block_name=""):

    conv_a = KL.Conv2D(filters, kernel_size, activation='relu', padding=padding,
                       name='{}_contracting_conv_a'.format(block_name))(input_layer)
    conv_b = KL.Conv2D(filters, kernel_size, activation='relu', padding=padding,
                       name='{}_contracting_conv_b'.format(block_name))(conv_a)
    pool = KL.MaxPooling2D(pool_size=(2, 2), padding=padding,
                           name='{}_contracting_pool'.format(block_name))(conv_b)

    batch_normalization = KL.BatchNormalization()(pool)

    return conv_b, batch_normalization


def expanding(input_layer, merge_layer, filters, kernel_size=(3, 3), padding='same',
              block_name=""):

    input_layer = KL.UpSampling2D(size=(2, 2))(input_layer)

    conv_up = KL.Conv2D(filters, kernel_size=(2, 2), activation='relu',
                        padding='same', name='{}_expanding_conv_up'.format(block_name))(input_layer)

    conv_up_height, conv_up_width = int(conv_up.shape[1]), int(conv_up.shape[2])
    merge_height, merge_width = int(merge_layer.shape[1]), int(merge_layer.shape[2])

    crop_top = (merge_height - conv_up_height) // 2
    crop_bottom = (merge_height - conv_up_height) - crop_top
    crop_left = (merge_width - conv_up_width) // 2
    crop_right = (merge_width - conv_up_width) - crop_left

    cropping = ((crop_top, crop_bottom), (crop_left, crop_right))
    merge_layer = KL.Cropping2D(cropping)(merge_layer)
    merged = KL.concatenate([merge_layer, conv_up])

    conv_a = KL.Conv2D(filters, kernel_size, activation='relu', padding=padding,
                       name='{}_expanding_conv_a'.format(block_name))(merged)
    conv_b = KL.Conv2D(filters, kernel_size, activation='relu', padding=padding,
                       name='{}_expanding_conv_b'.format(block_name))(conv_a)

    batch_normalization = KL.BatchNormalization()(conv_b)

    return batch_normalization

编译:

optimizer = keras.optimizers.SGD(lr=0.0001, momentum=0.9)
loss = keras.losses.categorical_crossentropy
metrics = [keras.metrics.categorical_accuracy]

model.compile(optimizer, loss, metrics)

模型摘要:


Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_2 (InputLayer)            (None, 96, 96, 3)    0                                            
__________________________________________________________________________________________________
block1_contracting_conv_a (Conv (None, 96, 96, 64)   1792        input_2[0][0]                    
__________________________________________________________________________________________________
block1_contracting_conv_b (Conv (None, 96, 96, 64)   36928       block1_contracting_conv_a[0][0]  
__________________________________________________________________________________________________
block1_contracting_pool (MaxPoo (None, 48, 48, 64)   0           block1_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
batch_normalization_10 (BatchNo (None, 48, 48, 64)   256         block1_contracting_pool[0][0]    
__________________________________________________________________________________________________
block2_contracting_conv_a (Conv (None, 48, 48, 128)  73856       batch_normalization_10[0][0]     
__________________________________________________________________________________________________
block2_contracting_conv_b (Conv (None, 48, 48, 128)  147584      block2_contracting_conv_a[0][0]  
__________________________________________________________________________________________________
block2_contracting_pool (MaxPoo (None, 24, 24, 128)  0           block2_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
batch_normalization_11 (BatchNo (None, 24, 24, 128)  512         block2_contracting_pool[0][0]    
__________________________________________________________________________________________________
block3_contracting_conv_a (Conv (None, 24, 24, 256)  295168      batch_normalization_11[0][0]     
__________________________________________________________________________________________________
block3_contracting_conv_b (Conv (None, 24, 24, 256)  590080      block3_contracting_conv_a[0][0]  
__________________________________________________________________________________________________
block3_contracting_pool (MaxPoo (None, 12, 12, 256)  0           block3_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
batch_normalization_12 (BatchNo (None, 12, 12, 256)  1024        block3_contracting_pool[0][0]    
__________________________________________________________________________________________________
block4_contracting_conv_a (Conv (None, 12, 12, 512)  1180160     batch_normalization_12[0][0]     
__________________________________________________________________________________________________
block4_contracting_conv_b (Conv (None, 12, 12, 512)  2359808     block4_contracting_conv_a[0][0]  
__________________________________________________________________________________________________
block4_contracting_pool (MaxPoo (None, 6, 6, 512)    0           block4_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
batch_normalization_13 (BatchNo (None, 6, 6, 512)    2048        block4_contracting_pool[0][0]    
__________________________________________________________________________________________________
block5_contracting_conv_a (Conv (None, 6, 6, 1024)   4719616     batch_normalization_13[0][0]     
__________________________________________________________________________________________________
block5_contracting_conv_b (Conv (None, 6, 6, 1024)   9438208     block5_contracting_conv_a[0][0]  
__________________________________________________________________________________________________
dropout_2 (Dropout)             (None, 6, 6, 1024)   0           block5_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
up_sampling2d_5 (UpSampling2D)  (None, 12, 12, 1024) 0           dropout_2[0][0]                  
__________________________________________________________________________________________________
cropping2d_5 (Cropping2D)       (None, 12, 12, 512)  0           block4_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
block6_expanding_conv_up (Conv2 (None, 12, 12, 512)  2097664     up_sampling2d_5[0][0]            
__________________________________________________________________________________________________
concatenate_5 (Concatenate)     (None, 12, 12, 1024) 0           cropping2d_5[0][0]               
                                                                 block6_expanding_conv_up[0][0]   
__________________________________________________________________________________________________
block6_expanding_conv_a (Conv2D (None, 12, 12, 512)  4719104     concatenate_5[0][0]              
__________________________________________________________________________________________________
block6_expanding_conv_b (Conv2D (None, 12, 12, 512)  2359808     block6_expanding_conv_a[0][0]    
__________________________________________________________________________________________________
batch_normalization_15 (BatchNo (None, 12, 12, 512)  2048        block6_expanding_conv_b[0][0]    
__________________________________________________________________________________________________
up_sampling2d_6 (UpSampling2D)  (None, 24, 24, 512)  0           batch_normalization_15[0][0]     
__________________________________________________________________________________________________
cropping2d_6 (Cropping2D)       (None, 24, 24, 256)  0           block3_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
block7_expanding_conv_up (Conv2 (None, 24, 24, 256)  524544      up_sampling2d_6[0][0]            
__________________________________________________________________________________________________
concatenate_6 (Concatenate)     (None, 24, 24, 512)  0           cropping2d_6[0][0]               
                                                                 block7_expanding_conv_up[0][0]   
__________________________________________________________________________________________________
block7_expanding_conv_a (Conv2D (None, 24, 24, 256)  1179904     concatenate_6[0][0]              
__________________________________________________________________________________________________
block7_expanding_conv_b (Conv2D (None, 24, 24, 256)  590080      block7_expanding_conv_a[0][0]    
__________________________________________________________________________________________________
batch_normalization_16 (BatchNo (None, 24, 24, 256)  1024        block7_expanding_conv_b[0][0]    
__________________________________________________________________________________________________
up_sampling2d_7 (UpSampling2D)  (None, 48, 48, 256)  0           batch_normalization_16[0][0]     
__________________________________________________________________________________________________
cropping2d_7 (Cropping2D)       (None, 48, 48, 128)  0           block2_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
block8_expanding_conv_up (Conv2 (None, 48, 48, 128)  131200      up_sampling2d_7[0][0]            
__________________________________________________________________________________________________
concatenate_7 (Concatenate)     (None, 48, 48, 256)  0           cropping2d_7[0][0]               
                                                                 block8_expanding_conv_up[0][0]   
__________________________________________________________________________________________________
block8_expanding_conv_a (Conv2D (None, 48, 48, 128)  295040      concatenate_7[0][0]              
__________________________________________________________________________________________________
block8_expanding_conv_b (Conv2D (None, 48, 48, 128)  147584      block8_expanding_conv_a[0][0]    
__________________________________________________________________________________________________
batch_normalization_17 (BatchNo (None, 48, 48, 128)  512         block8_expanding_conv_b[0][0]    
__________________________________________________________________________________________________
up_sampling2d_8 (UpSampling2D)  (None, 96, 96, 128)  0           batch_normalization_17[0][0]     
__________________________________________________________________________________________________
cropping2d_8 (Cropping2D)       (None, 96, 96, 64)   0           block1_contracting_conv_b[0][0]  
__________________________________________________________________________________________________
block9_expanding_conv_up (Conv2 (None, 96, 96, 64)   32832       up_sampling2d_8[0][0]            
__________________________________________________________________________________________________
concatenate_8 (Concatenate)     (None, 96, 96, 128)  0           cropping2d_8[0][0]               
                                                                 block9_expanding_conv_up[0][0]   
__________________________________________________________________________________________________
block9_expanding_conv_a (Conv2D (None, 96, 96, 64)   73792       concatenate_8[0][0]              
__________________________________________________________________________________________________
block9_expanding_conv_b (Conv2D (None, 96, 96, 64)   36928       block9_expanding_conv_a[0][0]    
__________________________________________________________________________________________________
batch_normalization_18 (BatchNo (None, 96, 96, 64)   256         block9_expanding_conv_b[0][0]    
__________________________________________________________________________________________________
class_output (Conv2D)           (None, 96, 96, 4)    260         batch_normalization_18[0][0]     
==================================================================================================
Total params: 31,039,620
Trainable params: 31,035,780
Non-trainable params: 3,840
__________________________________________________________________________________________________

Total params: 31,031,940
Trainable params: 31,031,940
Non-trainable params: 0

数据集中的类别百分比:

{0: 0.6245757457188198,
 1: 0.16082110268729075,
 2: 0.1188858904157366,
 3: 0.09571726117815291}
  • 0是背景
  • 来自生成器(rgb)的图像形状:(1, 96, 96, 3)
  • 生成器中标签的形状:(1, 96, 96, 4)

3 个答案:

答案 0 :(得分:2)

您的模型似乎没有什么错。

Softmax可以,因为它默认为最后一个轴,因此您显然使用'channels_last'作为配置。这样就可以了

建议是:

  • 添加几层BatchNormalization()并降低学习速度(这可以防止relu太快地变为“全零”)。
  • 检查您的输出数据范围正确无误,np.unique(y_train)仅包含0和1
  • 检查每个像素是否仅分类为一个类别:(np.sum(y_train, axis=-1) == 1).all() == True
  • 检查您的图像是否不太偏向头等舱。 np.sum(y_train[:,:,:,0])不应大于np.sum(y_train[:,:,:,1:])
    • 如果是这样,请考虑配合class_weight参数,传递权重以平衡每个类的损失(有关使用方法,请查看fit上的keras文档)

答案 1 :(得分:0)

对于大多数细分项目,该模型对我来说效果很好,我对多类细分使用交叉熵,对二元类使用平滑骰子

def conv_block(tensor, nfilters, size=3, padding='same', initializer="he_normal"):
    x = Conv2D(filters=nfilters, kernel_size=(size, size), padding=padding, kernel_initializer=initializer)(tensor)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    x = Conv2D(filters=nfilters, kernel_size=(size, size), padding=padding, kernel_initializer=initializer)(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    return x


def deconv_block(tensor, residual, nfilters, size=3, padding='same', strides=(2, 2)):
    y = Conv2DTranspose(nfilters, kernel_size=(size, size), strides=strides, padding=padding)(tensor)
    y = concatenate([y, residual], axis=3)
    y = conv_block(y, nfilters)
    return y


def Unet(img_height, img_width, nclasses=3, filters=64):
# down
    input_layer = Input(shape=(img_height, img_width, 3), name='image_input')
    conv1 = conv_block(input_layer, nfilters=filters)
    conv1_out = MaxPooling2D(pool_size=(2, 2))(conv1)
    conv2 = conv_block(conv1_out, nfilters=filters*2)
    conv2_out = MaxPooling2D(pool_size=(2, 2))(conv2)
    conv3 = conv_block(conv2_out, nfilters=filters*4)
    conv3_out = MaxPooling2D(pool_size=(2, 2))(conv3)
    conv4 = conv_block(conv3_out, nfilters=filters*8)
    conv4_out = MaxPooling2D(pool_size=(2, 2))(conv4)
    conv4_out = Dropout(0.5)(conv4_out)
    conv5 = conv_block(conv4_out, nfilters=filters*16)
    conv5 = Dropout(0.5)(conv5)
# up
    deconv6 = deconv_block(conv5, residual=conv4, nfilters=filters*8)
    deconv6 = Dropout(0.5)(deconv6)
    deconv7 = deconv_block(deconv6, residual=conv3, nfilters=filters*4)
    deconv7 = Dropout(0.5)(deconv7) 
    deconv8 = deconv_block(deconv7, residual=conv2, nfilters=filters*2)
    deconv9 = deconv_block(deconv8, residual=conv1, nfilters=filters)
# output
    output_layer = Conv2D(filters=nclasses, kernel_size=(1, 1))(deconv9)
    output_layer = BatchNormalization()(output_layer)
    output_layer = Activation('softmax')(output_layer)

    model = Model(inputs=input_layer, outputs=output_layer, name='Unet')
    return model

答案 2 :(得分:0)

有时,问题与模型架构有关。在处理复杂的数据集进行细分时,需要增强模型架构。我在新数据集上遇到了相同的问题,而模型可以在另一个数据集上很好地工作。因此,我使用Res-Unet而不是Unet作为模型架构,并解决了问题。 希望这会有所帮助