Keras带注意力Seq2Seq文本摘要模型预测时报Graph disconnected错误
错误原因
你构建推理解码器时,注意力计算需要依赖编码器的全部序列输出encoder_outputs,但当前解码器的输入仅包含解码器输入和上一步的隐状态,没有将编码器输出作为独立输入传入,导致计算图无法关联到原编码器的输入张量,触发了图断开的报错。
修复方案
1. 修改编码器推理模型
编码器除了返回最后一步的隐状态、细胞状态外,额外返回编码器的全部序列输出,供后续注意力计算使用:
model = load_model("model_intro.h5") encoder_inputs = model.input[0] # 建议通过层名而非索引取输出,避免层顺序变动导致错误 encoder_outputs, forward_h, forward_c, backward_h, backward_c = model.layers[5].output state_h_enc = Concatenate()([forward_h, backward_h]) state_c_enc = Concatenate()([forward_c, backward_c]) # 编码器输出新增encoder_outputs encoder_model = Model(encoder_inputs, [encoder_outputs, state_h_enc, state_c_enc])
2. 修改解码器推理模型
新增编码器序列输出作为解码器的输入参数,注意力计算直接使用传入的编码器输出,不再绑定原模型的编码器输入张量:
# 新增编码器序列输出作为解码器输入 encoder_outputs_input = Input(shape=(max_text_len, latent_dim*2), name="encoder_outputs_input") decoder_inputs = model.input[1] decoder_state_input_h = Input(shape=(latent_dim*2,), name="input_3") decoder_state_input_c = Input(shape=(latent_dim*2,), name="input_4") decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c] decoder_emdedding = model.layers[6](decoder_inputs) decoder_lstm = model.layers[9] decoder_outputs, state_h_dec, state_c_dec = decoder_lstm(decoder_emdedding, initial_state=decoder_states_inputs) decoder_states = [state_h_dec, state_c_dec] # 注意力计算使用传入的encoder_outputs_input attention = dot([decoder_outputs, encoder_outputs_input], axes=[2, 2]) attention2 = Activation('softmax')(attention) context = dot([attention2, encoder_outputs_input], axes=[2,1]) decoder_outputs = Concatenate(axis=-1)([context, decoder_outputs]) decoder_dense = model.layers[-1] decoder_outputs = decoder_dense(decoder_outputs) # 解码器输入列表新增encoder_outputs_input decoder_model = Model( [decoder_inputs, encoder_outputs_input] + decoder_states_inputs, [decoder_outputs] + decoder_states )
3. 调整推理生成逻辑
生成文本前先调用编码器得到完整的编码器序列输出,每一步生成下一个token时将提前计算好的编码器输出传入解码器即可:
def decode_sequence(input_seq): # 预计算编码器输出和初始状态 enc_out, state_h, state_c = encoder_model.predict(input_seq, verbose=0) # 初始化解码器输入为<sos>起始符 target_seq = np.zeros((1, 1)) target_seq[0, 0] = target_word_index['<sos>'] decoded_sentence = '' stop_condition = False while not stop_condition: # 调用解码器时传入预计算的enc_out output_tokens, h, c = decoder_model.predict([target_seq, enc_out, state_h, state_c], verbose=0) # 取概率最高的token sampled_token_idx = np.argmax(output_tokens[0, -1, :]) sampled_token = reverse_target_word_index[sampled_token_idx] if sampled_token == '<eos>' or len(decoded_sentence.split()) > max_summary_len: stop_condition = True else: decoded_sentence += ' ' + sampled_token # 更新下一轮的解码器输入和状态 target_seq = np.zeros((1, 1)) target_seq[0, 0] = sampled_token_idx state_h, state_c = h, c return decoded_sentence.strip()
内容的提问来源于stack exchange,提问作者BlueMango
相关产品推荐
相关产品推荐

