在机器学习中,模型的输出通常需要通过一个阈值来转换成最终的类别标签。这个阈值的选择对于模型的性能有着重要的影响。默认情况下,许多分类器使用0.5作为后验概率估计或决策分数的阈值,但这种默认策略可能并不总是最优的。本文将展示如何使用TunedThresholdClassifierCV来根据感兴趣的指标调整决策阈值。
为了说明决策阈值的调整,将使用糖尿病数据集。这个数据集可以在OpenML上找到。使用fetch_openml函数来获取这个数据集。通过查看目标变量,可以了解正在处理的问题类型。在这个二元分类问题中,明确将标记为“tested_negative”的类别视为负类(也是最常见的),将标记为“tested_positive”的类别视为正类。还观察到这个二元问题是轻微不平衡的,负类的样本数量大约是正类的两倍。在评估时,应该考虑这一点来解释结果。
定义了一个基本的预测模型,由一个缩放器后跟一个逻辑回归分类器组成。使用交叉验证来评估模型。使用准确率和平衡准确率来报告模型的性能。平衡准确率是一个对类别不平衡不太敏感的指标,将使能够将准确率得分放在透视中。交叉验证允许研究不同数据分割的决策阈值的方差。然而,数据集相当小,使用超过5折来评估分散将是有害的。因此,使用RepeatedStratifiedKFold,其中应用5折交叉验证的多次重复。
from sklearn.datasets import fetch_openml
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
import pandas as pd
from sklearn.model_selection import RepeatedStratifiedKFold, cross_validate
# 获取糖尿病数据集
diabetes_data = fetch_openml(data_id=37, as_frame=True, parser="pandas")
data, target = diabetes_data.data, diabetes_data.target
# 定义基准分类器
model = make_pipeline(StandardScaler(), LogisticRegression())
# 交叉验证设置
scoring = ["accuracy", "balanced_accuracy"]
cv_scores = ["train_accuracy", "test_accuracy", "train_balanced_accuracy", "test_balanced_accuracy"]
cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=10, random_state=42)
# 执行交叉验证
cv_results = pd.DataFrame(cross_validate(model, data, target, scoring=scoring, cv=cv, return_train_score=True, return_estimator=True))
# 显示交叉验证结果
cv_results[cv_scores].aggregate(["mean", "std"]).T
预测模型成功地把握了数据和目标之间的关系。训练和测试分数彼此接近,意味着预测模型没有过拟合。还可以观察到,由于之前提到的类别不平衡,平衡准确率低于准确率。对于这个分类器,让用于将正类的预测概率转换为类别预测的决策阈值保持默认值:0.5。然而,这个阈值可能不是最优的。如果目标是最大化平衡准确率,应该选择另一个可以最大化这个指标的阈值。TunedThresholdClassifierCV元估计器允许根据感兴趣的指标调整分类器的决策阈值。
创建一个TunedThresholdClassifierCV,并将其配置为最大化平衡准确率。使用与之前相同的交叉验证策略来评估模型。与基准模型相比,观察到平衡准确率得分增加了。当然,这是以降低准确率得分为代价的。这意味着模型现在对正类更敏感,但在负类上犯了更多的错误。然而,需要注意的是,这个调整后的预测模型在内部与基准模型相同:它们具有相同的拟合系数。
from sklearn.model_selection import TunedThresholdClassifierCV
# 创建调整后的模型
tuned_model = TunedThresholdClassifierCV(estimator=model, scoring="balanced_accuracy")
# 执行交叉验证
cv_results_tuned = pd.DataFrame(cross_validate(tuned_model, data, target, scoring=scoring, cv=cv, return_train_score=True, return_estimator=True))
# 显示调整后的模型的交叉验证结果
cv_results_tuned[cv_scores].aggregate(["mean", "std"]).T
平均而言,大约0.32的决策阈值可以最大化平衡准确率,这与默认的0.5决策阈值不同。因此,当预测模型的输出用于做出决策时,调整决策阈值尤为重要。此外,用于调整决策阈值的指标应该仔细选择。在这里,使用了平衡准确率,但这可能不是手头问题最合适的指标。“正确”指标的选择通常取决于问题,并且可能需要一些领域知识。有关更多详细信息,请参阅标题为“针对成本敏感学习的后决策阈值调整”的示例。
(0分钟30.948秒)