簡體   English   中英

Keras Unet + VGG16的預測都是一樣的

[英]Keras Unet + VGG16 predictions are all the same

我正在Keras用VGG16(解碼器部分)訓練U-Net。 該模型訓練良好且正在學習 - 我看到逐步改進驗證集。

但是,當我嘗試在圖像上調用predict時,我會收到所有值相同的矩陣。

以下是型號:

class Gray2VGGInput(Layer):
    """Custom conversion layer"""
    def build(self, x):
        self.image_mean = K.variable(value=np.array([103.939, 116.779, 123.68]).reshape([1,1,1,3]).astype('float32'), 
                                     dtype='float32', 
                                     name='imageNet_mean' )
        self.built = True
        return
    def call(self, x):
        rgb_x = K.concatenate([x,x,x], axis=-1 )
        norm_x = rgb_x - self.image_mean
        return norm_x

    def compute_output_shape(self, input_shape):
        return input_shape[:3] + (3,)


def UNET1_VGG16(img_rows=864, img_cols=1232):
    ''' 
    UNET with pretrained layers from VGG16
    '''
    def upsampleLayer(in_layer, concat_layer, input_size):
        '''
        Upsampling (=Decoder) layer building block
        Parameters
        ----------
        in_layer: input layer
        concat_layer: layer with which to concatenate
        input_size: input size fot convolution
        '''
        upsample = Conv2DTranspose(input_size, (2, 2), strides=(2, 2), padding='same')(in_layer)    
        upsample = concatenate([upsample, concat_layer])
        conv = Conv2D(input_size, (1, 1), activation='relu', kernel_initializer='he_normal', padding='same')(upsample)
        conv = BatchNormalization()(conv)
        conv = Dropout(0.2)(conv)
        conv = Conv2D(input_size, (1, 1), activation='relu', kernel_initializer='he_normal', padding='same')(conv)
        conv = BatchNormalization()(conv)
        return conv

    #--------
    #INPUT
    #--------
    #batch, height, width, channels
    inputs_1 = Input((img_rows, img_cols, 1))

    #-----------------------
    #INPUT CONVERTER & VGG16
    #-----------------------
    inputs_3 = Gray2VGGInput(name='gray_to_rgb')(inputs_1)  #shape=(img_rows, img_cols, 3)
    base_VGG16 = VGG16(include_top=False, weights='imagenet', input_tensor=inputs_3)

    #--------
    #DECODER
    #--------
    c1 = base_VGG16.get_layer("block1_conv2").output #(None, 864, 1232, 64)
    c2 = base_VGG16.get_layer("block2_conv2").output #(None, 432, 616, 128) 
    c3 = base_VGG16.get_layer("block3_conv2").output #(None, 216, 308, 256) 
    c4 = base_VGG16.get_layer("block4_conv2").output #(None, 108, 154, 512) 

    #--------
    #BOTTLENECK
    #--------
    c5 = base_VGG16.get_layer("block5_conv2").output #(None, 54, 77, 512)

    #--------
    #ENCODER
    #--------    
    c6 = upsampleLayer(in_layer=c5, concat_layer=c4, input_size=512)
    c7 = upsampleLayer(in_layer=c6, concat_layer=c3, input_size=256)
    c8 = upsampleLayer(in_layer=c7, concat_layer=c2, input_size=128)
    c9 = upsampleLayer(in_layer=c8, concat_layer=c1, input_size=64)

    #--------
    #DENSE OUTPUT
    #--------
    outputs = Conv2D(1, (1, 1), activation='sigmoid')(c9)

    model = Model(inputs=inputs_1, outputs=outputs)

    #Freeze layers
    for layer in model.layers[:16]:
        layer.trainable = False

    print(model.summary())

    model.compile(optimizer='adam', 
                  loss=fr.diceCoefLoss, 
                  metrics=[fr.diceCoef])

    return model

然后,我加載模型並調用predict

model = un.UNET1_VGG16()

pth_to_model = PTH_OUTPUT + 'weights__L_01.h5'
model.load_weights(pth_to_model) 

preds = model.predict(X_image_test, verbose=1)

但是,結果如下:

[[0.4567569 0.4567569 0.4567569 ... 0.4567569 0.4567569 0.4567569]
 [0.4567569 0.4567569 0.4567569 ... 0.4567569 0.4567569 0.4567569]
 [0.4567569 0.4567569 0.4567569 ... 0.4567569 0.4567569 0.4567569]
 ...
 [0.4567569 0.4567569 0.4567569 ... 0.4567569 0.4567569 0.4567569]
 [0.4567569 0.4567569 0.4567569 ... 0.4567569 0.4567569 0.4567569]
 [0.4567569 0.4567569 0.4567569 ... 0.4567569 0.4567569 0.4567569]]

我在沒有VGG16的情況下使用與其他型號相同的程序,一切運行良好。 因此,我認為與VGG16有關的事情是錯誤的。 也許輸入層,我轉換為“假”RGB圖像?

問題在於VGG凍結層。 如果您的數據集與imagenet完全不同,也許您應該端到端地訓練整個模型。 而且,顯然,如果你凍結BatchNormalization圖層,它們可能會很奇怪。 供參考,請參閱此討論

如果你訓練你的網絡有一些特定的約束(例如你減去平均值),當你測試你的網絡時(因為通過測試你也可以通過網絡進行前向傳遞),你需要減去平均值(就像在訓練中一樣) 。

這可以解決您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM