堆叠LSTM序列自编码器调用autoencoder.fit()触发KeyError异常求解
看起来你这是在构建堆叠LSTM自编码器的时候踩了几个变量和形状匹配的坑,我帮你拆解下问题根源和修复方法:
一、直接触发KeyError的变量名错误
你在定义autoencoder和encoder的时候,误用了一个根本没定义的变量input_dim:
# 错误代码:input_dim是未定义的变量 autoencoder = keras.Model(input_dim, decoded) encoder = keras.Model(input_dim, encoded)
这里应该用你之前已经创建好的inputs变量(就是keras.Input(...)的返回值),改成下面这样就解决了第一个问题:
autoencoder = keras.Model(inputs, decoded) encoder = keras.Model(inputs, encoded)
二、Decoder输入形状完全不匹配
你的encoded层设置了return_sequences=False,所以它的输出形状是(batch_size, encoding_dim),但你定义解码器输入的时候多了一个timesteps维度:
# 错误形状:多了不必要的timesteps维度 encoded_input = keras.Input(shape=(timesteps, encoding_dim,))
正确的输入形状应该只保留编码维度,改成:
encoded_input = keras.Input(shape=(encoding_dim,))
三、Decoder构建时遗漏了RepeatVector层
原模型里解码流程是从RepeatVector层开始的,但你在手动构建decoder的时候直接跳过了这一层,导致后续LSTM层的输入形状完全对不上。正确的做法是先调用RepeatVector层,再依次调用后面的LSTM层。
为了避免数层索引出错,我建议给RepeatVector层加个名字,这样后续调用更稳妥:
# 给RepeatVector层命名 x = layers.RepeatVector(timesteps, name='repeat_vec')(encoded)
然后构建decoder的时候可以这样写:
decoder_input = keras.Input(shape=(encoding_dim,)) # 先调用RepeatVector层 x = autoencoder.get_layer('repeat_vec')(decoder_input) # 再依次调用后续的LSTM层 x = autoencoder.layers[8](x) x = autoencoder.layers[9](x) x = autoencoder.layers[10](x) x = autoencoder.layers[11](x) x = autoencoder.layers[12](x) x = autoencoder.layers[13](x) # 最后调用TimeDistributed输出层 decoder_output = autoencoder.layers[14](x) decoder = keras.Model(decoder_input, decoder_output)
四、额外解决你提到的NaN损失问题
你说简化版模型会出现NaN损失,这大概率是因为给LSTM用了relu激活函数。LSTM内部的门控机制天生更适配tanh或sigmoid,relu的硬饱和特性很容易引发梯度爆炸/消失,进而出现NaN。
建议把所有LSTM的激活函数改成tanh(这也是Keras LSTM的默认激活),同时可以把Adam优化器的学习率调小一点(比如1e-4),进一步避免梯度问题:
# 编码器和解码器的LSTM都用tanh x = layers.LSTM(320, activation='tanh', return_sequences=True)(inputs) # ...其他LSTM层同理 # 编译时用更小的学习率 autoencoder.compile(optimizer=keras.optimizers.Adam(learning_rate=1e-4), loss='mean_squared_error')
把这些修改都加上之后,你的模型应该就能正常训练,不会再触发KeyError,也能缓解NaN损失的问题了。
备注:内容来源于stack exchange,提问作者Albas

