如何基于gstat的cv.krige获取各折交叉验证的R²、RMSE、MAE统计值
解决留一法交叉验证cv.krige的指标统计问题
问题根源
你遇到的分位值完全一致的问题,是因为代码仅使用了留一法中**最后一个样本(最后一折)**的数据计算指标,而非所有折的结果。留一法交叉验证中,每个样本单独作为测试集,cv.krige返回的结果每行对应一个折的真实值(observed)和预测值(var1.pred),必须基于全量行数据计算统计汇总。
解决方案代码
以下代码严格使用gstat、Metrics包及自定义RSQUARE函数,实现所有折的指标统计:
# 加载依赖包 library(gstat) library(Metrics) # 自定义R²计算函数 RSQUARE <- function(obs, pred) { cor(obs, pred)^2 } # 示例:使用meuse数据集执行留一法交叉验证 data(meuse) coordinates(meuse) <- ~x+y cv_result <- cv.krige(zinc ~ 1, meuse, vgm(1, "Sph", 900, 1)) # 1. 计算每个折的单样本误差(MAE和RMSE,单样本下二者数值相同) cv_result$mae_per_fold <- abs(cv_result$observed - cv_result$var1.pred) cv_result$rmse_per_fold <- sqrt((cv_result$observed - cv_result$var1.pred)^2) # 2. 计算整体交叉验证指标(全局R²、RMSE、MAE) overall_metrics <- data.frame( Metric = c("R²", "RMSE", "MAE"), Value = c( RSQUARE(cv_result$observed, cv_result$var1.pred), rmse(cv_result$observed, cv_result$var1.pred), mae(cv_result$observed, cv_result$var1.pred) ) ) # 3. 对单折误差做统计汇总(分位数、极值) fold_metrics_summary <- data.frame( Metric = rep(c("单折MAE", "单折RMSE"), each = 5), Statistic = rep(c("最小值", "25分位数", "中位数", "75分位数", "最大值"), 2), Value = c( quantile(cv_result$mae_per_fold, c(0, 0.25, 0.5, 0.75, 1)), quantile(cv_result$rmse_per_fold, c(0, 0.25, 0.5, 0.75, 1)) ) ) # 输出结果 cat("=== 整体交叉验证指标 ===\n") print(overall_metrics, row.names = FALSE) cat("\n=== 单折误差统计汇总 ===\n") print(fold_metrics_summary, row.names = FALSE)
关键说明
- 留一法中单个样本的RMSE与MAE数值完全一致(单个误差的平方开根号等于绝对误差),因此二者的统计结果也会相同,属于正常现象。
- 全局R²基于所有真实值与预测值的相关系数平方,反映模型整体拟合能力,无需按折拆分统计。
- 避免错误:不要通过
tail()或索引取单个行数据计算指标,必须使用cv_result的全量observed和var1.pred列。
内容的提问来源于stack exchange,提问作者Foeke Boersma
相关产品推荐
相关产品推荐

