错误 - 在lognet(x, is.sparse, ix, jx, y, weights, offset, alpha, nobs)中出现错误 = 等等。

6

使用Caret中的glmnet时遇到错误

以下是示例 加载库

library(dplyr)
library(caret)
library(C50)

从 C50 库加载流失数据集

data(churn)

创建 x 和 y 变量。
churn_x <- subset(churnTest, select= -churn)   
churn_y <- churnTest[[20]]

使用createFolds()在目标变量churn_y上创建5个CV折叠。
 myFolds <- createFolds(churn_y, k = 5)

创建trainControl对象:myControl

myControl <- trainControl(
 summaryFunction = twoClassSummary,
 classProbs = TRUE, # IMPORTANT!
 verboseIter = TRUE,
 savePredictions = TRUE,
 index = myFolds
)

拟合glmnet模型:model_glmnet

model_glmnet <- train(
  x = churn_x, y = churn_y,
  metric = "ROC",
  method = "glmnet",
  trControl = myControl
)

我遇到了以下错误:

lognet(x, is.sparse, ix, jx, y, weights, offset, alpha, nobs)中的参数5存在NA/NaN/Inf值,这是由于外部函数调用导致的错误。 此外,还有一个警告信息: 在lognet(x, is.sparse, ix, jx, y, weights, offset, alpha, nobs)中,强制转换导致了NAs。

我已经检查过churn_x变量,并没有缺失值。

sum(is.na(churn_x))

有人知道答案吗?

2个回答

7
问题在于模型规范。如果使用caret训练公式接口,则训练将正常工作。
train <- data.frame(churn_x, churn_y)

model_glmnet <- train(churn_y ~ ., data = train,
  metric = "ROC",
  method = "glmnet",
  trControl = myControl
)

> model_glmnet$results
  alpha       lambda       ROC      Sens      Spec      ROCSD     SensSD      SpecSD
1  0.10 0.0001754386 0.6958156 0.2845934 0.9123349 0.01855530 0.01616471 0.004002873
2  0.10 0.0017543858 0.7187303 0.2901986 0.9185721 0.01681286 0.01415863 0.005347573
3  0.10 0.0175438576 0.7399174 0.2355121 0.9487161 0.01482812 0.03932741 0.010769455
4  0.55 0.0001754386 0.6988285 0.2901800 0.9121614 0.01907845 0.01312159 0.004200233
5  0.55 0.0017543858 0.7260286 0.2946617 0.9185714 0.01761485 0.02171189 0.006755247
6  0.55 0.0175438576 0.7630039 0.2008939 0.9617103 0.01743847 0.03989938 0.006118592
7  1.00 0.0001754386 0.7009482 0.2924146 0.9119881 0.01958200 0.01233419 0.004157393
8  1.00 0.0017543858 0.7313495 0.2957728 0.9203040 0.01797853 0.02356945 0.008478577
9  1.00 0.0175438576 0.7672690 0.1595779 0.9760892 0.01935176 0.01935583 0.007938801

然而,当你指定xy时,它将不起作用,因为glmnet以模型矩阵形式获取x。当你向caret提供公式时,它会处理model.matrix的创建,但如果你只指定xy,那么它将假定x是一个model.matrix并将其传递给glmnet。例如,这样可以工作:
x <- model.matrix(churn_y ~ ., data = train)

model_glmnet2 <- train(x = x, y = churn_y,
                      metric = "ROC",
                      method = "glmnet",
                      trControl = myControl
)
> model_glmnet2$results
  alpha       lambda       ROC      Sens      Spec      ROCSD     SensSD      SpecSD
1  0.10 0.0001754386 0.6958156 0.2845934 0.9123349 0.01855530 0.01616471 0.004002873
2  0.10 0.0017543858 0.7187303 0.2901986 0.9185721 0.01681286 0.01415863 0.005347573
3  0.10 0.0175438576 0.7399174 0.2355121 0.9487161 0.01482812 0.03932741 0.010769455
4  0.55 0.0001754386 0.6988285 0.2901800 0.9121614 0.01907845 0.01312159 0.004200233
5  0.55 0.0017543858 0.7260286 0.2946617 0.9185714 0.01761485 0.02171189 0.006755247
6  0.55 0.0175438576 0.7630039 0.2008939 0.9617103 0.01743847 0.03989938 0.006118592
7  1.00 0.0001754386 0.7009482 0.2924146 0.9119881 0.01958200 0.01233419 0.004157393
8  1.00 0.0017543858 0.7313495 0.2957728 0.9203040 0.01797853 0.02356945 0.008478577
9  1.00 0.0175438576 0.7672690 0.1595779 0.9760892 0.01935176 0.01935583 0.007938801

model.matrix仅在存在因子特征时需要。


1
我发现a) model.matrix() 的转换对分类变量执行一次独热编码,而且b) 当使用 caret::train() 进行算法 "knn", "svmRadial", "svmLinear", "xgbTree", "xgbLinear" 时,你也需要这样做。 - Agile Bean
没错。因此,如果您想要使用其他类型的分类编码,您需要在将数据馈送到这些模型之前进行处理。 - missuse
非常有趣的链接,谢谢@missuse。你听说过使用监督学习来估计每个因子水平的数值的方法吗?我发现这是最直观的方法,但有人用过吗?请参见https://tidymodels.github.io/embed/。 - Agile Bean
@ Agile Bean 很棒的链接!谢谢。我听说过它,但不知道 embed 包。这种类型的东西通常在您有很多分类特征时使用。当监督学习器是神经网络 (layer_embedding) 时最常用。但是没有什么可以阻止您与任何学习器一起玩弄它。 - missuse

1
如果您想使用glmnet并得到相同的错误,请按照以下步骤操作!

简短回答:使用data.matrix()修复了我的问题!

最初,我进行了以下操作:
# Given X and Y are datframes
cv.glmnet(x = as.matrix(X), y = as.matrix(Y), alpha = 1, family = "binomial")

这是通过以下方式修复的:
cv.glmnet(x = data.matrix(X), y = as.matrix(Y), alpha = 1, family = "binomial")

较长的答案(其实不长):

我也曾遇到类似的问题,当我使用 as.matrix() 传递 X 矩阵时,它会将数据框中的所有元素转换为可强制转换的类型,如果数据框中存在因子,则as.matrix() 将所有内容都转换为字符。使用 data.matrix() 可以解决这个问题。 data.matrix() 可以处理因子和有序因子,而 as.matrix 则更基本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接