基于torch.autograd训练的RNN生成无意义内容,求调试方案
问题:RNN训练后生成随机字符串的调试方向
模型结构
model = keras.Sequential([ keras.layers.Input(shape=(SEQ_LENGTH,), batch_size=batch_size), keras.layers.Embedding(len(vocabulary), 256), keras.layers.LSTM(1024, return_sequences=True, stateful=stateful), keras.layers.Dense(len(vocabulary)) ])
训练流程
loss_fn = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=5e-3) for i in range(1000): inputs, targets = random_inputs_and_targets(vectorized_songs, seq_length=SEQ_LENGTH, batch_size=BATCH_SIZE) predictions = model(inputs) loss = loss_fn(predictions.permute(0, 2, 1), torch.from_numpy(targets).long()) loss.backward() optimizer.step() optimizer.zero_grad()
模型保存与加载
torch.save(model.state_dict(), os.path.join(cwd, "model.pt")) trained_model = build_model(1, True) trained_model.load_state_dict(torch.load(os.path.join(cwd, "model.pt"))) trained_model.eval()
文本生成代码
input_eval = [char_to_index[s] for s in start_string] input_eval = torch.unsqueeze(torch.tensor(input_eval), 0) text_generated = [] for i in range(generation_length): predictions = torch.squeeze(model(input_eval), 0) predicted_index = torch.multinomial(softmax(predictions, dim=0), 1, replacement=True)[-1, 0] input_eval = torch.unsqueeze(torch.unsqueeze(predicted_index, 0), 0) text_generated.append(index_to_char[predicted_index.item()]) return start_string + ''.join(text_generated)
问题现象
训练1000轮后,损失从约4.42降至0.78,但生成的文本是类似XwQ5>ab>6q6S(z']!<hxaG4..M= (=ERp/xJmS|qIh_CzbM0D-N 6Yc=Ei[tcodBsEKfW<WZ5Jb("u1rrGLcFIk"PVk.'FEII:(qu7.nFbw^3/RY2LyrW的随机字符串,完全不符合ABC记谱法的预期。
调试建议
- 修正框架混用问题:模型用Keras定义,但训练用PyTorch的损失函数、优化器和反向传播流程,两个框架的张量处理、参数更新逻辑不兼容,这是核心问题。必须统一用PyTorch构建模型,或者改用Keras的训练流程,禁止跨框架混用。
- 核对模型加载后的参数一致性:加载参数后,对比原模型和加载后模型的关键参数(如Embedding层权重、LSTM层的权重矩阵)是否完全一致,避免batch_size变更导致的参数维度不匹配。
- 修正生成时的模型调用对象:生成代码里用的是
model(input_eval),但实际应该用加载后的trained_model,变量名错误会导致调用未加载参数的模型或训练时的旧模型。 - 检查隐藏状态的处理逻辑:
- 训练时如果
stateful=False,每次batch都会重置隐藏状态;生成时用stateful=True,需要确保初始隐藏状态正确初始化,且每一步生成后状态被保留。 - 生成时输入序列长度从训练时的
SEQ_LENGTH变为1,要确认LSTM层在不同序列长度下的行为是否符合预期,尤其是stateful模式下的状态传递。
- 训练时如果
- 验证训练集上的实际预测效果:不要只看损失值,随机抽取训练集中的输入,让模型预测下一个字符,查看预测结果是否符合ABC记谱法的规律,确认模型是否真的学到有效模式,而非仅损失下降但未拟合特征。
- 确认softmax的维度正确性:生成时
softmax(predictions, dim=0)是否匹配训练时的维度逻辑?如果输入长度为1时predictions是(1, vocab_size),dim=0是正确的,但要和训练时的输出维度对齐。 - 临时调整生成策略排查问题:暂时去掉multinomial采样,直接取预测概率最大的字符(argmax),观察生成结果是否有规律,排除采样策略导致的随机性干扰。
内容的提问来源于stack exchange,提问作者yaskovdev
相关产品推荐
相关产品推荐

