许多机器学习模型都能够预测类别成员的概率或类概率分数。
概率为评估和比较模型提供了所需的粒度级别,尤其是在不平衡分类问题中,例如使用 ROC 曲线 来解释预测,以及使用 ROC AUC 指标来比较模型性能,这两者都使用概率。
不幸的是,许多模型预测的概率或类概率分数并未校准。这意味着它们在某些情况下可能过于自信,而在其他情况下则不够自信。更糟糕的是,不平衡分类任务中存在的严重倾斜的类别分布可能导致预测概率中的偏差更大,因为它们过于倾向于预测多数类。
因此,在评估非线性机器学习模型的性能之前,通常最好校准其预测的概率。此外,当处理不平衡数据集时,即使是像逻辑回归这样在类别标签平衡时能很好地预测概率的模型,也最好对概率进行一般性校准。
在本教程中,您将了解如何为不平衡分类校准预测的概率。
完成本教程后,您将了解:
- 为了充分利用不平衡分类问题的模型,需要校准概率。
- 如何为 SVM、决策树和 KNN 等非线性模型校准预测的概率。
- 如何在具有倾斜类分布的数据集上对不同概率校准方法进行网格搜索。
启动您的项目,请参阅我的新书 《Python 不平衡分类》,其中包含分步教程和所有示例的Python 源代码文件。
让我们开始吧。

如何校准不平衡分类的概率
照片作者:Dennis Jarvis,部分权利保留。
教程概述
本教程分为五个部分;它们是:
- 未校准概率的问题
- 如何校准概率
- 带校准概率的 SVM
- 带校准概率的决策树
- 使用 KNN 进行概率校准的网格搜索
未校准概率的问题
许多机器学习算法都可以预测一个表示类别成员的概率或类概率分数。
例如,逻辑回归可以直接预测类别成员的概率,而支持向量机可以预测一个非概率但可以解释为概率的分数。
概率可以作为不确定性的度量,用于需要概率预测的问题。这在不平衡分类中尤其如此,因为清晰的类别标签通常不足以评估和选择模型。预测概率为更精细的模型评估和选择提供了基础,例如使用 ROC 和精确率-召回率诊断图、ROC AUC 等指标以及阈值移动等技术。
因此,在处理不平衡分类任务时,通常倾向于使用预测概率的机器学习模型。问题在于,很少有机器学习模型具有校准的概率。
……为了有用地区分为概率,分数应该被校准。
— 第 57 页,《学习不平衡数据集》,2018 年。
校准的概率意味着概率反映了真实事件的可能性。
如果考虑到在分类中,我们有正确的或不正确的类别标签而不是概率,这可能会令人困惑。为了澄清,请回想一下,在二元分类中,我们预测的是类别 0 或 1 的负例或正例。如果 100 个示例被预测的概率为 0.8,那么如果概率已校准,其中 80% 的示例将属于类别 1,20% 将属于类别 0。在此,校准是预测概率与正例出现情况的一致性。
未校准的概率表明概率分数存在偏差,这意味着概率在某些情况下过于自信或不够自信。
- 校准的概率。概率与事件的真实可能性相匹配。
- 未校准的概率。概率过于自信和/或不够自信。
这对于未采用概率框架进行训练的机器学习模型以及具有倾斜分布(如不平衡分类任务)的训练数据来说是很常见的。
导致未校准概率的两个主要原因;它们是:
- 未使用概率框架进行训练的算法。
- 训练数据中的偏差。
很少有机器学习算法能产生校准的概率。这是因为模型要预测校准的概率,必须明确地在概率框架下进行训练,例如最大似然估计。提供校准概率的算法示例包括:
- 逻辑回归。
- 线性判别分析。
- 朴素贝叶斯。
- 人工神经网络。
许多算法要么预测类概率分数,要么预测类别标签,并且必须进行强制才能产生类概率分数。因此,这些算法通常需要在使用前校准其“概率”。示例包括:
- 支持向量机。
- 决策树。
- 决策树的集成(bagging、随机森林、梯度提升)。
- k-近邻。
训练数据集中的偏差,例如类别分布的倾斜,意味着模型平均而言将自然地为多数类预测比少数类更高的概率。
问题是,模型可能会过度补偿,过于关注多数类。这甚至适用于通常产生校准概率的模型,如逻辑回归。
……在不平衡的情况下通过监督学习获得的类别概率估计系统地低估了少数类实例的概率,尽管整体校准看似良好。
— 不平衡数据的类别概率估计不可靠(以及如何修复它们),2012 年。
想要开始学习不平衡分类吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
如何校准概率
通过重新缩放其值来校准概率,使其更好地匹配训练数据中观察到的分布。
……我们希望估计的类别概率能够反映样本的真实潜在概率。也就是说,预测的类别概率(或类概率值)需要得到良好的校准。为了得到良好的校准,概率必须有效地反映所关注事件的真实可能性。
— 第 249 页,《应用预测建模》,2013。
概率预测是在训练数据上进行的,并将概率的分布与期望的概率进行比较,然后进行调整以提供更好的匹配。这通常涉及拆分训练数据集,使用一部分来训练模型,另一部分作为验证集来缩放概率。
有两种主要的概率缩放技术;它们是 Platt 缩放 和 等渗回归。
- Platt 缩放。使用逻辑回归模型转换概率。
- 等渗回归。使用加权最小二乘回归模型转换概率。
Platt 缩放是一种更简单的方法,旨在将支持向量机的输出缩放到概率值。它涉及学习一个逻辑回归模型来执行分数到校准概率的转换。等渗回归是一种更复杂的加权最小二乘回归模型。它需要更多训练数据,但功能也更强大,更通用。在这里,等渗仅仅是指原始概率到重新缩放值的单调递增映射。
当预测概率的失真呈 S 形时,Platt 缩放最有效。等渗回归是一种更强大的校准方法,可以纠正任何单调失真。
— 通过监督学习预测良好概率,2005 年。
scikit-learn 库可以通过 CalibratedClassifierCV 类访问 Platt 缩放和等渗回归这两种概率校准方法。
这是一个模型(如 SVM)的包装器。首选的缩放技术通过“method”参数定义,该参数可以是“sigmoid”(Platt 缩放)或“isotonic”(等渗回归)。
交叉验证用于缩放模型的预测概率,通过“cv”参数设置。这意味着模型在训练集上拟合,在测试集上校准,并且此过程对 k 折重复 k 次,其中预测概率在运行中取平均值。
设置“cv”参数取决于可用数据的数量,尽管可以使用 3 或 5 等值。重要的是,拆分是分层的,这在使用不平衡数据集(通常阳性类样本很少)的概率校准时非常重要。
1 2 3 4 |
... # 包装模型进行概率校准的示例 model = ... calibrated = CalibratedClassifierCV(model, method='sigmoid', cv=3) |
既然我们知道如何校准概率,让我们在不平衡分类数据集上查看一些校准模型概率的示例。
带校准概率的 SVM
在本节中,我们将回顾如何在不平衡分类数据集上为 SVM 模型校准概率。
首先,让我们使用 make_classification() 函数 定义一个数据集。我们将生成 10,000 个样本,其中 99% 属于负类(类别 0),1% 属于正类(类别 1)。
1 2 3 4 |
... # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) |
接下来,我们可以定义一个具有默认超参数的 SVM。这意味着模型没有针对数据集进行调整,但将提供一个一致的比较基础。
1 2 3 |
... # 定义模型 model = SVC(gamma='scale') |
然后,我们可以使用重复分层 k 折交叉验证在数据集上评估此模型,进行三次重复的 10 折交叉验证。
我们将使用 ROC AUC 来评估模型,并计算所有重复和折叠的平均分数。ROC AUC 将利用 SVM 提供的未校准的类概率分数。
1 2 3 4 5 6 7 |
... # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
将这些结合起来,完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 评估 SVM 在不平衡分类上的未校准概率 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.svm import SVC # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = SVC(gamma='scale') # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
运行示例将在不平衡分类数据集上评估带有未校准概率的 SVM。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到 SVM 达到的 ROC AUC 约为 0.804。
1 |
平均 ROC AUC: 0.804 |
接下来,我们可以尝试使用 CalibratedClassifierCV 类包装 SVM 模型并预测校准的概率。
我们使用分层 10 折交叉验证来评估模型;这意味着在每一折中,有 9,000 个样本用于训练,1,000 个样本用于测试。
使用 CalibratedClassifierCV 和 3 折,其中一折的 9,000 个样本将被分为 6,000 个用于训练模型,3,000 个用于校准概率。这没有留下多少少数类样本,例如,在 10 折交叉验证中是 90/10,然后是 60/30 用于校准。
在使用校准时,重要的是根据您选择的模型评估方案来处理这些数字,并调整折叠数以确保数据集足够大,甚至在需要时从交叉验证切换到更简单的训练/测试拆分。可能需要进行实验。
我们将像以前一样定义 SVM 模型,然后定义带有等渗回归的 CalibratedClassifierCV,然后通过重复分层 k 折交叉验证来评估校准的模型。
1 2 3 4 5 |
... # 定义模型 model = SVC(gamma='scale') # 包装模型 calibrated = CalibratedClassifierCV(model, method='isotonic', cv=3) |
由于 SVM 概率默认未校准,我们可以预期校准它们会提高 ROC AUC,因为 ROC AUC 明确基于概率评估模型。
将这些结合起来,下面列出了评估带有校准概率的 SVM 的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 评估 SVM 在不平衡分类上的校准概率 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.calibration import CalibratedClassifierCV from sklearn.svm import SVC # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = SVC(gamma='scale') # 包装模型 calibrated = CalibratedClassifierCV(model, method='isotonic', cv=3) # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(calibrated, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
运行示例将在不平衡分类数据集上评估带有校准概率的 SVM。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到 SVM 的 ROC AUC 从约 0.804 提升到约 0.875。
1 |
平均 ROC AUC: 0.875 |
概率校准可以与算法或数据集的其他修改相结合进行评估,以解决类别分布倾斜的问题。
例如,SVM 提供了“class_weight”参数,可以设置为“balanced”以调整边距以偏向少数类。我们可以包含此更改到 SVM 中并校准概率,并且我们可能会看到模型技能得到进一步提升;例如:
1 2 3 |
... # 定义模型 model = SVC(gamma='scale', class_weight='balanced') |
将这些结合起来,下面列出了带有校准概率的加权 SVM 的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 评估带有校准概率的加权 SVM 在不平衡分类上的应用 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.calibration import CalibratedClassifierCV from sklearn.svm import SVC # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = SVC(gamma='scale', class_weight='balanced') # 包装模型 calibrated = CalibratedClassifierCV(model, method='isotonic', cv=3) # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(calibrated, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
运行示例将在不平衡分类数据集上评估带有校准概率的加权 SVM。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到 SVM 的 ROC AUC 从约 0.875 进一步提升到约 0.966。
1 |
平均 ROC AUC: 0.966 |
带校准概率的决策树
决策树是另一种高度有效的机器学习方法,它不能自然地产生概率。
相反,它直接预测类别标签,并且可以基于落入新示例预测的树叶中的训练数据集的分布来估计类概率分数。因此,决策树的概率分数在使用和选择模型之前应进行校准。
我们可以使用 DecisionTreeClassifier scikit-learn 类定义一个决策树。
可以在我们的合成不平衡分类数据集上使用未校准的概率来评估模型。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 评估决策树在不平衡分类上的未校准概率 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.tree import DecisionTreeClassifier # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = DecisionTreeClassifier() # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
运行示例将在不平衡分类数据集上评估带有未校准概率的决策树。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到决策树达到的 ROC AUC 约为 0.842。
1 |
平均 ROC AUC: 0.842 |
然后,我们可以使用校准包装器来评估相同的模型。
在这种情况下,我们将使用 Platt 缩放方法,通过将“method”参数设置为“sigmoid”来配置。
1 2 3 |
... # 包装模型 calibrated = CalibratedClassifierCV(model, method='sigmoid', cv=3) |
下面列出了评估带有校准概率的决策树在不平衡分类上的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 评估带有校准概率的决策树在不平衡分类上的应用 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.calibration import CalibratedClassifierCV from sklearn.tree import DecisionTreeClassifier # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = DecisionTreeClassifier() # 包装模型 calibrated = CalibratedClassifierCV(model, method='sigmoid', cv=3) # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(calibrated, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
运行示例将在不平衡分类数据集上评估带有校准概率的决策树。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到决策树的 ROC AUC 从约 0.842 提升到约 0.859。
1 |
平均 ROC AUC: 0.859 |
使用 KNN 进行概率校准的网格搜索
概率校准可能对方法和使用方法的方式都很敏感。
因此,最好在模型上测试一系列不同的概率校准方法,以发现最适合您数据集的方法。一种方法是将校准方法和交叉验证折叠视为超参数并进行调整。在本节中,我们将介绍如何使用网格搜索来调整这些超参数。
k-近邻算法,或 KNN,是另一种非线性机器学习算法,它直接预测类别标签,并且必须进行修改才能产生类概率分数。这通常涉及使用邻域中类别标签的分布。
我们可以使用 KNeighborsClassifier 类在我们的合成不平衡分类数据集上评估具有未校准概率的 KNN,其默认邻域大小为 5。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 评估 KNN 在不平衡分类上的未校准概率 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.neighbors import KNeighborsClassifier # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = KNeighborsClassifier() # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1) # 总结性能 print('平均 ROC AUC: %.3f' % mean(scores)) |
运行示例将在不平衡分类数据集上评估带有未校准概率的 KNN。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到 KNN 达到的 ROC AUC 约为 0.864。
1 |
平均 ROC AUC: 0.864 |
已知概率取决于邻域大小且未校准,我们可以预期某种校准将改善使用 ROC AUC 的模型的性能。
我们不会仅检查 CalibratedClassifierCV 类的一种配置,而是使用 GridSearchCV 来网格搜索不同的配置。
首先,模型和校准包装器按照之前的方式定义。
1 2 3 4 5 |
... # 定义模型 model = KNeighborsClassifier() # 包装模型 calibrated = CalibratedClassifierCV(model) |
我们将测试“sigmoid”和“isotonic”这两种“method”值,以及不同的“cv”值 [2,3,4]。请记住,“cv”控制用于估计校准概率的训练数据集的拆分。
我们可以将参数网格定义为一个字典,其中包含我们想要调整的 CalibratedClassifierCV 的参数名称,并提供要尝试的值列表。这将测试 3 * 2 即 6 种不同的组合。
1 2 3 |
... # 定义网格 param_grid = dict(cv=[2,3,4], method=['sigmoid','isotonic']) |
然后,我们可以定义 GridSearchCV,使用模型和参数网格,并使用我们之前使用的相同重复分层 k 折交叉验证来评估每个参数组合。
1 2 3 4 5 6 7 |
... # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义网格搜索 grid = GridSearchCV(estimator=calibrated, param_grid=param_grid, n_jobs=-1, cv=cv, scoring='roc_auc') # 执行网格搜索 grid_result = grid.fit(X, y) |
评估后,我们将总结具有最高 ROC AUC 的配置,然后列出所有组合的结果。
1 2 3 4 5 6 7 8 |
# 报告最佳配置 print("最佳: %f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) # 报告所有配置 means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 使用: %r" % (mean, stdev, param)) |
将这些结合起来,下面列出了在 KNN 模型上使用网格搜索概率校准以进行不平衡分类的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# 使用 KNN 进行概率校准的网格搜索,用于不平衡分类 from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import GridSearchCV from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.neighbors import KNeighborsClassifier from sklearn.calibration import CalibratedClassifierCV # 生成数据集 X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0, n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4) # 定义模型 model = KNeighborsClassifier() # 包装模型 calibrated = CalibratedClassifierCV(model) # 定义网格 param_grid = dict(cv=[2,3,4], method=['sigmoid','isotonic']) # 定义评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义网格搜索 grid = GridSearchCV(estimator=calibrated, param_grid=param_grid, n_jobs=-1, cv=cv, scoring='roc_auc') # 执行网格搜索 grid_result = grid.fit(X, y) # 报告最佳配置 print("最佳: %f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) # 报告所有配置 means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 使用: %r" % (mean, stdev, param)) |
运行此示例将在一组不同类型的已校准概率上评估 KNN,用于不平衡分类数据集。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到,当“cv”设置为 2 且“method”设置为“isotonic”时,取得了最佳结果,平均 ROC AUC 约为 0.895,相较于未校准时实现的 0.864 有所提升。
1 2 3 4 5 6 7 |
最佳:0.895120,参数为 {'cv': 2, 'method': 'isotonic'} 0.895084 (0.062358) 使用:{'cv': 2, 'method': 'sigmoid'} 0.895120 (0.062488) 使用:{'cv': 2, 'method': 'isotonic'} 0.885221 (0.061373) 使用:{'cv': 3, 'method': 'sigmoid'} 0.881924 (0.064351) 使用:{'cv': 3, 'method': 'isotonic'} 0.881865 (0.065708) 使用:{'cv': 4, 'method': 'sigmoid'} 0.875320 (0.067663) 使用:{'cv': 4, 'method': 'isotonic'} |
这提供了一个模板,您可以使用它来评估您自己模型上的不同概率校准配置。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
论文
- 使用监督学习预测良好概率, 2005.
- 类别概率估计对于不平衡数据是不可靠的(以及如何修复它们), 2012.
书籍
- 从不平衡数据集中学习 (Learning from Imbalanced Data Sets), 2018.
- 不平衡学习:基础、算法与应用 (Imbalanced Learning: Foundations, Algorithms, and Applications), 2013.
- 应用预测建模, 2013.
API
- sklearn.calibration.CalibratedClassifierCV API.
- sklearn.svm.SVC API.
- sklearn.tree.DecisionTreeClassifier API.
- sklearn.neighbors.KNeighborsClassifier API.
- sklearn.model_selection.GridSearchCV API.
文章
总结
在本教程中,您将了解如何校准不平衡分类的预测概率。
具体来说,你学到了:
- 为了充分利用不平衡分类问题的模型,需要校准概率。
- 如何为 SVM、决策树和 KNN 等非线性模型校准预测的概率。
- 如何对具有倾斜类别分布的数据集进行网格搜索不同的概率校准方法。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
您将如何校准一组的概率,其中一组的概率必须加起来为一?
例如,您可能有 20 行。前 12 行是组 1,最后 8 行是组 2。概率相加应该等于 2,但它们不等于。您将如何在此情况下进行校准?
谢谢
概率是针对每一行(样本)考虑的,而不是跨行考虑的。
也许我不明白您想实现什么?
我是否可以这样假设,在 Python SKlearn ML 模型训练中创建和使用自己的损失函数是不可能的,除非深入研究底层?对于 Keras 构建的模型或 ML 模型超参数调优,情况并非如此?
如果我错了,您是否有相关的文章?
谢谢
您可能需要扩展类并更改学习算法。
您将如何设置一个预测问题,在该问题中,您正试图预测一个组的二元结果,其中该组的概率总和为 1。
例如,您正在预测一个包含 3 个观测值的组的概率。您使用标准的 ML 方法,您的概率是 0.6、0.4 和 0.25,它们加起来是 1.25。但是您需要将这些概率校准为总和为 1。您将如何以这种方式优化您的 ML,以考虑到组?
这有道理吗?
顺便说一句,我喜欢这些文章。
谢谢
使用具有跨组 softmax 激活的神经网络。
嗨,Jason,
总的来说,您认为在校准概率并选择了最佳阈值后,是否应该将训练集和验证集合并以训练一个新模型?如果合并并训练一个新模型,是否可以使用先前在验证集上选择的阈值?
谢谢!
这确实取决于您的数据集(您有多少数据)以及您项目的具体细节。
使用单独的数据集进行校准和阈值设定是理想的,但并非总是可行的。
这说得通,如果没有足够的数据,您会如何建议进行校准和阈值设定?
您可以使用训练数据(哎呀!不行!),或者对每个任务使用相同的验证集(更好),或者为每个任务使用单独的验证集(最好)。
嗨 Jason,先在您的模型上进行网格搜索,然后运行校准分类器是否有意义? https://datascience.stackexchange.com/questions/77181/do-not-understand-my-calibration-curve-output-for-xgboost < — 这是我得到的结果,是否正确??我无法获得我的 isotonic 和 platt 图/输出。我有一个不平衡的问题。
如果您根据预测概率选择模型,那么请将校准作为模型的一部分,并在校准后的模型上进行网格搜索。
如果不是,则完全删除校准,它可能不是必需的。
好的,假设我有一个 xgboost – 我对它进行了网格搜索。然后我得到参数,然后我对它进行了拟合校准:clf_isotonic = CalibratedClassifierCV(clf, cv=’prefit’, method=’isotonic’)。我的 platt 结果非常奇怪 – 我只得到一个 platt 点(在 bin 0 和 0.2 之间),您认为这是否表明存在不平衡问题,或者我不应该理会它。对于我的未校准图,曲线始终位于对角线(完美校准)下方,但我不明白为什么 platt 只绘制一个点。
也许 platt 不适合您的模型/数据集。
校准是否不会保留算法的原始顺序?
如果会,为什么 ROC AUC 指标在应用校准后会提高?
也就是说,ROC AUC 取决于顺序,如果我们对保留原始顺序的概率进行某种单调变换,它应该不会改变,对吗?
https://stackoverflow.com/questions/54318912/does-calibration-improve-roc-score
校准会包装原始模型。
ROC 可以提高,因为概率分布发生了变化,这反过来又通过 ROC 中计算的用于不同阈值的类别标签映射改变了它。
好的,那么说,在您的示例中,如果您有一个验证集,那么在训练集上校准(训练和校准)的算法在同一验证集上的 AUC 分数不会比未校准算法在该验证集上的 AUC 分数有所提高,因为该验证集也是在训练集上训练的,对吗?
不一定——这是一个范围的变化。
我猜这与此处 Abhilash Menon 的评论(https://machinelearning.org.cn/calibrated-classification-model-in-scikit-learn/)相似,无法链接到确切的评论和 Pepe 和 John 的回复。
从那里听起来,校准集中的顺序可能略有不同,但那仅仅是平均和 CV 的伪影。否则,AUC 和顺序应该完全相同。
那么我不明白为什么在这篇文章中 AUC 分数提高了这么多。您能解释一下吗?
感谢您的教程 Jason – 这是一篇很棒的读物。我有一个小问题。校准是否应该在超参数调整之前进行?我的理解是,概率校准应该首先进行(尤其是在优化 ROC AUC 或 PR AUC 时,两者都使用概率),然后对校准后的模型进行超参数调整和模型评估。这是通用的工作流程吗?我也很好奇为什么不需要过采样/欠采样技术(我认为这更多地取决于您有兴趣用于评估的评分指标)。
最后,在某些模型不指定类权重参数并结合概率校准(不调整边距以偏向少数类)是否有任何好处?例如,XGBoost 的 scale_pos_weight 参数会给予正类更大的权重 – 我读过禁用 scale_pos_weight 可能会产生更好的校准概率(https://discuss.xgboost.ai/t/how-does-scale-pos-weight-affect-probabilities/1790)。
难题。
也许更好的方法是将校准包含在正在调整的“模型”中。这是我的首选方法。
过采样/欠采样会有帮助,这取决于您的数据集。试试看。
类权重和校准可能一起使用很有用,我猜不是 – 但很难考虑所有可能的情况。同样,也许试试看。
你好,虽然有点晚了,但值得一提。
实际上这是我的问题和疑问,我最终找到了一篇文章,它在某种程度上回答了这个问题,并给了我关于所有“校准”以及“阈值移动”方法的澄清。
所以我绝对推荐给其他有此领域疑问和问题的人,并希望它也能帮助他人。以下是文章链接:
https://towardsdatascience.com/tackling-imbalanced-data-with-predicted-probabilities-3293602f0f2
感谢您发表这篇文章。我刚刚开始学习如何处理不平衡数据集。我想了解为什么在以上所有示例中您都选择比较 AUC。在您关于 ROC AUC 的文章中,您说:
“当每个类别的观测数量大致相等时,应该使用 ROC 曲线。”
难道在校准前后查看 PR AUC 会更好吗?
不客气。
本教程中指标的选择是任意的,因为我们关注的是校准。
这可以帮助您选择指标
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
亲爱的 Jason,
非常感谢!
不客气。
你好 Jason,
感谢您撰写这篇出色的资源。我有一个快速的问题。如果我想制作类似校准图(例如,概率分位数与标签分位数)来直观检查校准模型,我是否仍然需要先将特征和标签分离到测试/训练集,或者 CalibratedClassifierCV 下发生的 k-fold 交叉验证是否会减轻这种担忧?也就是说,我能否将用于校准模型的同一整个数据集用于绘制该模型的校准曲线?非常感谢您的时间。
如果您使用 k-fold CV,则训练/测试的分离是自动完成的。这就是“交叉验证”的含义。
你好 Adrian,
感谢您的回复。我明白交叉验证的作用。我想知道我们是否可以使用用于校准模型(使用 CV)的相同数据集来生成校准曲线,并了解模型在多大程度上可以充分匹配未来数据的概率。或者我是否需要另一个单独的保留集(与 CV 期间使用的数据集分开)来了解校准模型在未来数据上的表现?
您可能需要另一个保留集。如果这样做,请保留您的保留集,然后将其余部分传递给交叉验证模型。然后,在模型完成后使用保留集。此维基百科文章可能对您有帮助:https://en.wikipedia.org/wiki/Training,_validation,_and_test_sets
非常感谢,Adrian!这有助于澄清。
感谢 Jason 带来的精彩阅读!校准图对于高度不平衡的数据集是否不太有用?每当我尝试校准在高度不平衡数据集上训练的模型的模型概率时,相关的校准图都会显示校准模型几乎水平于图的 x 轴,远未接近完美校准模型所代表的对角线(y 轴代表正类的比例,x 轴代表正类的平均预测概率)。这更多地是由于数据中严重的类别不平衡,还是模型概率分数不佳?此外,如果校准图对于高度不平衡的数据集没有用,您是否建议使用 logloss 和 brier 分数等指标来评估模型概率在多大程度上代表“真实概率”,或者是否有其他指标和/或可视化建议来评估这一点?
嗨 Jake… 不客气!以下资源可能对您感兴趣
https://machinelearning.org.cn/calibrated-classification-model-in-scikit-learn/
嗨,Jason,
det_curve 为我的二元分类模型 (SVC) 返回每个阈值、fpr 和 fnr 的一个值。您能解释一下为什么会这样吗?
尽管存在 0-1 范围内的分数
我同意之前评论者的观点,即 ROC/AUC 可能不是与校准方法结合使用的最佳示例。例如,请参阅 stackoverflow. com/questions/54318912/does-calibration-improve-roc-score
除此之外,感谢一如既往的精彩资源!
感谢 rflameiro 您的反馈和分享您的发现!