机器学习入门(二)——模型评价指标

1.0 模型评价思想

        与一般的产品质量检验类似,模型的评价就是对模型的功能——预测的好坏及稳健性进行评判,本文介绍的指标也是围绕这一目标进行的。

1.1 测试集与验证集

        通常应准备两套数据集,一套用于对模型进行训练(拟合),即测试集,用于训练模型的预测效果;另一套数据用于检验,即验证集,用于验证模型的预测效果。

1.2 数据分割

         通常所获得的数据是一套整体,因此需要对其进行分割。sklearn中有相应的方法可以直接使用:


from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=666)


        其中,test_size是划分比例,即从数据集中抽取多少比例作为测试集,非必需参数,默认就是0.2,可根据需要调整。random_state是随机种子,非必需参数,给定random_state参数的好处在于便于调试,否则每运行一次train_test_split()数据集分割的结果都会改变。

1.3 数据分割思路

        通常为提高模型效果的准确性和稳定性,仅采用一组测试集是不够的。为了充分使用数据集的价值,通常会将数据集分割为独立不同的5组(如前20%,20%~40%,40%~60%,60%~80%,后20%),每一组分别作为测试集(剩余数据作为验证集)完成一次测试训练和验证,共通过5次训练后所得的模型结果能够相对稳定。

1.4 随机数据集与有序数据集

        有时候我们得到的数据集的标签向量的数据组织方式是不同的。一种是随机的,如sklearn中的digits数据集,其标签为array([0, 1, 2, ..., 8, 9, 8]),数值之间是随机排列的。这种数据直接使用train_test_split()进行数据分割即可。如需要划分为独立的若干组的话可以直接用切片器分割

        另一种是序数化的,如sklearn中的iris数据集,其标签为array([0, 0, ... 0, 0, 1, 1... 1, 1, 2, 2 ... 2, 2]),数值是按照从小到大顺序排列的,此时若以此取20%的数据作为训练集或出现较大的偏差,因此需要先对数据做乱序处理,在进行数据分割。


#数据乱序方法一:打乱索引,然后按照乱序后的索引分割数据;便于重复操作,分割灵活性更高;

from sklearn import datasets

import numpy as np

iris = datasets.load_iris()

X = iris.data

y = iris.target

shuffle_index = np.random.permutation(len(X))  #permutation()生成从0到len(X)-1的乱序索引

test_size = int(len(shuffle_index) * 0.2)

train_index = shuffle_index[:test_size]  #取前20%作为测试集的索引

test_index = shuffle_index[test_size:]  #剩余作为验证集的索引

X_train = X[train_index]

X_test = X[test_index]

y_train = y[train_index]

y_test = y[test_index]


#数据乱序方法二:直接打乱数据

(包导入略,数据导入略)

temp = np.concatenate((X, y.reshape(-1,1)), axis=1)  #concatenate()对X和y进行拼接,axis=1按列拼接

np.random.shuffle(tempConcat)  #打乱数据集

shuffle_X,shuffle_y = np.split(tempConcat, [4], axis=1)  #从打乱后的数据集中把特征向量和标签向量分开

X_train, X_test, y_train, y_test = train_test_split(shuffle_X, shuffle_y, test_ratio=0.2, random_state=666)


2.0 模型评价的指标

2.1 分类模型

2.1.1 分类准确度accuracy

        准确度accuracy是最直接、最简单的评价指标,该评价指标直接对验证数据的预测标签与实际标签进行比较,统计结果相同的数量,即为准确量,而准确量的占验证数据总量的百分比即为准确率。

        sklearn中的accuracy计算:


from sklearn.model_selection import train_test_split

from sklearn.metrics import accuracy_score

from sklearn.neighbors import KNeighborsClassifier

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=666)

kNN_clf = KNeighborsClassifier(n_neighbors=3)

kNN_clf.fit(X_train, y_train)

y_predict = kNN_clf.predict(X_test)

accuracy_score(y_test, y_predict)  # 需要把预测结果y_predict输入

kNN.score(X_test, y_test)  #无需y_predict


2.1.2 超参数及网格搜索

        在得到分类模型的准确性评分之后,该如何调整模型以使分数变得更高呢?这就需要超参数实现。

        所谓超参数,就是在机器学习算法模型执行之前需要指定的参数。常说的调参就是调的超参数,如kNN算法中的k和w。

        与超参数相对的概念是模型参数,即算法学习训练过程中得到的参数,如回归模型中的回归系数,kNN中没有模型参数。

        以kNN为例,kNN中包含两个超参数,一个是k,即指定的近邻数量;一个是w,即判断近邻重要性的权重指标,默认值为"uniform",即无论距离原因,所有近邻点的权重均一样,也可指定为"distance",即距离越近权重越高,具体的权重值为距离的倒数。当w设置为distance时,还有另一个参数p,就是距离的计算方式,距离的计算为明可夫斯基距离,默认情况下p=2,明可夫斯基距离即欧式距离,当p=1时明可夫斯基距离即为曼哈顿距离,也可设置为更高次。

        网格搜索就是通过对不同的参数组合进行试验,最终得到使得模型准确性最高的那一组参数。

        sklearn中的kNN的超参数和网格搜索GridSearch:


(数据导入、包导入略)

from sklearn.model_selection import GridSearchCV  # 导入网格搜索包

param_search = [   # 超参数组合

    {"weights" : ["uniform"], "n_neighbors" : [i for i in range(1,11)]},

    {"weights" : ["distance"], "n_neighbors" : [i for i in range(1,11)], "p" : [i for i in range(1,6)]}

]

kNN_clf = KNeighborsClassifier()

grid_search = GridSearchCV(kNN_clf, param_search)

grid_search.fit(X_train, y_train)

grid_search.best_estimator_  # 查看测试集下的最佳参数组合

grid_search.best_score_  # 查看测试集下的最佳参数组合的准确性得分

kNN_clf = grid.search.best_estimator_  #用最佳参数构建分类器

kNN_clf.score(X_test, y_test)  # 最佳参数组合的验证集得分


2.2 混淆矩阵与精准率,召回率

        分类的准确度accuracy在评价分类算法时,会有很大的问题的,尤其是在遇到极度偏斜(Skewed Data)的数据,只使用分类准确度是不能衡量。这就需要混淆矩阵来判别。

2.2.1 混淆矩阵 confusion matrix

        TN:实际为0,预测为0 (Negative),预测正确 (True)

        FP:实际为0,预测为1 (Positive),预测错误 (False)

        FN:实际为1,预测为0 (Negative),预测错误 (False)

        TP:实际为1,预测为1 (Positive),预测正确 (True)

2.2.2 精准率precision 和 召回率recall

        现在假设有1万人对某项疾病进行预测,对结果建立混淆矩阵如下:

        依据上表的例子,计算精准率和召回率:

        精准率presicion = TP/(TP+FP) = 8/(8+12) = 40%

        召回率recall = TP/(TP+FN) = 8/(8+2) = 80%

        精准率presicion,描述的是在所有预测值为1的里面,实际值也是1的比例。犹如射击的准度一样,开了20枪,有8枪命中目标。精准率的关注点在于“准”,也成为查准率。

        召回率recall,描述的是在所有真实值为1的里面,预测值也是1的比例。犹如召回事件一样,所有的有问题的产品中,有多少被召回了。召回率的关注点在于“全”,也称为查全率。

        从上表的例子来看,模型预测的准确度达到了99.86%,但从精准率和召回率的结果来看,高准确度却没有什么意义。

        sklearn中的混淆矩阵、精准率和召回率:


from sklearn.metrics import confusion_matrix  # 导入confusion_matrix包

confusion_matrix(y_test, y_predict)

from sklearn.metrics import precision_score  # 导入presicion_score包

precision_score(y_test, y_predict)

from sklearn.metrics import recall_score  #导入recall_score包

recall_score(y_test, y_log_predict)


2.3 F1 score

        那么精准率和召回率这两个指标,对于同一个模型来说,到底应该关注哪一个?或者是如何综合考量这两个指标?下面回答这些问题。

        首先,二者之间的选取,需要根据实际的需要来看。如前面所给的指标解释,精准率关注的就是“准”,召回率关注的是“全”,那么当“准”的重要性高于“全”时,则主要看精准率,如股票涨跌的预测、项目可行性的预测等,因为当预测能够有收益时,我们希望是抓住每一次的机会,从而得到真实的收益,此时全不全并不重要,因为不可能把所有上涨的股票或可行的项目都覆盖到。而在召回有问题的商品时,希望达到的是尽可能全面,因为一旦有问题商品未被召回,可能会引发更大的问题。

        其次,当需要综合考虑这两个指标的时候,此时使用新的指标F1 score。均值一直是综合考虑若干个指标特征是的常规选择,这里F1 score就是精准率和召回率的调和平均数:

                                                 1/F1 score = 1/precision + 1/recall

        sklearn中没有计算F1 score的直接方法,可以按照以上公式进行计算。

2.4 ROC和AUC

2.4.1 分类阈值

        分类阈值,即设置判断样本为标签为1的阈值thr。功能上可以理解未及格线,及格线以上的为1,及格线以下的为0。

        sklearn中在建立好机器学习模型后,会有一个decision_function()方法,返回各个样本的标签值或类别值(当阈值为及格线时,标签值就是考试分数):


decision_scores = reg.decision_function(X_test)

y_predict = np.array(decision_score >= 5, dtype='int')  # 返回阈值为5时的分类结果


        精准率和召回率这两个指标有内在的联系,并且相互冲突。precision随着阈值的增加而增加,recall随着阈值的增大而减小。如果某些场景需要precision,recall都保持在80%,可以通过调整阈值方找出合适的阈值。

2.4.2 TPR和FRP

        TPR是指预测为1占实际就为1的比例,其实就是召回率,TPR = TP/(TP+FN)

        FPR与TPR完全相反,是指预测为1占实际为0的比例(可以理解为判错率),FPR = FP/(FP+TN)

2.4.3 ROC曲线

        那么,当阈值变化时,TPR和FPR会有不同的取值组合,将TPR(y轴)和FPR(x轴)取值组合会旨在二维坐标系中,所得到的曲线就是ROC(receiver operation characteristic curve)曲线。

        从上面可知,TPR就是判断对的比例,FPR是判断错比例。从机器学习的角度来说,目标当然是判对的比例越高越好,判错的比例越低越好。但从ROC曲线的形式可以知道,TPR和FPR是正向关联的,当TPR提高的时候,FPR也不免被提高。

        sklearn中的ROC:


(数据和包导入略)

from sklearn.metric import roc_curve

fprs, tprs, thrs = roc_curve(y_test, decision_score)

plt.plot(fprs, tprs)

plt.show()


        对于ROC的解读其实很简单,模型的目标是TPR越高、FPR越低,因此ROC曲线距离左上角越近,证明模型效果越好。当两个模型比较时,若模型1的ROC曲线从左上方完全包含模型2,则可以断定模型1优于模型2。

       很多时候两个模型的ROC曲线存在相交,无法直接判断哪个模型效果更好,此时可以计算曲线下的面积作为性能度量,即AUC。

2.4.4 AUC

         AUC(Area Under Curve)就是ROC曲线向下与X轴之间的面积。

        由于ROC曲线的X和Y轴的区间均是(0,1),因此AUC的面积同样是属于(0,1)。

        当AUC = 1,是完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。AUC = 0.5,跟随机猜测一样,模型没有预测价值。AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测。

        sklearn中的AUC:


from sklearn.metrics import roc_auc_score

roc_auc_score(y_test, decision_scores)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容