问题描述
我正在尝试复制 missuse 的工作answer,以便从插入符号的火车功能中提取预测。我使用的是弹性网,但无法获得。
以下是可重现的示例:
require(caret)
require(glmnet)
x = matrix(rnorm(100 * 20),100,20)
set.seed(3)
g = sample(c(0,1),replace = TRUE)
df = as.data.frame(x)
g_f = as.factor(g)
df$g_f = g_f
train_control <- trainControl(
method="cv",number = 3,savePredictions = T)
sorozat = seq(0,1,0.25)
search_grid <- expand.grid(
alpha = sorozat,lambda = sorozat )
set.seed(3)
fit2 <- train(g_f ~ .,data = df,trControl = train_control,tuneGrid = search_grid,preProc = c("BoxCox","center","scale"),method = "glmnet")
而我的尝试却给出了错误:
prediction2 <- predict(fit2$finalModel,data = predict(fit2$preProcess,df))$prediction
predict.glmnet中的错误(fit2 $ finalModel,data = dict(fit2,df)): 您需要提供“ newx”的值
下面是我如何获得预测的方法。但是如果混淆矩阵,我怎么能确定它是否正确呢?
# CM ver.1
pred_f = predict(fit2,df)
cm = as.data.frame(pred_f)
cm$g = g_f
table(cm)
g
pred_f 0 1
0 29 9
1 15 47
与模型提供的不同吗?
# CM ver.2
confusionMatrix(fit2)$table
Reference
Prediction 0 1
0 23 16
1 21 40
在此先感谢您的帮助!
解决方法
链接的答案不适用于glmnet,因为predict.glmnet
具有一些特殊之处:
predict.glmnet
的数据参数称为newx
,必须为矩阵。
除此之外,此预测函数使用所有拟合的lambda来创建预测,因此,如果要获得最佳预测,则必须指定。另外,建议将响应设置为您的链接:
在您的示例中,最佳拟合值为alpha = 0.5和lambda = 0.25。 alpha设置在模型内部,但必须在预测期间指定lambda。
但是首先我们必须预处理测试数据(与链接的答案相同):
predict(fit2$preProcess,df)
这将返回带有类列的数据帧,因此为了将其提供给predict.glmnet
,必须删除响应列(因子)并将数据帧转换为矩阵:
as.matrix(predict(fit2$preProcess,df)[,-21])
现在以最佳λ为0.25调用predict.glmnet
并将预测类型设置为class:
library(glmnet)
prediction2 <- predict(fit2$finalModel,newx = as.matrix(predict(fit2$preProcess,-21]),type = "class",s = 0.25)
head(prediction2)
1
[1,] "0"
[2,] "1"
[3,] "0"
[4,] "0"
[5,] "0"
[6,] "0"
编辑:回答有关混淆矩阵差异的已编辑问题。
当您在confusionMatrix
的输出上调用train
时,则从重采样过程中的失格预测获得结果矩阵-由于这些是测试集预测,因此偏差较小。
当您对所有数据拟合模型(这是fit2$finalModel
)并使用它对正在创建的列车集合预测进行预测的同一数据时-由于模型使用了这些拟合,因此存在很大的偏差观察。这就是与在confusionMatrix
上调用fit2
相比,这种情况下对角线总和要少得多的原因。有时将这种情况称为过拟合-模型可以更好地预测已经看到的数据。
简而言之
`confusionMatrix(fit2)`
从异常预测中产生一个混淆矩阵。可以用作模型选择的指标。
同时
confusionMatrix(as.factor(prediction2),g_f)
基于对火车数据的模型预测,生成高度偏差的混淆矩阵。不应将其用作模型选择的指标。
EDTI2::我只是想到这可能是XY problem。
如果您只想要交叉验证的预测,则可以简单地使用:
fit2$pred
如果要计算这些的AUC,则应在trainControl中指定您要的类概率:
train_control <- trainControl(
method="cv",number = 3,savePredictions = TRUE,classProbs = TRUE)
另一个需要注意的是,类级别必须是有效的变量名称,因此0和1之类的数字将不起作用,一个简单的解决方法是:
df$g_f <- factor(df$g_f,levels = c(0,1),labels = c("zero","one"))
合适之后:
set.seed(3)
fit2 <- train(g_f ~ .,data = df,trControl = train_control,tuneGrid = search_grid,preProc = c("BoxCox","center","scale"),method = "glmnet")
预测在fit2$pred
中:
head(fit2$pred)
#output
pred obs rowIndex zero one alpha lambda Resample
1 one one 2 0.4513397 0.5486603 0 1 Fold1
2 zero zero 4 0.5764889 0.4235111 0 1 Fold1
3 zero one 5 0.5154925 0.4845075 0 1 Fold1
4 one one 6 0.4836418 0.5163582 0 1 Fold1
5 zero zero 7 0.5199623 0.4800377 0 1 Fold1
6 one zero 8 0.4770536 0.5229464 0 1 Fold1
这些预测适用于所有经过测试的超参数组合,以获取性能最佳的超参数:
library(tidyverse)
fit2$pred %>%
filter(alpha == fit2$bestTune$alpha&
lambda == fit2$bestTune$alpha) -> best_preds
有两种方法可以从这些预测中获取指标。
方法1.您可以使用组合的折叠预测(频率较低,但在数据集较小时很有用,因此折叠性能差异很大)可以做到这一点
pROC::roc(best_preds$obs,best_preds$one)$auc
#output
Area under the curve: 0.6631
方法2。您可以按平均和折算来计算(更常见,插入符号在内部用于任何度量标准:
library(tidyverse)
best_preds %>%
group_by(Resample) %>%
summarise(auc = as.numeric(pROC::roc(obs,one)$auc))
#output
Resample auc
<chr> <dbl>
1 Fold1 0.592
2 Fold2 0.757
3 Fold3 0.614
上面是每折AUC
求平均值:
best_preds %>%
group_by(Resample) %>%
summarise(auc = as.numeric(pROC::roc(obs,one)$auc)) %>%
ungroup() %>%
summarise(mean_auc = mean(auc))
#output
mean_auc
<dbl>
1 0.654