保存并加载模型优化器状态

我有一套相当复杂的模型,我正在训练,我正在寻找一种方法来保存和加载模型优化器状态 . "trainer models"由几个其他"weight models"的不同组合组成,其中一些具有共享权重,一些具有取决于训练师的冻结权重等 . 分享一个例子有点过于复杂,但总之,我无法停止和开始训练时使用 model.save('model_file.h5')keras.models.load_model('model_file.h5') .

如果训练已经完成,使用 model.load_weights('weight_file.h5') 可以很好地测试我的模型,但如果我尝试使用这种方法继续训练模型,那么损失甚至不会回到最后位置 . 我已经读过这是因为没有使用这种方法保存优化器状态是有意义的 . 但是,我需要一种方法来保存和加载我的教练模型的优化器的状态 . 似乎keras曾经有一个 model.optimizer.get_sate()model.optimizer.set_sate() 可以完成我所追求的目标,但似乎不再是这种情况(至少对于Adam优化器而言) . 当前的Keras还有其他解决方案吗?

回答(2)

2 years ago

您可以从 load_modelsave_model 函数中提取重要的行 .

要保存优化程序状态,请在 save_model 中:

# Save optimizer weights.
symbolic_weights = getattr(model.optimizer, 'weights')
if symbolic_weights:
    optimizer_weights_group = f.create_group('optimizer_weights')
    weight_values = K.batch_get_value(symbolic_weights)

要加载优化程序状态,请在 load_model 中:

# Set optimizer weights.
if 'optimizer_weights' in f:
    # Build train function (to get weight updates).
    if isinstance(model, Sequential):
        model.model._make_train_function()
    else:
        model._make_train_function()

    # ...

    try:
        model.optimizer.set_weights(optimizer_weight_values)

结合上面的行,这是一个例子:

  • 首先使模型适合5个时期 .
X, y = np.random.rand(100, 50), np.random.randint(2, size=100)
x = Input((50,))
out = Dense(1, activation='sigmoid')(x)
model = Model(x, out)
model.compile(optimizer='adam', loss='binary_crossentropy')
model.fit(X, y, epochs=5)

Epoch 1/5
100/100 [==============================] - 0s 4ms/step - loss: 0.7716
Epoch 2/5
100/100 [==============================] - 0s 64us/step - loss: 0.7678
Epoch 3/5
100/100 [==============================] - 0s 82us/step - loss: 0.7665
Epoch 4/5
100/100 [==============================] - 0s 56us/step - loss: 0.7647
Epoch 5/5
100/100 [==============================] - 0s 76us/step - loss: 0.7638
  • 现在保存权重和优化器状态 .
model.save_weights('weights.h5')
symbolic_weights = getattr(model.optimizer, 'weights')
weight_values = K.batch_get_value(symbolic_weights)
with open('optimizer.pkl', 'wb') as f:
    pickle.dump(weight_values, f)
  • 在另一个python会话中重建模型,并加载权重 .
x = Input((50,))
out = Dense(1, activation='sigmoid')(x)
model = Model(x, out)
model.compile(optimizer='adam', loss='binary_crossentropy')

model.load_weights('weights.h5')
model._make_train_function()
with open('optimizer.pkl', 'rb') as f:
    weight_values = pickle.load(f)
model.optimizer.set_weights(weight_values)
  • 继续模型培训 .
model.fit(X, y, epochs=5)

Epoch 1/5
100/100 [==============================] - 0s 674us/step - loss: 0.7629
Epoch 2/5
100/100 [==============================] - 0s 49us/step - loss: 0.7617
Epoch 3/5
100/100 [==============================] - 0s 49us/step - loss: 0.7611
Epoch 4/5
100/100 [==============================] - 0s 55us/step - loss: 0.7601
Epoch 5/5
100/100 [==============================] - 0s 49us/step - loss: 0.7594

2 years ago

将Keras升级到2.2.4并使用pickle为我解决了这个问题 . 随着keras发布2.2.3 Keras模型现在可以安全地进行酸洗 .