14

我正在尝试对我之前在 R 中构建的一些 glm 模型进行 10 倍交叉验证。尽管我已经阅读了很多帮助文件,但我cv.glm()对包中的函数有点困惑。boot当我提供以下公式时:

library(boot)
cv.glm(data, glmfit, K=10)

这里的“数据”参数是指整个数据集还是仅指测试集?

到目前为止,我看到的示例提供了“数据”参数作为测试集,但这并没有真正意义,例如为什么在同一个测试集上进行 10 折?他们都会给出完全相同的结果(我假设!)。

不幸的是?cv.glm,以一种模糊的方式解释它:

数据:包含数据的矩阵或数据框。行应该是案例,列对应于变量,其中之一是响应

我的另一个问题是关于$delta[1]结果的。这是 10 次试验的平均预测误差吗?如果我想得到每个折叠的错误怎么办?

这是我的脚本的样子:

##data partitioning
sub <- sample(nrow(data), floor(nrow(x) * 0.9))
training <- data[sub, ]
testing <- data[-sub, ]

##model building
model <- glm(formula = groupcol ~ var1 + var2 + var3,
        family = "binomial", data = training)

##cross-validation
cv.glm(testing, model, K=10)
4

2 回答 2

17

我对使用各种包的 10 折交叉验证方法总是有点谨慎。我有自己的简单脚本,可以为任何机器学习包手动创建测试和训练分区:

#Randomly shuffle the data
yourData<-yourData[sample(nrow(yourData)),]

#Create 10 equally size folds
folds <- cut(seq(1,nrow(yourData)),breaks=10,labels=FALSE)

#Perform 10 fold cross validation
for(i in 1:10){
    #Segement your data by fold using the which() function 
    testIndexes <- which(folds==i,arr.ind=TRUE)
    testData <- yourData[testIndexes, ]
    trainData <- yourData[-testIndexes, ]
    #Use test and train data partitions however you desire...
}
于 2014-07-04T20:23:45.877 回答
6

@Roman 在他的评论中提供了一些答案,但是,您的问题的答案是通过检查代码来提供的cv.glm

我相信这段代码将随机设置的数据拆分为 K 折叠,如果 K 不整除 n,则根据需要安排舍入:

if ((K > n) || (K <= 1)) 
    stop("'K' outside allowable range")
K.o <- K
K <- round(K)
kvals <- unique(round(n/(1L:floor(n/2))))
temp <- abs(kvals - K)
if (!any(temp == 0)) 
    K <- kvals[temp == min(temp)][1L]
if (K != K.o) 
    warning(gettextf("'K' has been set to %f", K), domain = NA)
f <- ceiling(n/K)
s <- sample0(rep(1L:K, f), n)

此处的该位显示增量值不是均方根误差。正如帮助文件所说The default is the average squared error function.,这是什么意思?我们可以通过检查函数声明来看到这一点:

function (data, glmfit, cost = function(y, yhat) mean((y - yhat)^2), 
    K = n) 

这表明在每一折内,我们计算误差平方的平均值,其中误差在通常意义上是在预测响应与实际响应之间。

delta[1]只是每个折叠的所有这些术语的 SUM的加权平均值cv.glm,请参阅我在代码中的内联注释:

for (i in seq_len(ms)) {
    j.out <- seq_len(n)[(s == i)]
    j.in <- seq_len(n)[(s != i)]
    Call$data <- data[j.in, , drop = FALSE]
    d.glm <- eval.parent(Call)
    p.alpha <- n.s[i]/n #create weighted average for later
    cost.i <- cost(glm.y[j.out], predict(d.glm, data[j.out, 
        , drop = FALSE], type = "response"))
    CV <- CV + p.alpha * cost.i # add weighted average error to running total
    cost.0 <- cost.0 - p.alpha * cost(glm.y, predict(d.glm, 
        data, type = "response"))
}
于 2015-04-07T09:43:47.060 回答