使用Keras构建回归模型预测高值时MSE、MAE过高无法拟合高值如何解决
回归模型高值拟合差问题解决方案
1. 立刻修正输出层配置
你当前输出层使用了sigmoid激活函数,这是回归任务的典型错误:sigmoid的输出范围被强制限制在(0,1)区间,当数值接近区间上下限的时候会进入梯度饱和区,梯度近乎消失,根本无法拟合接近上限的高值样本。回归任务输出层不要加任何激活函数,直接用默认的linear即可。
2. 调整损失函数适配高值拟合需求
MSE损失会被占比更高的低值样本主导,模型为了整体损失最小会主动放弃拟合少数高值样本,可做如下调整:
- 优先换用Huber损失,平衡MSE和MAE的优势,对高值/异常值的敏感度更可控
- 也可以自定义加权损失,给高值区间的样本设置更高的损失权重,强制模型关注高值拟合效果
3. 优化大值域特征的预处理方式
对取值范围跨度极大的特征不要直接用MinMax归一化,会导致绝大多数样本的特征被压缩到接近0的区间,丧失区分度:
- 先对该列做
log(x+1)对数变换,拉平值域分布,放大高值区间的特征差异 - 如果预测目标y本身也是大值域分布,同样对y做对数变换,训练完成预测后再用指数运算还原真实值
4. 调整模型容量与训练参数
当前2层7神经元的网络容量远不足以匹配80万行数据的拟合需求:
- 隐藏层调整为3-4层,每层神经元数量设为16/32/64,激活函数保持relu即可,可加入少量Dropout层防止过拟合
- 优化器换用Adam,相比RMSprop更适配这类回归场景,可适当降低初始学习率到1e-4避免训练震荡
- 高值样本占比过低的话,训练时传入
sample_weight参数给高值样本加权,或对高值样本做过采样处理
修改后参考代码
import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout # 自定义Huber损失,delta可根据业务需求调整 def huber_loss(delta=1.0): def loss(y_true, y_pred): error = y_true - y_pred cond = tf.abs(error) < delta squared_loss = 0.5 * tf.square(error) linear_loss = delta * (tf.abs(error) - 0.5 * delta) return tf.where(cond, squared_loss, linear_loss) return loss model = Sequential() model.add(Dense(32, input_dim=num_input, activation='relu')) model.add(Dropout(0.1)) model.add(Dense(32, activation='relu')) model.add(Dense(16, activation='relu')) # 输出层无激活,使用默认linear model.add(Dense(1)) # 编译用Huber损失,更换Adam优化器 model.compile(loss=huber_loss(delta=1.0), optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4), metrics=['mse', 'mae']) # 如需给高值样本加权重,计算sample_weight数组后传入即可 # sample_weight = np.where(y_train > 高值阈值, 5, 1) # 高值样本权重设为普通样本的5倍 # history = model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, # validation_data=(x_val, y_val), sample_weight=sample_weight) history = model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=(x_val, y_val))
内容的提问来源于stack exchange,提问作者isa
相关产品推荐
相关产品推荐

