Keras Unet + VGG16 все прогнозы одинаковы - PullRequest
1 голос
/ 12 мая 2019

Я тренирую U-Net с VGG16 (часть декодера) в Керасе.Модель хорошо тренируется и учится - я вижу постепенное улучшение набора проверки.

Однако, когда я пытаюсь вызвать 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-изображение?

Ответы [ 2 ]

2 голосов
/ 18 мая 2019

Проблема с VGG замороженными слоями.Возможно, вам следует обучить всю модель из конца в конец, если ваш набор данных сильно отличается от imagenet.Также, очевидно, если вы замораживаете BatchNormalization слои, они могут вести себя странно.Для справки см. обсуждение .

1 голос
/ 12 мая 2019

Если вы тренируете свою сеть с некоторыми конкретными ограничениями (например, вычитаете среднее значение), когда вы тестируете свою сеть (поскольку при тестировании вы также делаете прямой проход через сеть), вам необходимо вычесть средние значения (какв процессе обучения).

Это может решить вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...