在预训练模型之前添加转化层会产生ValueError

时间:2018-08-14 15:54:13

标签: python-3.x tensorflow keras conv-neural-network transfer-learning

我想将预训练的VGG16模型与特殊的输入块结合在一起,该输入块是输入层和卷积层。目标是在灰度图像上使用预先训练的RGB VGG16 imagenet模型:

from keras.applications.vgg16 import VGG16
from keras.layers.convolutional import Conv2D
from keras.layers import Input
from keras.models import Model

img_height = 299
img_width = 299

def input_block(img_height = 299, img_width = 299):
    input_shape = (img_height, img_width, 1)
    img_input = Input(shape=input_shape, name = 'grayscale_input_layer')
    x = Conv2D(3, (3,3),  padding= 'same', name = 'grayscale_RGB_layer')(img_input)
    return x

pretrained_model = VGG16(weights = 'imagenet', include_top=False, input_tensor = input_block(img_height, img_width))

VGG16()的权重初始化设置为'None'时,模型将正确构建,并具有以下所需结构:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
grayscale_input_layer (Input (None, 299, 299, 1)       0         
_________________________________________________________________
grayscale_RGB_layer (Conv2D) (None, 299, 299, 3)       30        
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 299, 299, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 299, 299, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 149, 149, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 149, 149, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 149, 149, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 74, 74, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 74, 74, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 74, 74, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 74, 74, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 37, 37, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 37, 37, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 37, 37, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 37, 37, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 18, 18, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 18, 18, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 18, 18, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 18, 18, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 9, 9, 512)         0         
=================================================================
Total params: 14,714,718
Trainable params: 14,714,718
Non-trainable params: 0
_________________________________________________________________
None

但是,当我将权重初始化设置为'imagenet'时, 我收到以下错误:

  

ValueError:您正在尝试将包含13层的权重文件加载到具有14层的模型中。

此错误是有道理的,因为我在VGG16模型之前添加了两层而不是一层。

作为一种解决方法,我尝试了以下方法:

def input_block_model(img_height = 299, img_width = 299):
    input_shape = (img_height, img_width, 1)
    img_input = Input(shape=input_shape, name = 'grayscale_input_layer')
    x = Conv2D(3, (3,3),  padding= 'same', name = 'grayscale_RGB_layer')(img_input)
    model = Model(img_input, x, name='input_block_model')
    return model

input_model = input_block_model(299,299)
pretrained_model = VGG16(weights = "imagenet", include_top=False)
combined_model = Model(input_model.input, 
pretrained_model(input_model.output))
print(combined_model.summary())

然后,模型结构为:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
grayscale_input_layer (Input (None, 299, 299, 1)       0         
_________________________________________________________________
grayscale_RGB_layer (Conv2D) (None, 299, 299, 3)       30        
_________________________________________________________________
vgg16 (Model)                multiple                  14714688  
=================================================================
Total params: 14,714,718
Trainable params: 14,714,718
Non-trainable params: 0
_________________________________________________________________
None

此结构的缺点是,我无法在VGG16模型中设置图层的属性。我想冻结该模型中的某些层,例如,我无法通过combined_model.layers访问这些层。有没有人有可行的解决方案,使得我可以像'None'初始化那样获得模型结构,但要使用经过预训练的ImageNet权重?

1 个答案:

答案 0 :(得分:0)

您可以使用combined_model.layers[2].layers冻结或训练图层,如上面的注释所述。您可以简化模型,如下所示:

```

img_input = Input(shape=(img_height, img_width, 1), name = 'grayscale_input_layer')
x = Conv2D(3, (3,3),  padding= 'same', name = 'grayscale_RGB_layer')(img_input)
x = VGG16(weights = None, include_top=False)(x)
model = Model(img_input, x)
model.summary()

for layer in model.layers[2].layers:
    layer.trainable = False

```

相关问题