是否有可能从中间层(通常和Keras)开始训练CNN?

时间:2019-02-04 21:39:06

标签: keras transfer-learning

我正在使用mobilenet v2在图像上训练模型。我冻结了除几层外的所有层,然后添加了其他层来进行培训。我希望能够从中间层而不是从一开始就进行训练。我的问题:

  1. 是否可以提供最后一个冻结层的输出作为 训练的输入(它是(?,7,7,1280)的张量)?
  2. 如何从第一个受训对象开始指定培训 (非冻结)层?在这种情况下,请使用mbnetv2_conv.layer [153]。
  3. 在这种情况下,y_train是什么?我不太了解y_train 在培训过程中被使用-通常,什么时候 CNN会回到y_train吗?

    加载mobilenet v2

    image_size = 224 mbnetv2_conv = MobileNetV2(weights ='imagenet',include_top = False,input_shape =(image_size,image_size,3))

    冻结除最后3层之外的所有层

    对于mbnetv2_conv.layers [:-3]中的层:     layer.trainable = False

    创建模型

    model = models.Sequential() model.add(mbnetv2_conv) model.add(layers.Flatten()) model.add(layers.Dense(16,activation ='relu')) model.add(layers.Dropout(0.5)) model.add(layers.Dense(3,Activation ='softmax')) model.summary()

    从图像中构建一个数组(?,224,224,3)

    x_train = np.array(all_images)

    获取图层输出

    从keras导入后端为K get_last_frozen_layer_output = K.function([mbnetv2_conv.layers [0] .input],                               [mbnetv2_conv.layers [152] .output]) last_frozen_layer_output = get_last_frozen_layer_output([x_train])[0]

    编译模型

    从keras.optimizers导入SGD sgd = SGD(lr = 0.01,衰减= 1e-6,动量= 0.9,Nesterov = True) model.compile(loss ='categorical_crossentropy',optimizer = sgd,metrics = ['acc'])

    如何从特定层进行训练,y_train应该是什么?

    model.fit(last_frozen_layer_output,y_train,batch_size = 2,epochs = 10)

1 个答案:

答案 0 :(得分:0)

是的,可以。两种不同的方式。

首先,困难的方法使您可以构建两个新模型,一个包含所有冻结层,一个包含所有可训练层。将Flatten()层添加到仅冻结层模型中。然后,您将逐层复制来自mobilenet v2的权重,以填充仅冻结层模型的权重。然后,您将通过仅冻结层模型运行输入图像,并将输出以CSV或pickle格式保存到磁盘。现在,这是可训练层模型的输入,您可以像上面一样使用model.fit()命令对其进行训练。完成训练后,节省重量。然后,您将必须使用两组图层来构建原始模型,并将权重加载到每一层中,然后保存整个内容。大功告成!

但是,更简单的方法是使用以下方法将模型的权重与体系结构分开保存:

model.save_weights(filename)

然后在将其添加到新的空模型之前,修改MobileNetV2中图层的layer.trainable属性:

mbnetv2_conv = MobileNetV2(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
for layer in mbnetv2_conv.layers[:153]:
    layer.trainable = False
model = models.Sequential() 
model.add(mbnetv2_conv) 

然后重新加载砝码

newmodel.load_weights(filename)

这使您可以调整mbnetv2_conv模型中要进行动态训练的层,然后只需调用model.fit()即可继续训练。