使用caret训练MLP模型出现重采样性能指标缺失值的报错问题
报错触发核心原因
这个提示本质是交叉验证过程中,部分折上的模型训练失败,输出了非数值类的预测结果(NaN/Inf),导致无法计算对应折的RMSE性能值,最终触发caret的缺失值警告。结合你编写的代码,具体触发点有三个:
- 神经网络适配的输入尺度不匹配:
caret内置的mlp方法底层是调用nnet包实现的,nnet本身不会自动对输入特征做标准化处理。而Boston数据集的特征量纲差异极大(比如税价值域是200-700,一氧化氮浓度值域是0.3-0.8),大尺度输入很容易导致网络权重更新溢出,生成NaN输出,无法计算性能指标。 - 回归任务的参数传递失效:你代码中写的
linOut = T本身是nnet包用来开启线性输出(适配连续值回归)的参数,但因为没有和必要的训练参数绑定传递,很多时候这个参数不会被底层正确接收,导致MLP默认用sigmoid输出层把结果压在(0,1)区间。训练过程中权重更新容易发散,最终在部分交叉折上生成无法计算的无效输出。 - 调参和训练逻辑疏漏:你的调参网格只设置了隐藏层节点数
size,但caret内置mlp方法的必填调参维度包含权重衰减decay,参数缺失会导致部分折的模型初始化失败;同时训练时直接传入了全量Boston数据集,之前做的训练/测试分区完全没生效,逻辑上存在冗余。
可直接落地的解决步骤
按照以下顺序调整代码,就能从根源上消除这个警告:
- 补上特征预处理配置:在
train函数中加入preProcess = c("center", "scale"),在每次交叉折训练前自动对输入特征做中心化、标准化,统一特征尺度,避免网络权重溢出。 - 修正参数传递逻辑:通过函数参数传递通道把
linOut = TRUE、最大迭代次数maxit = 200等底层训练参数传给nnet,保证回归任务的线性输出层正常生效,同时给够迭代次数让模型收敛。 - 完善调参网格:把权重衰减参数
decay加入调参范围,稳定不同交叉折上的训练过程,降低发散概率。 - 修复训练集引用错误:把之前拆分得到的训练子集传入
train函数,避免数据泄露和冗余计算。 - 固定随机种子:在训练前设置随机种子,避免初始权重随机选择导致的偶发训练发散。
调整后的可运行代码参考:
library(datasets) library(MASS) library(caret) # 固定随机种子 set.seed(123) # 生成分区索引 DP = caret::createDataPartition(Boston$medv, p=0.75, list = FALSE) train = Boston[DP, ] test = Boston[-DP, ] # 训练MLP模型 mlp = caret::train( medv ~ ., data = train, method = "mlp", trControl = trainControl(method = "cv", number = 3), # 补全调参网格,加入权重衰减 tuneGrid = expand.grid(size = 1:3, decay = c(0, 0.01, 0.1)), # 加入标准化预处理 preProcess = c("center", "scale"), # 传递底层nnet的训练参数 linOut = TRUE, maxit = 200, metric = "RMSE" ) # 测试集预测 Yp = predict(mlp, newdata = test[, 1:13])
按照上述调整后,交叉验证的每一个折都能正常完成训练、输出有效预测值、计算得到有效RMSE,不会再弹出“存在缺失的重采样性能值”的警告。
内容的提问来源于stack exchange,提问作者therafafan
相关产品推荐
相关产品推荐

