Входной слой для VGG16 в Керасе - PullRequest
0 голосов
/ 03 мая 2019

Я создаю сеть U-Net, и я хотел бы использовать предварительно обученную модель (VGG16) для части декодера.

Проблема в том, что у меня есть изображения в градациях серого, а VGG работает с RGB.

Я нашел функцию для преобразования ее в RGB (путем объединения):

from keras.layers import Layer
from keras import backend as K

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,)

Но мне не удается подключить его к модели. Gray2VGGInput - это слой, поэтому Я ищу способ подключения этого слоя к слоям из VGG . Ниже моя попытка:

def UNET1_VGG16():
    ''' 
    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

    img_rows = 864
    img_cols = 1232

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

    #--------
    #VGG16 BASE
    #--------
    #Prepare net
    base_VGG16 = VGG16(input_tensor=inputs_3, 
                       include_top=False, 
                       weights='imagenet')

    #----------------
    #INPUT CONVERTER
    #----------------
    #This is the problematic part

    vgg_inputs_3 = Gray2VGGInput(name='gray_to_rgb')(inputs_1)

    model_input = Model(inputs=[inputs_1], outputs=[vgg_inputs_3])

    new_outputs = base_VGG16(model_input.output)
    new_inputs = Model(inputs_1, new_outputs)

    #--------
    #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=[new_inputs.input], 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 

Я получаю следующую ошибку:

ValueError: График отключен: невозможно получить значение для тензорного тензора ("input_14: 0", shape = (?, 864, 1232, 3), dtype = float32) на слое "input_14". Следующие предыдущие слои были доступны без проблем: []

Ответы [ 2 ]

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

Я думаю, что вам не нужно многократные входы, скорее передайте вывод слоя Gray2VGGInput в качестве ввода в модель VGG16. Я думаю, как вы получаете выходные тензоры из модели VGG16 в порядке. Вот что я могу предложить:

from keras.applications import VGG16


inputs_1 = Input(shape=(img_rows, img_cols, 1))
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)
... 
... and so on

Модель можно назвать

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

Вы можете попробовать и сообщить мне, если это работает. Я не проверял это, поэтому могут быть ошибки.

0 голосов
/ 04 мая 2019

Изменение:

model_input = Model(inputs=[inputs_1], outputs=[vgg_inputs_3]) 

Для

model_input = Model(inputs=[vgg_inputs_3] etc...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...