如何通过抽样分布估计你的模型的不确定性

当开始一个新的数据科学项目时,首要任务之一将是获取数据,以便能够评估项目的范围,并开始了解可以实现的目标。如果条件允许拥有一个大的的数据集来进行研究是非常好的情况,然而更多的时候,你将获得一个小的数据集来构建一个基线模型,然后,随着时间的推移,你将收集更多的数据,重新训练你的模型,并改进它。这种情况在加入一家传统上不是“数据驱动”,而是刚刚开始发现数据科学能为他们做什么的公司时很常见。

虽然我们知道使用小数据集会导致模型在训练期间快速过拟合,但还有一个经常很少讨论的问题,即模型性能的不确定性问题。在这篇文章中,我将演示如何评估模型性能的不确定性,以及数据集的大小如何影响它。

性能不确定性的出现是因为你在测试集上评估模型,而测试集通常是从初始数据集中随机抽取的样本。由于测试集是我们整个数据集的随机样本(它扮演统计总体的角色),我们从它计算的所有统计数据都是随机变量,它们具有一些潜在的分布。与其说“我们的模型有一个精度为x”,我们应该说““我们的模型的平均精度为μ,标准差为σ”,其中σ表示统计估计的不确定性。通过在许多随机生成的测试集上评估你的模型并记录结果,你可以估计你的统计数据的抽样分布,从而估计μ和σ。我想重申,标准差是我们感兴趣的数量,这告诉我们多少我们的统计变化已经计算在许多随机测试集,而不是平均数标准误差这告诉我们多远从人口抽样分布的均值。

当你从总体(整个数据集)生成更多样本(测试集)时,由于中心极限定理,任何统计量的采样分布都接近正态分布。 用符号X表示我们的统计信息,其抽样分布在数学上表示为:

其中n是测试集的大小,μ是分布的平均值,而σ²/ n是其方差。 我们看到采样分布的标准偏差(方差的平方根)取决于测试集大小为1 /√n,并且随着我们的样本大小趋向于零,我们的不确定性将开始发散,因此,小的数据集会带来较大的不确定性。 这正是我将在本文中通过估算用于评估二元分类器性能的4种常用统计数据的抽样分布来证明的结果:准确性,精度,召回率和ROC曲线下的面积。

模型

对于本实验,我使用了人口普查收入数据集,该数据集可从此处的UCI机器学习存储库下载,其中的任务是将一个人的年收入分类为大于或小于5万美元。 该数据集包含24,698个收入低于50k的人和7839个收入超过 50k的人。 我执行了一些基本的清理工作,例如删除重复项和包含空值的行,选择要素的子集,然后在执行任何建模之前使用多数类的随机欠采样来平衡类。 完整的代码可以在此GitHub存储库(https://github.com/job9931/Blog-notebooks/tree/main/small_data_uncertainty)中找到,你可以随意克隆并执行自己喜欢的操作。

为了简单起见,我使用逻辑回归模型对实例进行分类。本实验的核心体现在如下所示的函数evaluate_model中。它的参数是一个数据集,一个scikit-learn管道对象,其中包括数据转换对象和分类器模型,一个预测器特征列表和一个目标变量,以及一个参数,以确定测试集的大小;它返回上面提到的四个统计数据。需要注意的是,在训练-测试分割期间没有随机种子集,因此每次调用该函数时都会生成不同的测试集。通过循环调用这个函数并记录结果,我们可以建立抽样分布。

def evaluate_model(data,pipeline,features,target,test_size=0.3):
    
    #Train-test split with no random seed, so different
    #sets are generated each time function is called. 
    X, y = data[features], data[target]
    split = StratifiedShuffleSplit(n_splits=1, test_size=test_size)
    for train_index, test_index in split.split(X, y):
        X_train, X_test = X.loc[train_index], X.loc[test_index]
        y_train, y_test = y.loc[train_index], y.loc[test_index]

    #train model, fit method overwrites training on each call
    pipeline.fit(X_train,y_train)
    
    #evaluate on test set
    test_predictions = pipeline.predict(X_test)
    recall = recall_score(y_test,test_predictions)
    precision = precision_score(y_test,test_predictions)
    acc = accuracy_score(y_test,test_predictions)
    
    #calculate fpr and tpr for each threshold to get an AUROC
    test_probabilities = pipeline.predict_proba(X_test)[:,1]
    fpr, tpr, thresholds = roc_curve(y_test,test_probabilities,pos_label=1,drop_intermediate=True)
    auroc = auc(fpr,tpr)
    
    return recall, precision, acc, auroc
    
#call evaluate_model in a loop and record results
n_splits=100
Recall = np.zeros(n_splits)
Precision = np.zeros(n_splits)
Accuracy = np.zeros(n_splits)
AUC = np.zeros(n_splits)

for j in range(n_splits):
    recall, precision, auroc, acc = evaluate_model(data,pipeline,features,target)
    Recall[j] = recall
    Precision[j] = precision
    Accuracy[j] = acc
    AUC[j] = auroc

下面的柱状图显示了我们描述逻辑回归模型的四个统计数据的抽样分布估计数,数据集为1000个数据点;测试集的大小是300个数据点,因为我使用了0.3的分割比率。这里,我生成了100个样本,以节省时间和计算,我们可以看到柱状图看起来近似正常,然而,你可能想在自己的工作中生成1000或10000个样本,这取决于你想要的精确度。我们可以看到,逻辑回归模型做得很好,平均精度为0.84±0.02或84±2%。重要的是,所有这些指标都是由分布描述的,一旦我们估计了它,我们就可以计算任何我们喜欢的属性。

不确定性作为数据集大小的函数

为了说明数据集大小对不确定性的影响,我对7个数据集大小重复了上述过程:7000、5000、3000、1000、500、100、50。下面的图表显示了统计不确定性,表示为百分比,绘制为测试集大小的函数,记住,测试集大小是本实验中数据集大小的0.3倍。一旦测试集的规模下降到大约300点以下,由于抽样分布标准差的1/√n依赖性,所有统计量的不确定性开始迅速增加。这样做的结果是,对于较小的数据集,你不能真正了解你的模型的性能。

结论

在这篇文章中,我们介绍了一种快速而简单的方法,通过估计统计数据的抽样分布来计算机器学习模型的不确定性。为了简单起见,我讨论了二元分类器的情况,但这适用于任何模型和任何统计数据集,只需在许多测试集上评估你的模型,记录结果,并计算标准偏差。重要的是,这表明如果你的数据集只有几百个点,你很可能有很大的不确定性围绕着统计数据,这可能解释为什么你的新模型训练在一个小数据集表现不佳。好消息是,通过收集更多的数据,随着你的模型是活的,并定期再训练,你的不确定性将迅速下降,你将拥有一个更稳定的模型!

作者:Oliver Batey

deephub翻译组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值