Keras训练LSTM文本生成模型时1个epoch后报CUDNN参数错误求助
这个CuDNN参数错误我之前做文本生成项目时也踩过坑,结合你的代码和报错信息,大概率是生成器逻辑、输入维度不匹配或者训练配置的问题,咱们一步步来修复:
1. 修复生成器的循环逻辑
你的生成器里有个明显的问题:当batch_size == len(lines)时会直接break,但训练时Keras的fit会持续从生成器取数据,直到完成指定的steps_per_epoch,如果生成器提前终止,会导致最后一批数据的维度异常,触发CuDNN的参数错误。正确的训练集生成器应该无限循环,遍历完所有样本后重置起始位置:
def generator(batch_size): total_samples = len(sequences) start = 0 while True: end = start + batch_size # 处理最后一批样本不足batch_size的情况 if end > total_samples: # 取剩余的所有样本 x = sequences[start:, :-1] y = sequences[start:, -1] y = to_categorical(y, num_classes=vocab_size) yield x, y # 重置起始位置,开始下一轮循环 start = 0 else: x = sequences[start:end, :-1] y = sequences[start:end, -1] y = to_categorical(y, num_classes=vocab_size) yield x, y start = end
2. 确保LSTM输入是3D张量
CuDNN加速的LSTM要求输入必须是3D张量(形状为(batch_size, timesteps, features)),而你的x目前是2D的((batch_size, timesteps)),这是触发该错误的常见原因。需要在生成器里给x增加一个特征维度(文本生成中每个时间步的特征数为1,因为是单个词的索引):
# 在生成器中生成x之后,添加这一行 x = x.reshape(x.shape[0], x.shape[1], 1)
同时,你的LSTM层的input_shape要对应这个3D形状,比如如果你的序列长度(去掉最后一个词后)是seq_len,那么LSTM层应该这样定义:
LSTM(units=256, input_shape=(seq_len, 1)) # seq_len是sequences[:,:-1]的列数
3. 匹配batch_size和steps_per_epoch
在调用model.fit时,必须明确设置steps_per_epoch,值为总样本数除以batch_size的整数部分,确保每个epoch刚好遍历完所有样本:
batch_size = 64 # 你可以根据内存调整这个值 steps_per_epoch = len(sequences) // batch_size model.fit( generator(batch_size), epochs=10, steps_per_epoch=steps_per_epoch )
4. 检查版本兼容性(可选)
如果上面的步骤都试过还是报错,可能是TensorFlow和CuDNN的版本不兼容导致的。你可以对照TensorFlow官方的版本对照表,确认你的CuDNN版本和TF版本匹配,比如TF 2.10对应CuDNN 8.6,TF 2.11对应CuDNN 8.7等。如果不匹配,可以升级或降级对应的库。
5. 验证输出维度匹配
最后再确认:
to_categorical(y, num_classes=vocab_size)的输出维度是(batch_size, vocab_size)- 模型最后一层是
Dense(vocab_size, activation='softmax'),确保两者维度完全一致
按照这些步骤调整后,应该就能解决这个CuDNN参数错误了。
内容的提问来源于stack exchange,提问作者Dilshan Manathunge

