【问题标题】:`predict` error while doing n-fold cross-validation for my GLM为我的 GLM 进行 n 次交叉验证时出现“预测”错误
【发布时间】:2023-04-03 16:05:02
【问题描述】:

我正在运行这个函数来进行 n 次交叉验证。错误分类率不会随折叠而变化,例如如果我跑 10 或 50。我也会收到警告:

“警告信息:

'newdata' 有 19 行,但找到的变量有 189 行"

如果我运行代码而不是函数的一部分,它就是我想要的 -> 例如对于 folds==1,它提取 10%,在 90% 的数据上运行模型,并预测另外 10%。 有没有人知道为什么它没有显示变量和折叠次数的变化?

library("MASS")  
data(birthwt)
data=birthwt

n.folds=10

jim = function(x,y,n.folds,data){

  for(i in 1:n.folds){
    folds <- cut(seq(1,nrow(data)),breaks=n.folds,labels=FALSE)      
    testIndexes <- which(folds==i,arr.ind=TRUE)
    testData <- data[testIndexes, ]
    trainData <- data[-testIndexes, ]
    glm.train <- glm(y ~ x, family = binomial, data=trainData)
    predictions=predict(glm.train, newdata =testData, type='response')
    pred.class=ifelse(predictions< 0, 0, 1)
    }

  rate=sum(pred.class!= y) / length(y)
  print(head(rate))
  }

jim(birthwt$smoke, birthwt$low, 10, birthwt)

【问题讨论】:

  • 谢谢你 - 预测应该是 (
  • 我希望 pred.class 作为一个向量,其中包含每个折叠的所有预测。在这个函数中,我只是得到了 19,它应该是 189。然后我使用这个长度为 189 的向量生成速率。

标签: r regression glm cross-validation predict


【解决方案1】:

我现在正在将我的 cmets 变成一个答案。

jim <- function(x, y, n.folds, data) {   

  pred.class <- numeric(0)  ## initially empty; accumulated later
  for(i in 1:n.folds){
    folds <- cut(seq(1,nrow(data)), breaks = n.folds, labels = FALSE)  
    testIndexes <- which(folds == i)  ## no need for `arr.ind = TRUE`
    testData <- data[testIndexes, ]
    trainData <- data[-testIndexes, ]
    ## `reformulate` constructs formula from strings. Read `?reformulate`
    glm.train <- glm(reformulate(x, y), family = binomial, data = trainData)
    predictions <- predict(glm.train, newdata = testData, type = 'response')
    ## accumulate the result using `c()`
    ## change `predictions < 0` to `predictions < 0.5` as `type = response`
    pred.class <- c(pred.class, ifelse(predictions < 0.5, 0, 1))
    }

  ## to access a column with string, use `[[]]` not `$`
  rate <- sum(pred.class!= data[[y]]) / length(data[[y]])
  rate  ## or `return(rate)`
  }

jim("smoke", "low", 10, birthwt)
# [1] 0.3121693

备注:

  1. 这里不用arr.ind = TRUE,虽然没有副作用。
  2. 您的分类有问题。你设置type = "response",然后你使用ifelse(predictions &lt; 0, 0, 1)。想想看,pred.class 总是得到 1。
  3. for 循环的每次迭代都会覆盖pred.class。我想你想积累结果。 pred.class &lt;- c(pred.class, ifelse(predictions &lt; 0.5, 0, 1))也是如此;
  4. 错误使用glmpredict。将$ 放在模型公式中是错误的。请阅读Predict() - Maybe I'm not understanding it。在这里,我已将您的函数更改为接受变量名(作为字符串),并在 glm 中使用正确的模型公式。请注意,此更改需要将ydata[[y]] 放在rate = sum(pred.class!= y) / length(y) 中。
  5. 您可能希望返回rate 而不仅仅是将其打印到屏幕上。因此,将您的 print 行替换为显式 return(rate) 或隐式 rate
  6. 您可以将ifelse(predictions &lt; 0.5, 0, 1) 替换为as.integer(predictions &lt; 0.5),尽管我没有在上面更改它。

【讨论】:

  • 谢谢。比率应该是与 y 不同的预测的百分比。预测应该是循环中每个预测的预测堆栈。我现在看到每次迭代都会覆盖 pred.class。如何返回预测然后计算速率?
  • 谢谢。但是,如果您在 jim("smoke", "low", 10,birthwt) 中输入其他变量,例如“年龄”、“低”或“种族”“低”,你仍然得到 31%。此外,如果您将 n.folds 更改为 50,您仍然会得到 31%。这就是问题所在。出了点问题。
  • 我现在明白了。有趣的是,对于 folds>10,比率不会改变。非常感谢你。我非常感谢您花时间帮助我解决这个问题!也许有一天我可以做出贡献!
猜你喜欢
  • 2021-08-31
  • 1970-01-01
  • 2014-02-18
  • 2020-12-26
  • 2020-03-26
  • 1970-01-01
  • 2018-07-04
  • 1970-01-01
  • 2021-06-09
相关资源
最近更新 更多