不应该是model.trainable =模型下的假冻结权重?

时间:2017-11-09 14:17:24

标签: keras keras-2

我正在尝试冻结免费训练的VGG16图层(下面的'conv_base')并在其上添加新图层以进行特征提取。 我希望在(ret1)/之后(ret2)拟合模型之前从'conv_base'获得相同的预测结果,但事实并非如此。 这是检查体重冻结的错误方法吗?

加载VGG16并设置为无法处理

conv_base  = applications.VGG16(weights='imagenet', include_top=False, input_shape=[150, 150, 3]) 
conv_base.trainable = False

模型拟合前的结果

ret1 = conv_base.predict(np.ones([1, 150, 150, 3]))

在VGG16顶部添加图层并编译模型

model = models.Sequential()
model .add(conv_base)
model .add(layers.Flatten())
model .add(layers.Dense(10, activation='relu'))
model .add(layers.Dense(1, activation='sigmoid'))
m.compile('rmsprop', 'binary_crossentropy', ['accuracy'])

适合模型

m.fit_generator(train_generator, 100, validation_data=validation_generator, validation_steps=50)
模型拟合后的

结果

ret2 = conv_base.predict(np.ones([1, 150, 150, 3]))

希望这是真的,但事实并非如此。

np.equal(ret1, ret2)

3 个答案:

答案 0 :(得分:7)

这是一个有趣的案例。为什么会发生这样的事情是由以下因素引起的:

你不能在编译后冻结整个模型,如果没有编译它就不会冻结

如果您设置了一个标记model.trainable=False,那么在编译keras时,所有图层都将无法训练。如果在编译后设置此标志 - 那么它根本不会影响您的模型。相同 - 如果您在编译之前设置此标志,然后您将重用模型的一部分来编译另一个 - 它不会影响您重复使用的图层。因此model.trainable=False仅在您按以下顺序应用时才有效:

# model definition
model.trainable = False
model.compile()

在任何其他情况下,它都无法按预期工作。

答案 1 :(得分:4)

您必须单独冻结图层(编译前):

for l in conv_base.layers: 
    l.trainable=False

如果这不起作用,您应该使用新的顺序模型来冻结图层。

如果模型中有模型,则应以递归方式执行此操作:

def freezeLayer(layer):
    layer.trainable = False
    if hasattr(layer, 'layers'):
        for l in layer.layers:
            freezeLayer(l)

freezeLayer(model)

答案 2 :(得分:1)

评价最高的答案不起作用。根据Keras官方文档(https://keras.io/getting-started/faq/)的建议,应按层执行。尽管模型有一个参数“可训练”,但可能尚未实现。最安全的方法是执行以下操作:

for layer in model.layers:
    layer.trainable = False
model.compile()