You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R包nnet训练神经网络新数据预测失准是否由过拟合导致?

问题定位

你遇到的问题同时包含R语言语法使用错误和神经网络通用认知错误,前者是导致结果异常的核心原因,后者是潜在风险。

1. 两个直接导致结果异常的R代码错误

错误1:训练集测试集拆分完全失效

你拆分数据时的subset调用写错了判断逻辑:

# 错误写法
df_train = subset(df, train = TRUE)
df_test = subset(df, train = FALSE)

subset()的第二个参数接收逻辑筛选条件,你写的单等号=是赋值操作——执行时会直接把所有行的train列设为你赋的值,根本没有按之前生成的7:3拆分标记筛选数据。你之前看到的“测试集预测效果好”,本质是在和训练集同源、甚至完全重叠的数据上做的验证,完全不具备泛化代表性。
正确拆分需要用双等号做逻辑判断:

df_train = subset(df, train == TRUE)
df_test = subset(df, train == FALSE)

错误2:新数据预测时列名不匹配触发R的变量查找机制

你训练模型用的是公式接口y ~ x,predict时要求传入的新数据集必须包含名为x的特征列,但你生成的新数据集df2列名是x2、y2,根本没有x列。
R的公式接口在newdata中找不到对应列时,不会直接报错,而是会自动到全局环境中搜索同名变量——也就是你最开始生成的第一版x,完全没有用到新生成的x2数据,预测结果自然完全错位。
修正方式很简单,新数据集的特征列名要和训练集保持一致:

df2 = data.frame(y = y2, x = x2)

2. 神经网络相关的认知误区

你提到“认为做训练-测试集拆分即可避免过拟合”,这个认知是错的:

  • 训练-测试集拆分的作用是检测过拟合,即让你发现模型在训练集和未见过的测试集上的效果差距,本身没有任何防止过拟合的作用。
  • 你当前设置的单隐藏层60个节点对于单输入的简单拟合任务来说容量过高,且没有加任何正则约束(权重衰减、提前停止等),哪怕修正了代码错误,也很容易出现过拟合:模型会记住训练集的局部噪声,而非学到真实的y~x映射关系,在新数据上的效果会明显差于测试集。
  • 想要降低过拟合风险,可以给nnet加decay参数设置权重衰减,或者适当减少隐藏层节点数、设置早停规则。

修正后可正常运行的完整代码

set.seed(123)
n = 1e3
x = rnorm(n)
y = 1 + 3*sin(x/2) + 15*cos(pi*x) + rnorm(n = length(x))
df = data.frame(y,x)
df$train = sample(c(TRUE, FALSE), length(y), replace=TRUE, prob=c(0.7,0.3))
# 修正拆分逻辑
df_train = subset(df, train == TRUE)
df_test = subset(df, train == FALSE)

library(nnet)
# 加权重衰减正则抑制过拟合
nn = nnet(y~x, data = df_train, size = 60, linout=TRUE, decay = 0.01, maxit = 200) 
yhat_nn = predict(nn, newdata = df_test)
plot(df_test$x,df_test$y)
points(df_test$x, yhat_nn, col = 'blue')

# 新数据列名和训练集对齐
x2 = rnorm(n)
y2 = 1 + 3*sin(x2/2) + 15*cos(pi*x2) + rnorm(n = length(x2))
df2 = data.frame(y = y2, x = x2)
plot(df2$x, df2$y)
points(df2$x, predict(nn, newdata = df2), col = 'blue')

内容的提问来源于stack exchange,提问作者invictus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:00:49