【06】机器学习算法——评估方法总结
分类的评估方法
1.精确率与召回率
(1)混淆矩阵
在分类任务下,预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合,构成混淆矩阵(适用于多分类)
(2)精准率(Precision)与召回率(Recall)
-
精确率:预测结果为正例样本中真实为正例的比例(了解)
-
召回率:真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)
- 还有其他的评估标准,F1-score,反映了模型的稳健型
分类评估报告API
- sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )
-
- y_true:真实目标值
- y_pred:估计器预测目标值
- labels:指定类别对应的数字
- target_names:目标类别名称
- return:每个类别精确率与召回率
print("精确率和召回率为:", classification_report(y_test, lr.predict(x_test), labels=[2, 4], target_names=['良性', '恶性']))
假设这样一个情况,如果99个样本癌症,1个样本非癌症,不管怎样我全都预测正例(默认癌症为正例),准确率就为99%但是这样效果并不好,这就是样本不均衡下的评估问题
2.ROC曲线与AUC指标
模型有很多评估方法,为什么还要使用ROC和AUC呢?
因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变换的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现样本类不平衡,即正负样本比例差距较大,而且测试数据中的正负样本也可能随着时间变化。
- ROC全称是“受试者工作特征”(Receiver Operating Characteristic)。
- ROC曲线的面积就是AUC(Area Under Curve)。
- AUC用于衡量“二分类问题”机器学习算法性能(泛化能力)。
ROC曲线,通过将连续变量设定出多个不同的临界值,从而计算出一系列真正率和假正率,再以假正率为横坐标、真正率为纵坐标绘制成曲线,曲线下面积越大,推断准确性越高。在ROC曲线上,最靠近坐标图左上方的点为假正率和真正率均较高的临界值。
对于分类器,或者说分类算法,评价指标主要有Precision,Recall,F-score。下图是一个ROC曲线的示例。
ROC曲线的横坐标为False Positive Rate(FPR),纵坐标为True Positive Rate(TPR)。其中
T
P
R
=
T
P
T
P
+
F
N
,
F
P
R
=
F
P
F
P
+
T
N
TPR = frac{TP}{TP+FN} ,FPR = frac{FP}{FP+TN}
TPR=TP+FNTP,FPR=FP+TNFP
下面着重介绍ROC曲线图中的四个点和一条线
- 第一个点(0,1),即FPR=0, TPR=1,这意味着FN(False Negative)=0,并且FP(False Positive)=0。意味着这是一个完美的分类器,它将所有的样本都正确分类。
- 第二个点(1,0),即FPR=1,TPR=0,意味着这是一个最糟糕的分类器,因为它成功避开了所有的正确答案。
- 第三个点(0,0),即FPR=TPR=0,即FP(False Positive)=TP(True Positive)=0,可以发现该分类器预测所有的样本都为负样本(Negative)。
- 第四个点(1,1),即FPR=TPR=1,分类器实际上预测所有的样本都为正样本。
- 经过以上分析,ROC曲线越接近左上角,该分类器的性能越好。
ROC曲线所覆盖的面积称为AUC(Area Under Curve),可以更直观的判断学习器的性能,AUC越大则性能越好。
(1)知道TPR与FPR
- TPR = TP / (TP + FN)
- 所有真实类别为1的样本中,预测类别为1的比例
- FPR = FP / (FP + FN)
- 所有真实类别为0的样本中,预测类别为1的比例
1、分析数据
y_true = [0, 0, 1, 1];scores = [0.1, 0.4, 0.35, 0.8];
2、列表
样本 | 预测属于P的概率(score) | 真实类别 |
---|---|---|
y[0] | 0.1 | N |
y[1] | 0.4 | N |
y[2] | 0.35 | P |
y[3] | 0.8 | P |
3、将截断点依次取为score值,计算TPR和FPR。
当截断点为0.1时:
说明只要score>=0.1,它的预测类别就是正例。 因为4个样本的score都大于等于0.1,所以,所有样本的预测类别都为P。
scores = [0.1, 0.4, 0.35, 0.8];y_true = [0, 0, 1, 1];y_pred = [1, 1, 1, 1];
正例与反例信息如下:
正例 | 反例 | |
---|---|---|
正例 | TP=2 | FN=0 |
反例 | FP=2 | TN=0 |
由此可得:
TPR = TP/(TP+FN) = 1; FPR = FP/(TN+FP) = 1;
当截断点为0.35时:
scores = [0.1, 0.4, 0.35, 0.8];y_true = [0, 0, 1, 1];y_pred = [0, 1, 1, 1];
正例与反例信息如下:
正例 | 反例 | |
---|---|---|
正例 | TP=2 | FN=0 |
反例 | FP=1 | TN=1 |
由此可得:
TPR = TP/(TP+FN) = 1; FPR = FP/(TN+FP) = 0.5;
当截断点为0.4时:
scores = [0.1, 0.4, 0.35, 0.8];y_true = [0, 0, 1, 1];y_pred = [0, 1, 0, 1];
正例与反例信息如下:
正例 | 反例 | |
---|---|---|
正例 | TP=1 | FN=1 |
反例 | FP=1 | TN=1 |
由此可得:
TPR = TP/(TP+FN) = 0.5; FPR = FP/(TN+FP) = 0.5;
当截断点为0.8时:
scores = [0.1, 0.4, 0.35, 0.8];y_true = [0, 0, 1, 1];y_pred = [0, 0, 0, 1];
正例与反例信息如下:
正例 | 反例 | |
---|---|---|
正例 | TP=1 | FN=1 |
反例 | FP=0 | TN=2 |
由此可得:
TPR = TP/(TP+FN) = 0.5; FPR = FP/(TN+FP) = 0;
4、根据TPR、FPR值,以FPR为横轴,TPR为纵轴画图。
(2)ROC曲线
- ROC曲线的横轴就是FPRate,纵轴就是TPRate,当二者相等时,表示的意义则是:对于不论真实类别是1还是0的样本,分类器预测为1的概率是相等的,此时AUC为0.5
如何画ROC曲线
-
下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率。
-
步骤:
1、假设已经得出一系列样本被划分为正类的概率,按照大小排序。
2、从高到低,依次将“Score”值作为阈值threshold,当测试样本属于正样本的概率大于或等于这个threshold时,我们认为它为正样本,否则为负样本。举例来说,对于图中的第4个样本,其“Score”值为0.6,那么样本1,2,3,4都被认为是正样本,因为它们的“Score”值都大于等于0.6,而其他样本则都认为是负样本。
3、每次选取一个不同的threshold,得到一组FPR和TPR,即ROC曲线上的一点。以此共得到20组FPR和TPR的值。
4、根据3、中的每个坐标点,画图。
(3)AUC指标
- AUC的概率意义是随机取一对正负样本,正样本得分大于负样本的概率
- AUC的最小值为0.5,最大值为1,取值越高越好
- AUC=1,完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
- 0.5<AUC<1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
最终AUC的范围在[0.5, 1]之间,并且越接近1越好
如何计算AUC
- 将坐标点按照横坐标FPR排序 。
- 计算第
i
i
i
+
1
i+1
d
x
dx
- 获取第
i
i
i
+
1
i+1
- 计算面积微元
d
s
=
y
d
x
ds=ydx
- 对面积微元进行累加,得到AUC。
(4)AUC计算API
from sklearn.metrics import roc_auc_score
sklearn.metrics.roc_auc_score(y_true, y_score)
- 计算ROC曲线面积,即AUC值
- y_true:每个样本的真实类别,必须为0(反例),1(正例)标记
- y_score:每个样本预测的概率值
# 0.5~1之间,越接近于1约好
y_test = np.where(y_test > 2.5, 1, 0)
print("AUC指标:", roc_auc_score(y_test, lr.predict(x_test)))
(5)总结
- AUC只能用来评价二分类
- AUC非常适合评价样本不平衡中的分类器性能
回归性能评估
- 均方误差(Mean Squared Error)MSE)评价机制:
M
S
E
=
1
m
∑
i
=
1
m
(
y
i
−
y
^
)
2
y
i
为
预
测
值
y
^
为
真
实
值
MSE = frac{1}{m}sum_{i=1}^{m}(y^i-hat{y})^2\y^i为预测值\ hat{y}为真实值
MSE=m1i=1∑m(yi−y^)2yi为预测值y^为真实值
- sklearn.metrics.mean_squared_error(y_true, y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
聚类评估
1.聚类算法优劣衡量标准
- 不同聚类算法有不同的优劣和不同的适用条件。可从以下方面进行衡量判断:
- 算法的处理能力:处理大的数据集的能力,即算法复杂度;处理数据噪声的能力;处理任意形状,包括有间隙的嵌套的数据的能力;
- 算法是否需要预设条件:是否需要预先知道聚类个数,是否需要用户给出领域知识;
- 算法的数据输入属性:算法处理的结果与数据输入的顺序是否相关,也就是说算法是否独立于数据输入顺序;算法处理有很多属性数据的能力,也就是对数据维数是否敏感,对数据的类型有无要求。
2. 聚类和分类有什么区别
聚类(Clustering)
- 聚类,简单地说就是把相似的东西分到一组,聚类的时候,我们并不关心某一类是什么,我们需要实现的目标只是把相似的东西聚到一起。一个聚类算法通常只需要知道如何计算相似度就可以开始工作了,因此聚类通常并不需要使用训练数据进行学习,在机器学习中属于无监督学习。
分类(Classification)
- 分类,对于一个分类器,通常需要你告诉它“这个东西被分为某某类”。一般情况下,一个分类器会从它得到的训练集中进行学习,从而具备对未知数据进行分类的能力,在机器学习中属于监督学习。
3.不同聚类算法特点性能比较
算法名称 | 可伸缩性 | 适合的数据类型 | 高维性 | 异常数据抗干扰性 | 聚类形状 | 算法效率 |
---|---|---|---|---|---|---|
WAVECLUSTER | 很高 | 数值型 | 很高 | 较高 | 任意形状 | 很高 |
ROCK | 很高 | 混合型 | 很高 | 很高 | 任意形状 | 一般 |
BIRCH | 较高 | 数值型 | 较低 | 较低 | 球形 | 很高 |
CURE | 较高 | 数值型 | 一般 | 很高 | 任意形状 | 较高 |
K-PROTOTYPES | 一般 | 混合型 | 较低 | 较低 | 任意形状 | 一般 |
DENCLUE | 较低 | 数值型 | 较高 | 一般 | 任意形状 | 较高 |
OPTIGRID | 一般 | 数值型 | 较高 | 一般 | 任意形状 | 一般 |
CLIQUE | 较高 | 数值型 | 较高 | 较高 | 任意形状 | 较低 |
DBSCAN | 一般 | 数值型 | 较低 | 较高 | 任意形状 | 一般 |
CLARANS | 较低 | 数值型 | 较低 | 较高 | 球形 | 较低 |
模型选择与调优
- 说明交叉验证过程
- 说明超参数搜索过程
- 应用GridSearchCV实现算法参数的调优
(1)为什么需要交叉验证
交叉验证目的:为了让被评估的模型更加准确可信
- 为了得到更为稳健可靠的模型,对模型的泛化误差进行评估,得到模型泛化误差的近似值。当有多个模型可以选择时,我们通常选择“泛化误差”最小的模型。
- 交叉验证的方法有许多种,但是最常用的是:留一交叉验证、k折交叉验证。
(2)什么是交叉验证(cross validation)理解k折交叉验证
交叉验证:将拿到的训练数据,分为训练和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。
- 将含有N个样本的数据集,分成K份,每份含有N/K个样本。选择其中1份作为测试集,另外K-1份作为训练集,测试集就有K种情况。
- 在每种情况中,用训练集训练模型,用测试集测试模型,计算模型的泛化误差。
- 交叉验证重复K次,每份验证一次,平均K次的结果或者使用其它结合方式,最终得到一个单一估测,得到模型最终的泛化误差。
- 将K种情况下,模型的泛化误差取均值,得到模型最终的泛化误差。
- 一般
2
⩽
K
⩽
10
2leqslant K leqslant10
- 训练集中样本数量要足够多,一般至少大于总样本数的50%。
- 训练集和测试集必须从完整的数据集中均匀取样。均匀取样的目的是希望减少训练集、测试集与原数据集之间的偏差。当样本数量足够多时,通过随机取样,便可以实现均匀取样的效果。
(3)分析
我们之前知道数据分为训练集和测试集,但是**为了让从训练得到模型结果更加准确。**做以下处理
- 训练集:训练集+验证集
- 测试集:测试集
验证集 | 训练集 | 训练集 | 训练集 | 80% |
---|---|---|---|---|
训练集 | 验证集 | 训练集 | 训练集 | 78% |
训练集 | 训练集 | 验证集 | 训练集 | 75% |
训练集 | 训练集 | 训练集 | 验证集 | 82% |
问题:那么这个只是对于参数得出更好的结果,那么怎么选择或者调优参数呢?
(4)超参数搜索-网格搜索(Grid Search)
通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。
K值 | K=3 | K=5 | K=7 |
---|---|---|---|
模型 | 模型1 | 模型2 | 模型3 |
(5)模型选择与调优API
sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
- 对估计器的指定参数值进行详尽搜索
- estimator:估计器对象
- param_grid:估计器参数(dict){“n_neighbors”:[1,3,5]}
- cv:指定几折交叉验证
- fit:输入训练数据
- score:准确率
- 结果分析:
- bestscore:在交叉验证中验证的最好结果_
- bestestimator:最好的参数模型
- cvresults:每次交叉验证后的验证集准确率结果和训练集准确率结果
(6)例子:Facebook签到位置预测K值调优
- 使用网格搜索估计器
# 使用网格搜索和交叉验证找到合适的参数
knn = KNeighborsClassifier()
param = {"n_neighbors": [3, 5, 10]}
gc = GridSearchCV(knn, param_grid=param, cv=2)
gc.fit(x_train, y_train)
print("选择了某个模型测试集当中预测的准确率为:", gc.score(x_test, y_test))
# 训练验证集的结果
print("在交叉验证当中验证的最好结果:", gc.best_score_)
print("gc选择了的模型K值是:", gc.best_estimator_)
print("每次交叉验证的结果为:", gc.cv_results_)
常见的类别不平衡问题解决方法
- 防止类别不平衡对学习造成的影响,在构建分类模型之前,需要对分类不平衡性问题进行处理。主要解决方法有:
1、扩大数据集
- 增加包含小类样本数据的数据,更多的数据能得到更多的分布信息。
2、对大类数据欠采样
- 减少大类数据样本个数,使与小样本个数接近。
- 缺点:欠采样操作时若随机丢弃大类样本,可能会丢失重要信息。
- 代表算法:EasyEnsemble。其思想是利用集成学习机制,将大类划分为若干个集合供不同的学习器使用。相当于对每个学习器都进行欠采样,但对于全局则不会丢失重要信息。
3、对小类数据过采样
- 过采样:对小类的数据样本进行采样来增加小类的数据样本个数。
- 代表算法:SMOTE和ADASYN。
- SMOTE:通过对训练集中的小类数据进行插值来产生额外的小类样本数据。
- 新的少数类样本产生的策略:对每个少数类样本a,在a的最近邻中随机选一个样本b,然后在a、b之间的连线上随机选一点作为新合成的少数类样本。
- ADASYN:根据学习难度的不同,对不同的少数类别的样本使用加权分布,对于难以学习的少数类的样本,产生更多的综合数据。 通过减少类不平衡引入的偏差和将分类决策边界自适应地转移到困难的样本两种手段,改善了数据分布。
- SMOTE:通过对训练集中的小类数据进行插值来产生额外的小类样本数据。
4、使用新评价指标
- 如果当前评价指标不适用,则应寻找其他具有说服力的评价指标。比如准确度这个评价指标在类别不均衡的分类任务中并不适用,甚至进行误导。因此在类别不均衡分类任务中,需要使用更有说服力的评价指标来对分类器进行评价。
5、选择新算法
- 不同的算法适用于不同的任务与数据,应该使用不同的算法进行比较。
6、数据代价加权
- 例如当分类任务是识别小类,那么可以对分类器的小类样本数据增加权值,降低大类样本的权值,从而使得分类器将重点集中在小类样本身上。
7、转化问题思考角度
- 例如在分类问题时,把小类的样本作为异常点,将问题转化为异常点检测或变化趋势检测问题。 异常点检测即是对那些罕见事件进行识别。变化趋势检测区别于异常点检测在于其通过检测不寻常的变化趋势来识别。
8、将问题细化分析
- 对问题进行分析与挖掘,将问题划分成多个更小的问题,看这些小问题是否更容易解决。