1.5 Performance Evaluation
为了衡量不同模型的效果,我们通常需要在测试数据利用特定的评价标准进行评价。那么我们需要定义用什么数据进行测试,也就是如何进行数据划分;用什么指标进行模型评估,也就是模型评价指标。
1) 数据集划分
1a) Training, Test and Validation Sets
当数据量非常大时(在深度学习中比较常见),常见的做法是将数据集划分为三部分:
Training Set:在调整超参数的过程中用于训练模型的数据集
在调参的过程中用于评估超参数效果的数据集: 有的文献中称为validation set,有的文献中称为testing set,上图中标注为testing set
用来最终测试模型的泛化能力的数据集:有的文献中称为testing set,有的文献中称为validation set,上图中标注为validation set
在数据集划分的过程中,我们通常不希望某个label只在特定一个数据集中出现。一般而言这种情况出现的可能性不大,但是当样本的类别比较多,或者某些类别的样本数量特别少时,也是容易发生的。这是我们通常会采取分层划分的方式,即对于每个类别的样本,分别进行数据集划分,这样就能排除上述的可能性。
超参数是模型不能直接从数据中学习得到,而需要事先人为给定的参数。所以为了选择合适的超参数(即所谓的"调参"),需要用一个外部的数据集上的分类效果作为挑选的指标。调参的过程属于一种模型选择(model selection)。
不同领域的文献中对数据集的描述可能会有一些出入。在传统机器学习的文献中,测试集(test set)指的是在性能评估前不能见到label的样本(即最终用于性能评估的样本),验证集(validation set)指的是用来调整超参数的数据集;但是有些临床研究中会把最终用于性能评估的样本称为"验证集"。这需要大家结合具体的语境进行区分,例如上图给出的数据集命名方式对应后者。
希望具体了解的同学可以参考维基百科的介绍Training, validation, and_test data sets
拟合最终用于评估模型泛化能力的模型时,所有可以用到的数据有时被称为"discovery set"。用来最终测试模型的泛化能力的数据集,剩下的数据都属于discovery set。在上图中,training set+testing set = discovery set
上图涉及了两类性能评估:
一是评估超参数的分类效果:我们选择不同的超参数组合,用training set拟合模型,用上图的"testing set"的标签作为指标,挑选出最大化分类性能的超参数组合
二是评估模型最终的泛化能力: 挑选出我们认为最合适的超参数组合后,我们用这组超参数在所有可用数据,即discovery set上拟合模型,再用一些从未见到过标签的数据(上图的"validation set")评估模型的泛化能力,作为分类效果的最终度量
由于我们在调参的过程中最大化的是上图中的testing set上的分类效果,所以在testing set上最好的一组超参数对应的分类效果是高估的,不能最终用于模型的性能评估。
如果我们不去调整模型的超参数,直接使用一个独立于数据的经验值,则不需要上图中的"testing set"。这时training set等价于discovery set,剩下的样本可全部用来评估模型的泛化能力
当数据量比较少时(在传统机器学习的应用场景中比较常见),我们通常会多次重复这一过程,取平均值以降低最终汇报的结果受随机因素的影响。具体的做法可以大致分为三类,我们以下逐一进行介绍:
多次random split
交叉验证(Cross-Validation)
bootstrapping
1b) 多次random split
相当于把我们在1a) 中介绍的方法重复很多次,每次都能得到一个评估泛化能力的指标,这样得到的分布就考虑到了随机性的影响
1c) Cross-Validation
K-fold Cross-validation
在K折交叉验证中,数据集被均匀地划分为个部分(folds)。在每轮验证中,把个folds当做discovery set,在剩下的一个fold上评估模型分类效果。
K折交叉验证确保训练样本和测试样本之间没有重叠,K轮结束后,每个样本会被设置为测试样品一次。最后,模型平均表现是在 轮次中计算指标的平均值得到的。
如果希望在交叉验证的过程中同时对模型超参数进行调节,一种常见的做法被称为"nested cross validation",即在每个划分出的discovery set上,对给定的每一组超参数组合,都进行一轮交叉验证,用平均的分类效果当做为这一个discovery set挑选超参数的指标,再用表现最好的超参数组合在整个discovery set上拟合模型。sklearn的文档提供了一个很好的例子,请大家参考plot nested cross validation iris
K折交叉验同样可以重复多次,以考虑随机性的影响。
Leave-one-out Cross-validation
Leave-one-out Cross-validation (LOOCV)是一种极端的K折交叉验证,对应把k设成样本总数的情形。这就是说每次进行只留下一个样本用作测试集,其余m-1全为训练集,进行m次训练,取m次的评估结果的平均值进行模型选择。
LOO的好处在于有确定的结果,缺点在于计算量比较大,而且无法反映分类效果受随机因素的影响。
1d) Bootstraping
当数据集较小,难以有效划分Training/Test时,可以采用**Bootstraping(自助采样)的方法。给定包含m个样本的数据集D,我们对它进行采样产生数据集 D′:每次随机从D中挑选出一个样本,将其拷贝放入D′, 然后再将该样本放回初始数据集D中,使得该样本在下次采样时仍有可能被采样到;这个过程重复执行m次后,我们就得到可包含m个样本数据的数据集D′,这就是Bootstraping(自助采样)**的结果。样本在m次采样中始终不被采到到概率为:
初始数据集D中约有36.8%的样本未出现在采样数据集D′中。于是我们可将D′ 用于模型拟合,D-D′用于评估泛化能力。
由于bootstraping进行的是有放回抽样,同一个样本在discovery set中可能会出现多次。
1e) 实现方法
简单起见,我们暂时不考虑调参的问题。
python
[sklearn] package在sklearn.model_selection子模块实现了很多种数据集划分的方式。如果理解了上述的数据集划分具体在做什么事情,直接用numpy也可以非常容易的实现。
random split: 可使用train_test_split函数
多次random split: 我们可以在一个循环里多次调用train_test_split函数。除此之外,sklearn还提供了ShuffleSplit和StratifiedShuffleSplit两个类,分别针对需要分层抽样课不需要分层抽样的情形,可以简化这一过程的实现
交叉验证: sklearn 提供了多个类用于实现交叉验证,具体使用请大家自行参阅文档
KFold: 常规的K折交叉验证的数据集划分
StratifiedKFold: K折交叉验证,按label分层划分fold
RepeatedKFold: 常规的K折交叉验证,重复多次
RepeatedStratifiedKFold: K折交叉验证,按label分层划分fold,重复多次
bootstrapping: 我们可以用
sklearn.utils.resample
函数来实现
R
R的caret package提供了很多用于数据集划分的函数,例如:
createDataPartition: 相当于sklearn的model_selection.train_test_split或ShuffleSplit
createFolds: 类似sklearn的StratifiedKFold
createMultiFolds: 类似sklearn的RepeatedStratifiedKFold
createResample: 有放回的抽样/bootstraping
这些函数接受样本标签作为输入进行分层抽样,并返回一个列表,列表中是一些数组,对应一次划分的训练集或测试集的标号。详细的说明请大家参考caret的文档。
请大家注意,R package通常通过数据类型区分分类问题和回归问题。
例如,如果我们们希望对分类问题根据标签进行分层划分,如果希望caret有预期的行为,就应当保证输入的样本标签是因子类型而不是数值类型
2) Performance Evaluation
2a) Confusion matrix
最常用的评估分类模型表现的方法是构建一个混淆矩阵(confusion matrix)
Confusion matrix会总结模型正确和错误分类的样本数量,并将预测的样本分成如下四类:
真实值 | 真实值 | 总数 | |
---|---|---|---|
Condition Positive | Condition Negative | ||
Predicted Condition Positive | True Positive(TP) | False Positive(FP) | P' |
Predicted Condition Negative | False Negative(FN) | True Negative(TN) | N' |
总数 | P | N |
真阳性(TP):正确的肯定,诊断为有,实际上也有癌症。
伪阳性(FP):错误的肯定,诊断为有,实际上却没有癌症。第一型错误。
真阴性(TN):正确的否定,诊断为没有,实际上也没有癌症。
伪阴性(FN):错误的否定,诊断为没有,实际上却有癌症。第二型错误。
我们可以通过python函数获得TP,FP,TN,FN。
2b) Evaluation Scores
Accuracy (0 ~ 1)
summarizes both positive and negative predictions, but is biased if the classes are imbalanced:
Sensitivity (0 ~ 1)
Also called Recall, True Positive Rate (TPR). It _**_summarizes how well the model finds out positive samples:
Specificity (0 ~ 1)
Also called True Negative Rate, which equals 1 - False Positive Rate (FPR), FPR=FP/(TN+FP)。
Precision/positive Predictive Value (PPV) (0 ~ 1)
summarizes how well the model finds out negative samples:
F1 score (0 ~ 1)
balances between positive predictive value (PPV) and true positive rate (TPR) and is more suitable for imbalanced dataset:
Matthews correlation coefficient (MCC) (-1 ~ 1)
another metric that balances between recall and precision:
2c) ROC Curve
有时一个固定的cutoff不足以评估模型性能。 Receiver Operating Characterisic(ROC)曲线可以评估模型的表现。 ROC曲线是根据在不同分类阈值下计算得到TPR和FPR,然后得到一系列的成对的TPR和FPR。ROC曲线对于类别不平衡问题也有比较好的评估。
如下图,描述了True Positive Rate (TPR)和False Positive Rate (FPR)之间的关系。TPR和FPR之间是成正比的,TPR高,FPR也高。x轴是FPR,y轴是TPR。ROC曲线下面积(AUROC)是一个单值,它总结了不同截止值下的模型平均表现,常常用于报告模型的分类表现。AUROC接近于1,可以认为模型的分类效果很好。
2d) Plot ROC with python
另外我们可以通过python函数完成这个过程。示例中是通过x预测y。最后用预测的y对照真实的y进行ROC绘制。
结果如下:
2e) Plot ROC with R
我们也可以通过R完成这个过程。示例中是通过x预测y。最后用预测的y对照真实的y进行ROC绘制。
结果如下:
3) Tips:Confidence interval of sensitivity
根据混淆矩阵可以计算得到Sensitivity和Specificity:
Sensitivity是指是指实际为阳性的样本中,判断为阳性的比例,可以认为是伯努利实验成功的概率p的点估计。
因此Sensitivity的置信区间可等价于努利实验成功的概率p的置信区间估计。
3a) 大样本量计算 - 正态分布近似
当样本数较大(N>30)时,根据中心极限定律可以利用正太分布近似成功概率p。
在线工具
通过下面链接完成计算, http://vassarstats.net/clin1.html。
R实现
可以通过R软件binom包实现,需要已知TP,FN。
3b) 大样本/中等样本量计算 - Bootstrap方法
Bootstrap估计是利用重复抽样的方法对参数进行估计的。我们可以通过R软件pROC包中Bootstrap估计进行Sensitivity的区间估计,这里为非参数估计。当样本量较大或者中等时,可采用这种方式。
可以利用R软件pROC包实现:
3c) 小样本量计算 - 其他精确近似方法
当样本量较小时,我们可以威尔逊区间法或者Pearson-Klopper方法等。我们可以通过R的binom包实现,需要已知TP,FN。
exact - Pearson-Klopper method. See also binom.test
wilson - Wilson method.
其他的近似方法可以调节binom.confint中method参数。
4) Homework
用你熟悉的脚本语言对BreastCancer数据集的预测结果 BreastCancer_predict.txt 进行评估,画出ROC curve,提交代码和ROC curve的图片。BreastCancer_predict.txt 中第一列为真实的数据标签,包括良性(benign,0)和恶性(malignant,1),第二列为预测为正类(malignant,1)的概率值,用制表符"\t"分隔。
对机器学习比较熟悉的同学可以选择自己训练二分类模型(使用任意分类器均可)并绘制ROC曲线。输入为 BreastCancer.csv 数据集,第一列为样本编号,最后一列是样本标签,剩下9列对应9个特征,用逗号","分隔。 如果自己拟合模型,需要进行数据空缺值填充(用特征的样本中位数补全缺失值),必要时做data scaling,并自行划分数据集。
Last updated