我有一个Keras模型,其中包含Embedding
、LSTM
和Dropout
层,以及keras_contrib
中的CRF
实现。
我试图恢复一个部分训练过的模型的训练,其权重我之前已经保存。然而,当我尝试通过keras_contrib
的save_load_utils.load_all_weights
加载之前训练过的模型时,我收到了以下错误。
第108行,在load_all_weights中:
model.optimizer.set_weights(optimizer_weight_values)
第113行,在set_weights中:
‘of the optimizer (‘ + str(len(params)) + ‘)’)
ValueError: 指定的权重列表长度(36)与优化器的权重数量(0)不匹配model.optimizer.set_weights(optimizer_weight_values)
显然,优化器权重的列表长度为0。在keras的optimizers.py实现中提到,set_weights“应该只在计算梯度后调用(否则优化器没有权重)。”
我想知道如何手动初始化优化器权重,以便我试图加载的模型权重可以覆盖它们。我考虑过用一个大小为1的虚拟批次训练模型一个周期,但还有没有其他更优雅的方法来实现这一点?
完整代码在Github上,但下面是我训练的模型,以提供一个简短的参考。
# 初始化vocab_size & embedding_weights# 初始化C, U, N, M, Hmodel = Sequential()embedding_layer = Embedding(vocab_size, N, weights=[embedding_weights], mask_zero=True, embeddings_regularizer=regularizers.l2(0.0001))model.add(TimeDistributed(embedding_layer, input_shape=(C, U)))model.add(TimeDistributed(Bidirectional(LSTM(M // 2, return_sequences=True, kernel_regularizer=regularizers.l2(0.0001)))))model.add(TimeDistributed(Dropout(0.2)))model.add(TimeDistributed(GlobalMaxPooling1D()))model.add(Bidirectional(LSTM(H // 2, return_sequences = True, kernel_regularizer=regularizers.l2(0.0001))))model.add(Dropout(0.2))crf = CRF(num_tags, sparse_target=False, kernel_regularizer=regularizers.l2(0.0001))model.add(crf)model.compile(optimizer, loss = crf.loss_function, metrics=[crf.accuracy])
回答:
我最终采取的措施几乎与我在问题中提到的一样。
我创建了一个小的虚拟训练和验证集,并训练模型一个周期,以便网络权重被初始化。然后我只需加载之前会话的权重并继续训练,使用keras_contrib.utils.save_load_utils
中的load_all_weights
。下面的代码示例大致描述了我使用的方法。
# 初始化real_training_set为包含(input, expected_result)的2元组if load_model_file is not None: # 初始化dummy_training_set为包含(input, expected_result)的2元组 model.fit_generator(batch_generator_function(dummy_training_set[0], dummy_training_set[1], ... ), epochs = 1) save_load_utils.load_all_weights(model, load_from_model_file)model.fit_generator(batch_generator_function(real_training_set[0], real_training_set[1], ... ), epochs = 1)
您可以在Github上查看实际代码。