TensorFlow LSTM自编码器内部实现归一化损失过高问题咨询
问题核心原因
你写的两段代码实际并不等效,核心差异在于输入输出的尺度匹配逻辑错误,两个常见的触发场景如下:
- 如果你修改模型后依然喂入提前归一化后的
data_train作为输入:相当于对数据做了两次归一化,输入分布完全偏离LSTM的预期范围,导致模型拟合失效。 - 如果你修改模型后喂入原始未归一化的
data_train作为输入,但标签依然用原始数据:模型最后输出的是和归一化后数据同分布的结果(量级通常在±1区间),和原始数据的尺度差多个数量级,计算损失自然会出现1e3级别的异常值。
可行解决方案
根据你的使用需求可以选择以下任意一种方案调整:
方案1:保持拟合目标为归一化后数据
不需要修改模型结构,仅调整训练时的传入参数即可:
- 训练时输入喂原始未归一化的
data_train - 拟合的标签喂
normalizer(data_train),和第一种方案的损失计算逻辑完全对齐,损失值会回到1e-2的正常区间。
该方案的模型输出为归一化后的结果,实际部署使用时需要额外对输出做反归一化操作。
方案2:模型直接输出原始尺度的重构结果
在模型末尾增加反归一化层,让输出和原始输入尺度匹配:
normalizer = Normalization(axis=-1) normalizer.adapt(data_train) # adapt必须使用原始训练数据 inputs = Input(shape=[None, n_inputs]) x = normalizer(inputs) x = LSTM(4, return_sequences=True)(x) x = LSTM(2, return_sequences=True)(x) x = LSTM(2, return_sequences=True)(x) x = LSTM(4, return_sequences=True)(x) x = TimeDistributed(Dense(n_inputs))(x) # 反归一化映射回原始数据尺度 outputs = normalizer.inverse_transform(x) # 若TensorFlow版本低于2.6不支持inverse_transform,可替换为以下实现: # outputs = Lambda(lambda x: x * tf.sqrt(normalizer.variance) + normalizer.mean)(x) model = Model(inputs, outputs)
训练时直接传入原始未归一化的data_train作为输入和标签即可,损失量级和第一种方案完全一致,部署时可以直接拿到原始尺度的重构结果,无需额外处理。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

