3.3. 调整类别预测的决策阈值#
分类最好分为两部分:
学习模型来预测(理想情况下)类别概率的统计问题;
基于这些概率预测采取具体行动的决策问题。
让我们举一个与天气预报相关的简单例子:第一点与回答“明天下雨的可能性有多大?”有关。”而第二点则与回答“明天我应该带伞吗?”".
当谈到scikit-learn API时,第一点是通过使用提供分数来解决的 predict_proba 或 decision_function .前者返回条件概率估计 \(P(y|X)\) 对于每个类别,而后者返回每个类别的决策分数。
The decision corresponding to the labels is obtained with predict. In binary classification, a decision rule or action is then defined by thresholding the scores, leading to the prediction of a single class label for each sample. For binary classification in scikit-learn, class labels predictions are obtained by hard-coded cut-off rules: a positive class is predicted when the conditional probability \(P(y|X)\) is greater than 0.5 (obtained with predict_proba) or if the decision score is greater than 0 (obtained with decision_function).
在这里,我们展示了一个例子,说明了条件概率估计之间的关系 \(P(y|X)\) 和类别标签::
>>> from sklearn.datasets import make_classification
>>> from sklearn.tree import DecisionTreeClassifier
>>> X, y = make_classification(random_state=0)
>>> classifier = DecisionTreeClassifier(max_depth=2, random_state=0).fit(X, y)
>>> classifier.predict_proba(X[:4])
array([[0.94 , 0.06 ],
[0.94 , 0.06 ],
[0.0416, 0.9583],
[0.0416, 0.9583]])
>>> classifier.predict(X[:4])
array([0, 0, 1, 1])
虽然这些硬编码规则作为默认行为乍一看可能是合理的,但它们对于大多数用例来说肯定并不理想。让我们举一个例子来说明。
考虑部署预测模型来帮助医生检测肿瘤的场景。在这种情况下,医生很可能有兴趣识别所有癌症患者,而不是错过任何患有癌症的人,以便为他们提供正确的治疗。换句话说,医生优先考虑实现高召回率。当然,这种对召回的强调伴随着潜在的更多假阳性预测的权衡,从而降低了模型的精确度。这是医生愿意承担的风险,因为错过癌症的成本远高于进一步诊断测试的成本。因此,当决定是否将患者归类为患有癌症时,当条件概率估计远低于0.5时,将他们归类为癌症阳性可能更有益。
3.3.1. 后调整决策阈值#
解决引言中所述问题的一种解决方案是,一旦模型已经训练好,就调整分类器的决策阈值。的 TunedThresholdClassifierCV
使用内部交叉验证调整此阈值。选择最佳阈值以最大化给定度量。
下图说明了梯度增强分类器的决策阈值的调整。虽然香草分类器和调优分类器提供相同的 predict_proba 输出,因此相同的接收器工作特性(ROC)和精确召回曲线,类别标签预测因调整的决策阈值而有所不同。普通分类器以大于0.5的条件概率预测感兴趣的类别,而调整后的分类器以非常低的概率(大约0.02)预测感兴趣的类别。此决策阈值优化了企业(在本例中是保险公司)定义的效用指标。

3.3.1.1. 调整决策阈值的选项#
决策阈值可以通过参数控制的不同策略来调整 scoring
.
调整阈值的一种方法是最大化预定义的scikit-learn指标。这些指标可以通过调用该函数来找到 get_scorer_names
.默认情况下,平衡准确性是使用的指标,但请注意,应该为其用例选择有意义的指标。
备注
重要的是要注意,这些指标带有默认参数,特别是感兴趣类别的标签(即 pos_label
).因此,如果此标签不适合您的应用程序,您需要定义评分器并通过正确的 pos_label
(and其他参数)使用 make_scorer
.参阅 可召唤得分手 获取信息来定义您自己的评分功能。例如,我们展示了如何将感兴趣标签的信息传递给评分者 0
当最大化 f1_score
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.model_selection import TunedThresholdClassifierCV
>>> from sklearn.metrics import make_scorer, f1_score
>>> X, y = make_classification(
... n_samples=1_000, weights=[0.1, 0.9], random_state=0)
>>> pos_label = 0
>>> scorer = make_scorer(f1_score, pos_label=pos_label)
>>> base_model = LogisticRegression()
>>> model = TunedThresholdClassifierCV(base_model, scoring=scorer)
>>> scorer(model.fit(X, y), X, y)
0.88
>>> # compare it with the internal score found by cross-validation
>>> model.best_score_
np.float64(0.86)
3.3.1.2. 有关内部交叉验证的重要注意事项#
默认情况下 TunedThresholdClassifierCV
使用5重分层交叉验证来调整决策阈值。参数 cv
允许控制交叉验证策略。可以通过设置绕过交叉验证 cv="prefit"
并提供合适的分类器。在这种情况下,根据提供给 fit
法
但是,使用此选项时应该非常小心。由于存在过度匹配的风险,您不应使用相同的数据来训练分类器和调整决策阈值。有关更多详细信息,请参阅以下示例部分(参见 TunedThresholdClassifierCV_no_cv ).如果您的资源有限,请考虑使用浮点数 cv
限制为内部单一训练测试拆分。
的选项 cv="prefit"
仅应在提供的分类器已经训练过并且您只是想使用新的验证集找到最佳决策阈值时使用。
3.3.1.3. 手动设置决策阈值#
前面的部分讨论了寻找最佳决策阈值的策略。还可以使用类手动设置决策阈值 FixedThresholdClassifier
.如果你不想在打电话时改装模型, fit
,用一个包裹您的次估计器 FrozenEstimator
和做 FixedThresholdClassifier(FrozenEstimator(estimator), ...)
.
3.3.1.4. 示例#
请参阅标题为的示例 事后调整决策函数的截止点 ,以了解决策阈值的后调整。
请参阅标题为的示例 sphx_glr_auto_examples_model_selection_plot_cost_sensitive_learning.py ,了解成本敏感的学习和决策阈值调整。