You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Seq2Seq对话语言模型无法生成连贯句子问题求助

Seq2Seq对话模型生成随机单词问题修复

核心问题梳理

  1. 模型输入冗余与损失逻辑混乱
    模型定义时引入了未使用的output_decoder输入,训练时该输入完全无效,同时损失计算的标签与模型输出的对应关系错误。
  2. 训练数据对齐错误
    按照描述,y_tar_seq是带SOS/EOS的目标输出,y_out_seq是左移一位的解码器输入(应包含SOS),但训练时输入和标签的对应关系完全搞反。
  3. 生成函数多处逻辑错误
    • 问题文本转序列时错误拆分单词,导致序列格式异常
    • 预测时跳过词表第一个索引,导致生成的ID与词表不匹配
    • 用序列滚动更新回复,破坏了已生成token的顺序
  4. 训练策略不合理
    未设置早停机制,1000轮epoch易导致过拟合或无效训练,dropout比例可能过高影响模型收敛。

修复后的完整代码

import tensorflow as tf
import numpy as np

BATCH_SIZE = 32
EMBEDDING_DIM = 256
RNN_UNITS = 1024
EPOCHS = 100

# 数据处理(修正对齐关系)
x_seq = tokenizer.texts_to_sequences(x)
y_decoder_input = tokenizer.texts_to_sequences(y_tar)  # y_tar是带SOS的解码器输入
y_decoder_target = tokenizer.texts_to_sequences(y_out) # y_out是带EOS的目标输出

max_seq_length = max(max(len(seq) for seq in x_seq), max(len(seq) for seq in y_decoder_target))

x_seq = tf.keras.preprocessing.sequence.pad_sequences(x_seq, maxlen=max_seq_length, padding='post')
y_decoder_input = tf.keras.preprocessing.sequence.pad_sequences(y_decoder_input, maxlen=max_seq_length, padding='post')
y_decoder_target = tf.keras.preprocessing.sequence.pad_sequences(y_decoder_target, maxlen=max_seq_length, padding='post')

# 模型定义(移除冗余输入)
input_encoder = tf.keras.layers.Input(shape=(None,))
input_decoder = tf.keras.layers.Input(shape=(None,))

encoder_embedding = tf.keras.layers.Embedding(vocab_size, EMBEDDING_DIM)(input_encoder)
encoder_lstm = tf.keras.layers.LSTM(RNN_UNITS, return_state=True, dropout=0.1)
encoder_outputs, state_h, state_c = encoder_lstm(encoder_embedding)
encoder_states = [state_h, state_c]

decoder_embedding = tf.keras.layers.Embedding(vocab_size, EMBEDDING_DIM)(input_decoder)
decoder_lstm = tf.keras.layers.LSTM(RNN_UNITS, return_sequences=True, return_state=True, dropout=0.1)
decoder_outputs, _, _ = decoder_lstm(decoder_embedding, initial_state=encoder_states)

decoder_dense = tf.keras.layers.Dense(vocab_size, activation='softmax')
output = decoder_dense(decoder_outputs)

# 修正模型输入输出
model = tf.keras.models.Model([input_encoder, input_decoder], output)
model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False))

# 添加早停机制
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)
history = model.fit([x_seq, y_decoder_input], y_decoder_target, 
                    epochs=EPOCHS, batch_size=BATCH_SIZE, 
                    validation_split=0.2, callbacks=[early_stopping])

# 构建推理用模型(分离编码器和解码器)
encoder_model = tf.keras.models.Model(input_encoder, encoder_states)

decoder_state_input_h = tf.keras.layers.Input(shape=(RNN_UNITS,))
decoder_state_input_c = tf.keras.layers.Input(shape=(RNN_UNITS,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]

decemb_infer = tf.keras.layers.Embedding(vocab_size, EMBEDDING_DIM)(input_decoder)
decoder_outputs, state_h_infer, state_c_infer = decoder_lstm(decemb_infer, initial_state=decoder_states_inputs)
decoder_states_infer = [state_h_infer, state_c_infer]
decoder_outputs = decoder_dense(decoder_outputs)
decoder_model = tf.keras.models.Model([input_decoder] + decoder_states_inputs, [decoder_outputs] + decoder_states_infer)

def generate_response(question):
    # 处理输入问题
    question_seq = tokenizer.texts_to_sequences([question])
    question_seq = tf.keras.preprocessing.sequence.pad_sequences(question_seq, maxlen=max_seq_length, padding='post')
    states_value = encoder_model.predict(question_seq, verbose=0)
    
    # 初始化回复序列(SOS token)
    target_seq = np.zeros((1, 1))
    target_seq[0, 0] = tokenizer.word_index['sos']
    
    response_tokens = []
    for _ in range(max_seq_length):
        output_tokens, h, c = decoder_model.predict([target_seq] + states_value, verbose=0)
        sampled_token_index = np.argmax(output_tokens[0, -1, :])
        if sampled_token_index == tokenizer.word_index.get('eos', -1):
            break
        if sampled_token_index in tokenizer.index_word:
            response_tokens.append(tokenizer.index_word[sampled_token_index])
        
        # 更新序列和状态
        target_seq = np.zeros((1, 1))
        target_seq[0, 0] = sampled_token_index
        states_value = [h, c]
    
    return ' '.join(response_tokens)

关键修复点说明

  • 移除冗余输入:删除模型中未使用的output_decoder输入,简化模型结构
  • 修正数据对齐:确保解码器输入是带SOS的左移序列,目标输出是带EOS的完整序列
  • 重构推理模型:分离编码器和解码器,采用标准的Seq2Seq推理流程,逐步生成每个token并更新状态
  • 优化训练策略:添加早停机制防止过拟合,降低dropout比例帮助模型收敛
  • 修复生成逻辑:修正问题序列处理方式,移除错误的索引跳过和序列滚动逻辑

内容的提问来源于stack exchange,提问作者Tyron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:54:59