恢复keras seq2seq模型

时间:2018-01-08 21:48:09

标签: python tensorflow machine-learning keras

我在这里使用keras seq2seq示例: https://github.com/keras-team/keras/blob/master/examples/lstm_seq2seq.py

我想保留词汇和解码器,以便稍后再加载它,并将其应用于新的序列。

虽然代码调用了model.save(),但这还不够,因为我可以看到解码设置引用了许多其他变量,这些变量是训练模型的深层指针:

encoder_model = Model(encoder_inputs, encoder_states)

decoder_state_input_h = Input(shape=(latent_dim,))
decoder_state_input_c = Input(shape=(latent_dim,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_outputs, state_h, state_c = decoder_lstm(
    decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)
decoder_model = Model(
    [decoder_inputs] + decoder_states_inputs,
    [decoder_outputs] + decoder_states)

我想翻译此代码,以确定从磁盘加载的模型中的encoder_inputs,encoder_states,latent_dim,decoder_inputs。可以假设我事先知道模型架构。有这么简单的方法吗?

更新: 我已经使用解码器构造代码并根据需要拉出层输入/输出取得了一些进展。

encoder_inputs = model.input[0] #input_1
decoder_inputs = model.input[1] #input_2
encoder_outputs, state_h_enc, state_c_enc = model.layers[2].output # lstm_1
_, state_h_dec, state_c_dec = model.layers[3].output # lstm_2
decoder_outputs = model.layers[4].output # dense_1

encoder_states = [state_h_enc, state_c_enc]
encoder_model = Model(encoder_inputs, encoder_states)

latent_dim = 256 # TODO: infer this from the model. Should match lstm_1 outputs.

decoder_state_input_h = Input(shape=(latent_dim,))
decoder_state_input_c = Input(shape=(latent_dim,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]

decoder_states = [state_h_dec, state_c_dec]

decoder_model = Model(
    [decoder_inputs] + decoder_states_inputs,
    [decoder_outputs] + decoder_states)

然而,当我尝试构建解码器模型时,我遇到了这个错误:

RuntimeError: Graph disconnected: cannot obtain value for tensor Tensor("input_1:0", shape=(?, ?, 96), dtype=float32) at layer "input_1". The following previous layers were accessed without issue: []

作为测试,我尝试了具有相同结果的Model(decoder_inputs,decoder_outputs)。我不清楚什么与图表断开连接,因为这些图层是从模型中加载的。

2 个答案:

答案 0 :(得分:4)

好的,我解决了这个问题,解码器正在产生合理的结果。在上面的代码中,我错过了解码器步骤中的一些细节,特别是它call()s LSTM和Dense图层以便连接它们。此外,新的解码器输入需要唯一的名称,因此它们不会与input_1和input_2发生冲突(这个细节闻起来像是一个keras bug)。

encoder_inputs = model.input[0] #input_1
encoder_outputs, state_h_enc, state_c_enc = model.layers[2].output # lstm_1
encoder_states = [state_h_enc, state_c_enc]
encoder_model = Model(encoder_inputs, encoder_states)

decoder_inputs = model.input[1] #input_2
decoder_state_input_h = Input(shape=(latent_dim,),name='input_3')
decoder_state_input_c = Input(shape=(latent_dim,),name='input_4')
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_lstm = model.layers[3]
decoder_outputs, state_h_dec, state_c_dec = decoder_lstm(
    decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h_dec, state_c_dec]
decoder_dense = model.layers[4]
decoder_outputs=decoder_dense(decoder_outputs)

decoder_model = Model(
    [decoder_inputs] + decoder_states_inputs,
    [decoder_outputs] + decoder_states)

这段代码的一大缺点是我们事先知道完整的架构。我想最终能够加载一个与架构无关的解码器。

答案 1 :(得分:1)

在Keras seq2seq示例的代码中,您将拥有完成的编码器和解码器模型。您可以将这些模型的体系结构和权重保存到磁盘并在以后加载它们。以下适用于我:

将模型保存到磁盘:

with open('encoder_model.json', 'w', encoding='utf8') as f:
    f.write(encoder_model.to_json())
encoder_model.save_weights('encoder_model_weights.h5')

with open('decoder_model.json', 'w', encoding='utf8') as f:
    f.write(decoder_model.to_json())
decoder_model.save_weights('decoder_model_weights.h5')

稍后加载编码器和解码器:

def load_model(model_filename, model_weights_filename):
    with open(model_filename, 'r', encoding='utf8') as f:
        model = model_from_json(f.read())
    model.load_weights(model_weights_filename)
    return model

encoder = load_model('encoder_model.json', 'encoder_model_weights.h5')
decoder = load_model('decoder_model.json', 'decoder_model_weights.h5')

在预测期间,您还需要许多其他数据,例如编码器/解码器令牌的数量,将字符映射到索引等的字典。您可以在训练之后将这些数据保存到文件中并稍后加载它们,就像模型一样。