如何调试错误,例如:"dim(x) must have a positive length" with caret

how to debug errors like: "dim(x) must have a positive length" with caret

我是 运行 对拟合的预测,类似于插入符号指南中的拟合:

Caret Measuring Performance

predictions <-  predict(caretfit, testing, type = "prob")

但我得到错误:

Error in apply(x, 1, paste, collapse = ",") : 
dim(X) must have a positive length

我想知道 1) 诊断这些错误的一般方法,这些错误是由于对此类函数的错误输入或 2) 为什么我的代码失败。

1) 所以看报错跟'X'有关。 x 是哪个参数?明明是'apply'中的第一个,但是predict中的哪个argument最后传给apply呢?查看回溯():

10: stop("dim(X) must have a positive length")
9: apply(x, 1, paste, collapse = ",")
8: paste(apply(x, 1, paste, collapse = ","), collapse = "\n")
7: makeDataFile(x = newdata, y = NULL)
6: predict.C5.0(modelFit, newdata, type = "prob")
5: predict(modelFit, newdata, type = "prob") at C5.0.R#59
4: method$prob(modelFit = modelFit, newdata = newdata, submodels = param)
3: probFunction(method = object$modelInfo, modelFit = object$finalModel, 
   newdata = newdata, preProc = object$preProcess)
2: predict.train(caretfit, testing, type = "prob")
1: predict(caretfit, testing, type = "prob")

现在,如果我可以按照代码阅读并理解问题而不是这些一般错误,那么这个问题就很容易解决了。我可以使用此回溯跟踪代码到 C5.0.R#59 处的代码。 (看起来没有办法在每条轨迹上获取行号?)我可以按照这段代码一直到第 59 行,然后(我认为)第 44 行的预测函数:

Github Caret C5.0 source

但在此之后我不确定逻辑流向何处。我在插入符号源中的任何地方都看不到 'makeDataFile',或者,如果它在另一个包中,它是如何到达那里的。我也尝试过 Rstudio 调试、debug() 和 browser()。 None 提供我期望从其他语言获得的堆栈跟踪。当您不知道错误消息的含义时,有关于如何遵循代码的建议吗?

2) 至于我的特定输入,'caretfit' 只是插入符匹配的结果,测试数据是 300 万行乘 59 列:

fitcontrol <- trainControl(method = "repeatedcv",
                       number = 10,
                       repeats = 1,
                       classProbs = TRUE,
                       summaryFunction = custom.summary,
                       allowParallel = TRUE)


fml <- as.formula(paste("OUTVAR ~",paste(colnames(training[,1:(ncol(training)-2)]),collapse="+")))
caretfit <- train(fml,
             data = training[1:200000,],
             method = "C5.0",
             trControl = fitcontrol,
             verbose = FALSE,
             na.action = na.pass)

1 调试程序

您可以使用几个函数查明问题所在。

虽然似乎仍然无法在代码中获得包含行号的完整堆栈跟踪(Boo!),但您可以使用从回溯中获得的函数并使用函数 getAnywhere() 进行搜索对于您正在寻找的功能。例如,您可以这样做:

getAnywhere(makeDataFile)

查看位置和来源。 (当库通常捆绑在二进制文件中时,这在 windows 中也很有效。)然后您必须使用 source 或 github 来查找特定的行号或跟踪代码的逻辑。

在我的特定问题中,如果我 运行:

newdata <- testing
caseString <- C50:::makeDataFile(x = newdata, y = NULL)

(注意三个“:”。)我可以看到此步骤在此级别完成,因此看起来好像我的训练数据集在此过程中发生了一些事情。

所以通过我的回溯一遍又一遍地使用 gitAnywhere() 和 github 我可以手动找到行号(Boo!)

  1. in caret/R/predict.train.R, predict.train(第108行定义) 在第 153 行调用 probFunction
  2. 在 caret/R/probFunction 中,probFunction (在第 3 行定义)调用 method$prob 函数,它是一个存储的 拟合对象 caretfit$modelInfo$prob 中的函数可以是 通过将其输入控制台进行检查。这是一样的 在第 58 行的 caret/models/files/C5.0.R 中找到的函数调用 'predict' 第 59 行
  3. 插入符号中的东西知道使用 C50/R/predict.C5.0.R 你可以通过搜索看到 getAnywhere()
  4. 第 25 行的 运行s makeDataFile 函数(部分 C50 包)
  5. 哪个叫paste,哪个叫apply,哪个dies 停止

2 插入符预测的特殊问题

至于我的问题,我一直检查代码,并在不同级别添加输入,它会成功完成。发生的事情是我的数据集在 predict.train.R 中发生了一些修改,这导致它失败。好吧,事实证明我没有包括我的 'na.action' 参数,对于我的基于树的数据,它使用 'na.pass'。如果我包含这个参数:

prediction <- predict(caretfit, testing, type = "prob", na.action = na.pass)

它按预期工作。 predict.train 的第 126 行使用此参数来决定是否在预测中包含不完整的案例。我的数据没有完整的案例,所以它没有抱怨需要一些正长度的矩阵。

现在如何知道这个应用错误的答案是由于缺少 na.action 参数根本不明显,因此需要一个好的调试程序。如果有人知道其他调试方法(请记住,在 windows 中,在 Rstudio 中单步执行库源代码效果不佳),请回答或评论。