TensorFlow回归模型对所有输入输出相同预测值问题求助
模型预测输出固定值的问题排查与解决
问题描述
用指定训练数据训练Keras回归模型后,对所有测试输入,模型均输出固定数值对[1128.1345 618.5919],预期输出需接近数据集中reference__x和reference__y列的真实值。
当前模型代码
import tensorflow as tf normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(source_data) model = tf.keras.models.Sequential([ normalizer, tf.keras.layers.Dense(128, input_shape=(source_data.shape[1],), activation="sigmoid"), tf.keras.layers.Dropout(0.1), tf.keras.layers.Dense(64, activation="relu"), tf.keras.layers.Dropout(0.1), tf.keras.layers.Dense(32, activation="relu"), tf.keras.layers.Dense(16, activation="relu"), tf.keras.layers.Dense(8, activation="relu"), tf.keras.layers.Dense(4, activation="relu"), tf.keras.layers.Dense(2, activation="relu"), tf.keras.layers.Dense(2) ]) model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.1), loss="mape") model.fit(source_data, source_data_reference, epochs=50)
已尝试的调整及结果
- 移除网络层:输出变为其他固定数值对
- 调整学习率(范围0.0001至10):每次调整得到不同的固定值
- 修改训练轮数(3至1000):轮数极低时预测值有差异但完全不符合预期;部分参数组合下预测值接近预期值的均值
- 更换损失函数(mae、mape、mse):仍输出固定数值对
问题根源与解决方法
1. 网络结构冗余引发梯度消失
模型堆叠了8层全连接层,中间大量使用ReLU激活,极易出现梯度消失问题——反向传播时梯度在深层网络中快速衰减,模型无法学习到输入与输出的关联,最终只能输出接近训练集标签均值的固定值。
修复方案:
大幅简化网络结构,保留2-3层全连接层即可:
model = tf.keras.models.Sequential([ normalizer, tf.keras.layers.Dense(64, activation="relu"), tf.keras.layers.Dense(32, activation="relu"), tf.keras.layers.Dense(2) ])
2. 初始学习率过高
Adam优化器的合理学习率通常在0.0001-0.001之间,你设置的0.1远超出合理范围,会导致梯度爆炸,参数更新混乱,最终收敛到无意义的局部最优解(固定输出)。
修复方案:
将学习率调整为0.001或更小,同时监控训练损失曲线:
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss="mse")
3. 输入特征有效性不足
检查输入特征与标签的相关性:
- 计算每个输入特征与
reference__x、reference__y的皮尔逊相关系数,移除相关性极低(绝对值<0.1)的特征 - 确认归一化逻辑一致:预测时的输入数据必须使用训练时适配好的
normalizer,不能重新适配测试数据
4. 训练过程缺乏监控
训练时未验证模型泛化能力,无法判断模型是否有效拟合:
- 添加验证集,同时监控训练集和验证集的损失变化:
model.fit(source_data, source_data_reference, epochs=100, validation_split=0.2, verbose=1)
如果训练集损失始终居高不下,说明模型未学到规律;如果训练集损失低但验证集损失高,才是过拟合问题(当前情况更偏向未拟合)
5. 激活函数选择不当
第一层使用Sigmoid激活,归一化后的输入经过Sigmoid后,输出容易集中在0.5附近,导致后续层的输入缺乏区分度,模型难以学习有效特征。
修复方案:
将第一层的激活函数替换为ReLU,或直接去掉第一层的激活:
tf.keras.layers.Dense(128, input_shape=(source_data.shape[1],), activation="relu"),
内容的提问来源于stack exchange,提问作者adamski234
相关产品推荐
相关产品推荐

