我试图冻结免费训练的VGG16的图层(下面的'conv_base'),并在它们上面添加新图层以进行特征提取.我希望在(ret1)/之后(ret2)拟合模型之前从'conv_base'获得相同的预测结果,但事实并非如此.这是检查体重冻结的错误方法吗?
conv_base = applications.VGG16(weights='imagenet', include_top=False, input_shape=[150, 150, 3])
conv_base.trainable = False
Run Code Online (Sandbox Code Playgroud)
ret1 = conv_base.predict(np.ones([1, 150, 150, 3]))
Run Code Online (Sandbox Code Playgroud)
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'])
Run Code Online (Sandbox Code Playgroud)
m.fit_generator(train_generator, 100, validation_data=validation_generator, validation_steps=50)
Run Code Online (Sandbox Code Playgroud)
ret2 = conv_base.predict(np.ones([1, 150, 150, 3]))
Run Code Online (Sandbox Code Playgroud)
np.equal(ret1, ret2)
Run Code Online (Sandbox Code Playgroud)
这是一个有趣的案例.为什么会发生这样的事情是由以下因素引起的:
编译后你不能冻结整个模型,如果没有编译它就不会冻结
如果您设置了一个标志,model.trainable=False那么在编译时keras将所有图层设置为不可训练.如果在编译后设置此标志 - 那么它根本不会影响您的模型.相同 - 如果您在编译之前设置此标志,然后您将重用模型的一部分来编译另一个 - 它不会影响您重复使用的图层.因此,model.trainable=False只有当您按以下顺序应用它时才有效:
# model definition
model.trainable = False
model.compile()
Run Code Online (Sandbox Code Playgroud)
在任何其他情况下,它将无法按预期工作.
您必须分别冻结图层(在编译之前):
for l in conv_base.layers:
l.trainable=False
Run Code Online (Sandbox Code Playgroud)
如果这不起作用,则您可能应该使用新的顺序模型冻结图层。
如果模型中有模型,则应递归执行此操作:
def freezeLayer(layer):
layer.trainable = False
if hasattr(layer, 'layers'):
for l in layer.layers:
freezeLayer(l)
freezeLayer(model)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4336 次 |
| 最近记录: |