如何更改二元分类的阈值

Posted

技术标签:

【中文标题】如何更改二元分类的阈值【英文标题】:How to change the threshold for binary classification 【发布时间】:2015-11-14 17:21:31 【问题描述】:

我已经在 R 中训练了一个 gbm 模型。由于我试图预测一个非常罕见的案例,因此我得到了很多误报。我想将正面(“好”)案例的阈值从默认值更改为 0.7。到目前为止,这是我的代码。

modFit.glm.ml <- train(as.factor(ml.training$one_lease)~., data=ml.training, method = "glm")
confusionMatrix(ml.testing$one_lease, predict(modFit.glm.ml, ml.testing), positive = "Good")

此代码有效,但它使用默认截止值。 有人提到使用 predict 函数可以做到这一点,但我不知道该怎么做。

【问题讨论】:

【参考方案1】:

您没有提供可重现的示例,所以这里有一个使用 iris 数据集来预测 iris 是否属于 setosa 类型的示例:

dat <- iris
dat$positive <- as.factor(ifelse(dat$Species == "setosa", "s", "ns"))
library(caret)
mod <- train(positive~Sepal.Length, data=dat, method="glm")

要使用除 0.5 以外的预测概率的截止值生成混淆矩阵,您可以使用所需的任何截止值对 predict 函数返回的概率进行阈值:

confusionMatrix(table(predict(mod, type="prob")[,"s"] >= 0.25,
                      dat$positive == "s"))
# Confusion Matrix and Statistics
# 
#        
#         FALSE TRUE
#   FALSE    88    3
#   TRUE     12   47
#                                           
#                Accuracy : 0.9             
#                  95% CI : (0.8404, 0.9429)
#     No Information Rate : 0.6667          
#     P-Value [Acc > NIR] : 2.439e-11       
#                                           
#                   Kappa : 0.7847          
#  Mcnemar's Test P-Value : 0.03887         
#                                           
#             Sensitivity : 0.8800          
#             Specificity : 0.9400          
#          Pos Pred Value : 0.9670          
#          Neg Pred Value : 0.7966          
#              Prevalence : 0.6667          
#          Detection Rate : 0.5867          
#    Detection Prevalence : 0.6067          
#       Balanced Accuracy : 0.9100          
#                                           
#        'Positive' Class : FALSE  

【讨论】:

【参考方案2】:

你还没有指定要使用哪个包,所以这里有另一个使用mlr的解决方案:

library(mlr)

dat = iris
training.set = seq(1, nrow(iris), by = 2)
test.set = seq(2, nrow(iris), by = 2)
dat$positive = as.factor(ifelse(dat$Species == "setosa", "s", "ns"))
task = makeClassifTask(data = dat, target = "positive")
lrn = makeLearner("classif.glmnet", predict.type = "prob")

mod = train(lrn, task, subset = training.set)
pred = predict(mod, task, subset = test.set)

print(getConfMatrix(pred))

pred = setThreshold(pred, c(s = 1))
print(getConfMatrix(pred))

mlr 允许您使用 setThreshold 显式设置阈值 - 优点是您可以将结果预测与任何衡量性能的函数一起使用,而无需确保阈值设置正确。

mlr 教程中有a whole section 进行分类器校准,可以帮助您找出此阈值的最佳值。

【讨论】:

以上是关于如何更改二元分类的阈值的主要内容,如果未能解决你的问题,请参考以下文章

不平衡二元分类问题的最佳阈值

计算二元分类的 roc_curve 阈值

SVM二元分类器不应该理解训练集中的阈值吗?

如何在 pyspark 中调整 GBTClassifier 的阈值

如何确定分类模型中的阈值?

更改随机森林分类器的阈值