机器学习预测结果评价

作者:jcmp      发布时间:2021-04-26      浏览量:0
对机器学习的预测结果的评价,以前只用到了

对机器学习的预测结果的评价,以前只用到了准确率,知道还有召回率,精准率这些词,但是一直理解的的比较浅显,所以今天找个时间来学习下。

有的时候我们不能仅仅用准确率,还需要关心其他指标,比如说医学上进行化验的时候,除了准确率,召回率也是我们关心的问题;搜索的时候,也许我们想更大范围地去查找,这时候召回率就非常重要。这些名词傻傻分不清楚,别怕,让我们来一起学习下。

一 分类问题的评价指标

谈到分类的结果问题,都会有一个叫二分类混淆矩阵的东西:

预测正例 预测反例 真实正例 TP (真正例) FN(假反例) 真实反例 FP(反正例) TN(真反例)。

解释下: T 表示True,F表示fasle; P positive 表示正例; N:Negative表示反例。 这样我们解读的时候:FP 表示 F-反 P(正例) 所以表示反正例。 比如我们一个池塘里面有鲫鱼和螃蟹,各有30只和70只,那么如果我们想打捞鲫鱼(正例为鲫鱼反例为螃蟹)。 结果捞出来30只,25只鲫鱼,5只螃蟹。 TP = 25 【25个鲫鱼 所以真正例为25】 FP = 5 【捞出5个螃蟹,所以假正例为 5】 TN = 65 【真反例 65个螃蟹,水中】 FN = 5 【假反例 5个鲫鱼当成螃蟹了,水中】

import numpy as np#正反例 y_predict 表示预测结果def TN(y_true, y_predict): return np.sum((y_true == 0) & (y_predict == 0))#假正例def FP(y_true, y_predict): return np.sum((y_true == 0) & (y_predict == 1))#假反例def FN(y_true, y_predict): return np.sum((y_true == 1) & (y_predict == 0))#真正例def TP(y_true, y_predict): return np.sum((y_true == 1) & (y_predict == 1))。

混淆矩阵结果:

def confusion_matrix(y_test, y_predict): return np.array([ [TN(y_test, y_log_predict), FP(y_test, y_log_predict)], [FN(y_test, y_log_predict), TP(y_test, y_log_predict)] ])#或from sklearn.metrics import confusion_matrixconfusion_matrix(y_true, y_predict)。

1.1 精准率和找回率

精准率表示预测结果中正确结果的个数: precision = TP/(TP+FP)。

用的是查出正样品的数量,除正样本和负样本之和。

def precision_score(y_true, y_predict): tp = TP(y_true, y_predict) fp = FP(y_true, y_predict) try: return tp / (tp + fp) except: return 0.0。

算下刚才的鲫鱼精准率: 即捞出来的所有鱼类中,鲫鱼的数量。 鲫鱼精准率 = 25 /(25+5 ) = 0.833。

还有一个准确率,不要和精准率混合了: accuracy = (TP+TN)/(TP+TN+FP+FN) 算下刚才捞鲫鱼的准确率: 25+65/100 = 90%

召回率 ,所有正分类中,预测到正分类占所有的正分类的比率: recall = TP/(TP+FN) 鲫鱼召回率 = 25 /30 = 0.833。

def recall_score(y_true, y_predict): tp = TP(y_true, y_predict) fn = FN(y_true, y_predict) try: return tp / (tp + fn) except: return 0.0。

用sklearn 计算精准率和召回率:

from sklearn.metrics import precision_scoreprecision_score(y_true, y_predict)from sklearn.metrics import recall_scorerecall_score(y_true, y_predict)#多分类中的召回率和准确率from sklearn.metrics import precision_scoreprecision_score(y_test, y_predict, average='micro')。

1.2 F1值

精准率,说明数据多少个是正确的,比如如果我们在告警的时候更强调准确性,那就是精准率要求高;召回率:表示是不是所有要获取的数据都已经获取到了,比如如果我们要进行医疗诊断,更强调有问题的都覆盖了,那就用召回率。

这两者是矛盾的,想刚才的例子,如果我一下捞出100只鱼类,那肯定30只鲫鱼在里面,召回率为100%,但是精准率只能为30%。 1/F1 = 1/2(1/precision + 1/recall) F1 = 2*precision *recall/(precision +recall) F1 是精准率和调和率的平均值,只有两者都高的时候F1才高,所以一般机器学习模型预测结果好坏,用F1值表示更恰当。

def f1_score(y_true, y_predict): precision = precision_score(y_true, y_predict) recall = recall_score(y_true, y_predict) try: return 2 * precision * recall / (precision + recall) except: return 0.0#用sklear计算:from sklearn.metrics import f1_scoref1_score(y_true, y_predict)。

二 Precision-Recall 曲线【这部分还没懂】

Scikit Learn 的逻辑回归中的概率公式为 ,其决策边界为 ,但是如果决策边界不为0会如何呢?

假定决策边界为 ,当 threshold 的取值不同(0、大于0的某个值、小于0的某个值),对应的精确度和召回率也不同。如图:

圆形和星形是不同的的分类,并且重点放在星形的分类上,可以看出,threshold 的取值越大时,精确率越高,而召回率越低。

如果要更改决策边界,逻辑回归的 decision_function() 返回传入数据的 计算结果 decision_scores,接着再构建一个新的预测结果;如代码所示,设定 decision_scores >= 5(默认decision_scores >= 0 ) 的预测结果才为1,其余为0:

from sklearn.linear_model import LogisticRegressionlog_reg = LogisticRegression()# X_train, y_train 为训练数据集log_reg.fit(X_train, y_train)# X_test,y_test 为测试数据集decision_scores = log_reg.decision_function(X_test)y_log_predict_threshold = np.array(decision_scores >= 5, dtype='int')。

如此可以得到不同的 y_log_predict_threshold,进而得到不同的精准率和召回率。

以手写数字识别数据为例,将标记为9的数据分类为1,其余分类为0:

from sklearn import datasetsdigits = datasets.load_digits()X = digits.datay = digits.target.copy()y[digits.target==9] = 1y[digits.target!=9] = 0from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=500)。

接着训练逻辑回归模型:

from sklearn.linear_model import LogisticRegressionlog_reg = LogisticRegression()log_reg.fit(X_train, y_train)。

获取测试数据集 X_test 对应的 取值:

decision_scores = log_reg.decision_function(X_test)。

在 decision_scores 的取值区间划分为一系列值 thresholds ,并将其中的值依次作为决策边界,进而得到不同的精确率和召回率。

from sklearn.metrics import precision_scorefrom sklearn.metrics import recall_scoreprecisions = []recalls = []thresholds = np.arange(np.min(decision_scores), np.max(decision_scores), 0.1)for threshold in thresholds: y_predict = np.array(decision_scores >= threshold, dtype='int') precisions.append(precision_score(y_test, y_predict)) recalls.append(recall_score(y_test, y_predict))。

将精确率、召回率与决策边界的关系绘制如图:

精确度与召回率的关系,即 Precision-Recall 曲线则为:

from sklearn.metrics import precision_recall_curveprecisions, recalls, thresholds = precision_recall_curve(y_test, decision_scores)。

Precision-Recall 曲线越靠外(即面积越大)则表示模型越好。

三 ROC曲线

ROC曲线用来比较两个模型的好坏,面积越大越好。ROC即:Receiver Operation Characteristic Curve,定义的是TPR和FPR之间的关系。 TPR = TP/(TP+FN) :即召回率 FPR = FP/(TN+FP): 即反例预测为正例的比率。

def TPR(y_true, y_predict): tp = TP(y_true, y_predict) fn = FN(y_true, y_predict) try: return tp / (tp + fn) except: return 0.0def FPR(y_true, y_predict): fp = FP(y_true, y_predict) tn = TN(y_true, y_predict) try: return fp / (fp + tn) except: return 0.0。

如果横坐标为False Positive Rate(FPR假正率),纵坐标为True Positive Rate(TPR真正率)。

sklearn.metrics.roc_curvefpr, tpr, thresholds=sklearn.metrics.roc_curve(y_true,y_score,pos_label=None,sample_weight=None,drop_intermediate=True)。

画多个模型的ROC曲线,越靠近左上面的模型效果越好。

参考: 重点理解: https://www.cnblogs.com/zongfa/p/9431807.html https://blog.csdn.net/hfutdog/article/details/88085878 https://segmentfault.com/a/1190000017364314。