从插入符的训练函数中提取预测
Extracting predictions from caret's train function
我正在尝试重现 missuse 的工作 从 caret 的训练函数中提取预测。我正在使用 eleastic net,但无法获取它。
这是一个可重现的例子:
require(caret)
require(glmnet)
x = matrix(rnorm(100 * 20), 100, 20)
set.seed(3)
g = sample(c(0,1), 100, 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
Error in predict.glmnet(fit2$finalModel, data = predict(fit2, df)) :
You need to supply a value for '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)
然而 returns 具有 class 列的数据框,因此为了将其提供给 predict.glmnet
必须删除响应列(因子)并转换数据框到矩阵:
as.matrix(predict(fit2$preProcess, df)[,-21])
现在用 0.25 的最佳 lambda 调用 predict.glmnet
,将预测类型设置为 class:
library(glmnet)
prediction2 <- predict(fit2$finalModel,
newx = as.matrix(predict(fit2$preProcess,
df)[,-21]),
type = "class",
s = 0.25)
head(prediction2)
1
[1,] "0"
[2,] "1"
[3,] "0"
[4,] "0"
[5,] "0"
[6,] "0"
编辑: 回答关于混淆矩阵差异的已编辑问题。
当您在 train
的输出上调用 confusionMatrix
时,结果矩阵是从重采样期间的折叠预测中获得的 - 由于这些是测试集预测,因此偏差较小。
当您在所有数据上拟合一个模型(这是 fit2$finalModel
)并使用它来预测您正在创建训练集预测的相同数据时 - 自模型拟合以来有很多偏差使用这些观察结果。这就是在这种情况下与在 fit2
上调用 confusionMatrix
相比,非对角线总和要少得多的原因。这有时被称为过度拟合 - 模型预测它已经看到的数据要好得多。
简而言之
`confusionMatrix(fit2)`
根据折叠预测生成混淆矩阵。这可以作为模型选择的指标。
而
confusionMatrix(as.factor(prediction2), g_f)
根据对训练数据的模型预测生成一个高度偏倚的混淆矩阵。这不应用作模型选择的指标。
EDTI2: 我刚想到这可能是 XY problem.
如果您只想要经过交叉验证的预测,您可以简单地使用:
fit2$pred
如果你想计算这些的 AUC,你应该在 trainControl 中指定你想要的 class 概率:
train_control <- trainControl(
method="cv",
number = 3,
savePredictions = TRUE,
classProbs = TRUE)
另一个问题是 class 级别需要是有效的变量名称,因此 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
我正在尝试重现 missuse 的工作
这是一个可重现的例子:
require(caret)
require(glmnet)
x = matrix(rnorm(100 * 20), 100, 20)
set.seed(3)
g = sample(c(0,1), 100, 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
Error in predict.glmnet(fit2$finalModel, data = predict(fit2, df)) : You need to supply a value for '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)
然而 returns 具有 class 列的数据框,因此为了将其提供给 predict.glmnet
必须删除响应列(因子)并转换数据框到矩阵:
as.matrix(predict(fit2$preProcess, df)[,-21])
现在用 0.25 的最佳 lambda 调用 predict.glmnet
,将预测类型设置为 class:
library(glmnet)
prediction2 <- predict(fit2$finalModel,
newx = as.matrix(predict(fit2$preProcess,
df)[,-21]),
type = "class",
s = 0.25)
head(prediction2)
1
[1,] "0"
[2,] "1"
[3,] "0"
[4,] "0"
[5,] "0"
[6,] "0"
编辑: 回答关于混淆矩阵差异的已编辑问题。
当您在 train
的输出上调用 confusionMatrix
时,结果矩阵是从重采样期间的折叠预测中获得的 - 由于这些是测试集预测,因此偏差较小。
当您在所有数据上拟合一个模型(这是 fit2$finalModel
)并使用它来预测您正在创建训练集预测的相同数据时 - 自模型拟合以来有很多偏差使用这些观察结果。这就是在这种情况下与在 fit2
上调用 confusionMatrix
相比,非对角线总和要少得多的原因。这有时被称为过度拟合 - 模型预测它已经看到的数据要好得多。
简而言之
`confusionMatrix(fit2)`
根据折叠预测生成混淆矩阵。这可以作为模型选择的指标。
而
confusionMatrix(as.factor(prediction2), g_f)
根据对训练数据的模型预测生成一个高度偏倚的混淆矩阵。这不应用作模型选择的指标。
EDTI2: 我刚想到这可能是 XY problem.
如果您只想要经过交叉验证的预测,您可以简单地使用:
fit2$pred
如果你想计算这些的 AUC,你应该在 trainControl 中指定你想要的 class 概率:
train_control <- trainControl(
method="cv",
number = 3,
savePredictions = TRUE,
classProbs = TRUE)
另一个问题是 class 级别需要是有效的变量名称,因此 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