R语言使用nnet函数训练模型输出拟合值全为0如何解决
问题原因
- 核心原因1:
nnet函数默认输出层使用sigmoid激活函数,仅当设置参数linout=TRUE时才会对回归任务使用线性输出。你未配置该参数,输出值会被强制压缩到(0,1)区间,结合你给出的模型权重参数,隐层到输出层的计算结果经过sigmoid激活后会被压缩到接近0的极小值,和你的因变量实际范围完全不匹配。 - 原因2:输入特征尺度差异过大,
ann_t1取值在-4左右,ann_t2、ann_t3取值在0附近,尺度差异会导致神经网络权重更新偏向大尺度特征,训练后隐层输出很容易进入激活函数饱和区,最终输出全部接近0。 - 原因3:因变量本身数值极小,你的
realized1最大值仅为0.02左右,本身就接近0,叠加sigmoid的压缩效应后,拟合值直接显示为0。
修复方案
- 第一步:回归任务调用
nnet时必须添加linout=TRUE参数,关闭输出层的sigmoid激活,使用线性输出适配回归任务,修改后的代码如下:
nnet(realized1~ann_t1+ann_t2+ann_t3, data=df2_input, size=2, linout=TRUE)
- 第二步:对输入特征和因变量做标准化/归一化处理,把所有特征缩放到相同尺度,训练完成后再把预测值逆缩放回原尺度,示例代码如下:
# 全数据集标准化 df2_input_scaled <- as.data.frame(scale(df2_input)) # 训练模型 model <- nnet(realized1~ann_t1+ann_t2+ann_t3, data=df2_input_scaled, size=2, linout=TRUE) # 拟合值逆缩放回原尺度 fitted_scaled <- predict(model) fitted_original <- fitted_scaled * sd(df2_input$realized1) + mean(df2_input$realized1)
- 第三步:可根据效果调整参数:添加
decay参数设置权重正则化,避免权重过大导致输出饱和;调大size参数增加隐层神经元数量提升拟合能力;如果模型提示未收敛,可增大maxit参数提升迭代次数,比如maxit=1000。
内容的提问来源于stack exchange,提问作者oercim
相关产品推荐
相关产品推荐

