模型评估方法(分类、回归)

分类问题、排序问题、回归问题 需要使用不同的指标进行评估。

每个评估指标都有其价值,但如果从单一的评估指标出发去评估模型,往往会得到片面甚至错误的结论。只有通过一组【互补】的指标去评估模型,才能更好地发现并解决模型存在的问题,从而更好地解决实际业务场景中遇到的问题。

不过即使评估指标选择对了,仍会存在模型过拟合或欠拟合、测试集和训练集划分不合理、线下评估和线上测试的样本分布存在差异等一系列问题。

一、分类模型评估

混淆矩阵、准确率 accuracy、精确率 precision、召回率 recall、F1值
P-R曲线、ROC曲线、AUC值
KS曲线(KS值)

混淆矩阵

from sklearn.metrics import confusion_matrix
y_pred = [0,1,0,1]
y_true = [0,1,1,0]
confusion_matrix(y_true, y_pred)
  • 可以通过prettytable来美化输出的混淆矩阵
import prettytable


def beautify_confusion_matrix(y_test, y_pre):
    '''
    美化打印出混淆矩阵,输入为y的实际值和预测值
    '''
    tn,fp,fn,tp=confusion_matrix(y_test,y_pre).ravel()
    confusion_matrix_table=prettytable.PrettyTable(['','prediction-0','prediction-1'])#创建表格
    confusion_matrix_table.add_row(['actual-0',tn,fp])
    confusion_matrix_table.add_row(['actual-1',fn,tp])
    print("confusion_matrix \n",confusion_matrix_table)


def beautify_confusion_matrix2(y_test, x_test, model):
    '''
    美化打印出混淆矩阵,输入为y的实际值、x的实际值 和 模型
    '''
    y_pre = model.predict(x_test)
    beautify_confusion_matrix(y_test, y_pre)
  • 自定义生成美化的表格
def plot_confusion_matrix(cm,classes,title='Confusion Matrix',cmap=plt.cm.Blues):
    '''
    绘制混淆矩阵(可视化)
    '''
    plt.imshow(cm,interpolation='nearest',cmap=cmap)
    plt.title(title,fontsize=22)
    plt.colorbar()
    tick_marks=np.arange(len(classes))
    plt.xticks(tick_marks,classes,rotation=0,fontsize=12)
    plt.yticks(tick_marks,classes,fontsize=12)

    thresh=cm.max()/2
    for i,j in itertools.product(range(cm.shape[0]),range(cm.shape[1])):
        plt.text(j,i,cm[i,j],
                horizontalalignment='center',
                fontsize=15,
                color='white' if cm[i,j]>thresh else 'black')

    plt.tight_layout()
    plt.ylabel("True label",fontsize=15)
    plt.xlabel('Predicted label',fontsize=15)


# 调用方式
from sklearn.metrics import confusion_matrix
con_matrix = confusion_matrix(y_test,y_pre)  #先生成混淆矩阵
f,ax=plt.subplots(figsize=(8,6))
plot_confusion_matrix(con_matrix,classes=[0,1],title='Confusion Matrix')  #混淆矩阵绘图

准确率、精确率、召回率、F1值

F1是准确率precision和召回率recall的调和平均数

F 1 = 2 ∗ p r e c i s i o n ∗ r e c a l l p r e c i s i o n + r e c a l l F1 = \frac{2*precision*recall}{precision+recall} F1=precision+recall2precisionrecall

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

print('accuracy_score:', accuracy_score(y_true, y_pred),\
      'precision_score:', precision_score(y_true, y_pred),\
      'recall_score:', recall_score(y_true, y_pred), \
      'f1_score:', f1_score(y_true, y_pred))


# 准确率 accuracy 也可以用逻辑回归模型对象的score方法来获取(注意:lr.score方法 与 f1_score函数 参数是不同的)
print('score方法计算正确率:', lr.score(X_true, y_true))  # lr.score(X_test, y_test))
  • 也可以使用 classification_report函数 来查看模型的分类统计信息, 该方法会返回字符串类型, 给出相关的分类指标评估量
from sklearn.metrics import classification_report
print(classification_report(y_true = y_test, y_pred = y_pred))

P-R曲线

P-R曲线的横轴是召回率Recall,纵轴是精确率Precision
P-R曲线的每个点表示:在某一阈值下,模型将大于该阈值的结果判定为正样本,小于该阈值的结果判定为负样本,返回此结果对应的召回率和精准率。

(整条P-R曲线是通过将阈值【从高到低】移动而生成的,原点附近表示当阈值最大时模型的精准率和召回率)

  • P-R曲线样例
    在这里插入图片描述

  • 代码

y_pred = [0,1,1,0,1,1,0,1,1,1]
y_true = [0,1,1,0,1,0,1,1,0,1]

import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve

precision, recall, thresholds = precision_recall_curve(y_true, y_pred)
plt.plot(precision, recall)

ROC曲线和AUC值

ROC曲线的横坐标为FPR,纵坐标为TPR

F P R = F P / N FPR = FP/N FPR=FP/N
T P R = T P / P TPR = TP/P TPR=TP/P

在二值分类问题中,模型的输出一般都是预测样本为正例的概率

  • ROC曲线的生成

通过动态地调整截断点,从最高的得分开始(对应ROC曲线的零点),逐渐调整至最低得分,每一个截断点都会对应一个FPR和TPR,在ROC图上绘制出每个截断点对应的位置。

注意:当正负样本的分布发生变化时,ROC曲线的形状能够基本保持不变,而P-R曲线的形状一般会发生较剧烈的变化。这个特点让ROC曲线能够尽量降低不同测试集带来的干扰,更加客观地衡量模型的性能。

  • ROC曲线的优势

ROC曲线能够尽量降低不同测试集带来的干扰,更加客观地衡量模型本身的性能。

在实际问题中,正负样本数量本身往往很不均衡。若选择不同的测试集,P-R曲线的变化很大,而ROC曲线则能够更加稳定地反映模型本身的好坏

所以,ROC曲线的适应场景更多,被广泛用于排序、推荐、广告等领域。

  • ROC曲线样例在这里插入图片描述

  • ROC曲线 代码

y_pred = [0,1,1,0,1,1,0,1,1,1]
y_true = [0,1,1,0,1,0,1,1,0,1]

import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve

FPR, TPR, thresholds = roc_curve(y_true, y_pred, pos_label=1)  # pos_label指定是正例的标签
print(f'fpr: {FPR}')
print(f'tpr: {TPR}')
print(f'thresholds: {thresholds}')

plt.title('ROC曲线')
plt.plot(FPR, TPR, 'b'); plt.plot([0,1], [0,1], 'r--')
plt.ylabel('TPR'); plt.xlabel('FPR')
  • AUC值 (Aera Under Curve)

AUC为ROC曲线下的面积,能够量化反映基于ROC曲线衡量出的模型性能。

计算AUC的值只需要沿着ROC横轴做积分即可。

由于ROC曲线一般都位于y=x这条直线的上方(如果不是的话,就把模型预测的概率反转成1-p 就可以得到一个更好的分类器),所以AUC的取值一般在0.5~1之间

AUC越大,说明分类器越可能把真正的正样本排在前面,分类性能越好

from sklearn.metrics import roc_auc_score
print('AUC score:', roc_auc_score(y_true, y_pred))

# 注意:auc 和 roc_auc_score 都可以返回AUC面积值,但是两个函数的参数是不同的
print('AUC面积值: ', auc(FPR, TPR))
print('AUC面积得分: ', roc_auc_score(y_true=y_true, y_score=y_pred))
  • 用鸢尾花数据集做个例子
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

iris = load_iris()
X, y = iris.data, iris.target
X = X[y!=0, 2:]   # 目的是 只保留两个类别, 简化成二分类问题
y = y[y!=0]
y[y==1] = 0
y[y==2] = 1  # 将我们感兴趣的类别(少量的类别) 构建成1

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 2)
lr = LogisticRegression()
lr.fit(X_train, y_train)

# 使用概率 作为每个样本数据的分值
probo = lr.predict_proba(X_test)
fpr, tpr, thresholds = roc_curve(y_true = y_test, y_score = probo[:, 1], pos_label=1)

# display(probo[:, 1])
# display(thresholds)

# 绘制ROC曲线
plt.figure(figsize=(10,6))
plt.plot(fpr, tpr, marker='o', label='ROC曲线')
plt.plot([0, 1], [0, 1], lw=2, ls = '--', label='随机猜测')
plt.plot([0, 0, 1], [0, 1, 1], lw = 2, ls = '-.', label='完美预测')
# 一些设置项
plt.xlim(-0.01, 1.02) # 设置x轴的最大和最小值
plt.ylim(-0.01, 1.02) # 设置y轴的最大和最小值
plt.xticks(np.arange(0, 1.1, 0.1))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.xlabel('False Positive Rate(FPR)', fontsize=16)
plt.ylabel('True Positive Rate(TPR)', fontsize=16)
plt.grid()
plt.title(f'ROC曲线-AUC值为{auc(fpr, tpr):.3f}', fontsize=16)
plt.legend()

KS值

KS曲线和ROC曲线的不同在于:ROC曲线是以FPR和TPR作为横纵坐标。KS曲线使用阈值(threshold)作为横坐标,分别画出FPR和TPR的曲线。(取两者之间距离最大处为最佳位置)

  • 在实际操作中往往使用ROC曲线配合求出KS值
from sklearn.metrics import roc_curve
FPR, TPR, thresholds = roc_curve(y_true, y_pred)
KS = abs(FPR-TPR).max()
print('KS值:', KS)

二、回归模型评估(待更新)

MAE, MSE, RMSE
R^2

MAE

M A E = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ MAE=\frac{1}{n}\sum_{i=1}^n|y_i-\hat y_i| MAE=n1i=1nyiy^i

from sklearn.metrics import mean_absolute_error

MSE

M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 MSE=\frac{1}{n}\sum_{i=1}^n(y_i-\hat y_i)^2 MSE=n1i=1n(yiy^i)2

from sklearn.metrics import mean_squred_error

RMSE

R M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 RMSE=\sqrt{\frac{1}{n}\sum_{i=1}^n(y_i-\hat y_i)^2} RMSE=n1i=1n(yiy^i)2

  • RMSE的局限
    一般情况下,RMSE能够很好地反映模型预测值与真实值的偏离程度。但在实际问题中,如果存在个别偏差程度非常大的离群点(outlier)时,即使离群点数量非常少,也会让RMSE指标变得很差。
    如果模型在95%的时间区间内的预测误差都小于1%,这说明,在大部分时间区间内,模型的预测效果都是非常优秀的。然而,RMSE却很差,这可能是由于在其他5%的时间区间内存在非常严重的离群点。
    (比如在流量问题中,噪声点是很容易产生的。)

  • 解决方式

  1. 如果认定这些点是噪声点的话,就需要在数据预处理阶段把这些噪声点过滤掉
  2. 如果不认为这些离群点是噪声点的话,就需要进一步提高模型的预测能力,将利群点产生的机制建模进去(这是个宏大的课题)
  3. 可以找一个更合适的指标来评估该模型。存在比RMSE的鲁棒性更好的指标,比如平方绝对百分比误差(MAPE, Mean Absolute Percent Error)
    相比于RMSE,MAPE相当于把每个点的误差进行了归一化,从而降低个别离群点带来的绝对误差的影响
    M A P E = ∑ i = 1 n ∣ y i − y ^ i y i ∣ ∗ 100 n MAPE={\sum_{i=1}^n|\frac{y_i-\hat y_i}{y_i}|*\frac{100}{n}} MAPE=i=1nyiyiy^in100

决定系数( R 2 R^2 R2

决定系数 是通过数据的变化来表征一个拟合的好坏。

理论上取值范围为(-无穷,1],正常取值范围为[0, 1]
如果结果是0,说明我们的模型跟瞎猜差不多。如果结果是1,说明模型无错误。

  • 决定系数公式

R 2 = 1 − M S E V a r i a n c e = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ‾ i ) 2 R^2=1-\frac{MSE}{Variance}=1-\frac{\sum_{i=1}^n(y_i-\hat y_i)^2}{\sum_{i=1}^n(y_i-\overline y_i)^2} R2=1VarianceMSE=1i=1n(yiyi)2i=1n(yiy^i)2

数学理解:分母为原始数据的离散程度,分子为预测数据和原始数据的误差,二者相除,可以消除原始数据离散程度的影响。

也可以写成:

R 2 = 模 型 解 释 的 离 差 平 方 和 总 离 差 平 方 和 = S S M S S T = ∑ i = 1 n ( y ^ i − y ‾ i ) 2 ∑ i = 1 n ( y i − y ‾ i ) 2 R^2=\frac{模型解释的离差平方和}{总离差平方和}=\frac{SS_M}{SS_T}=\frac{\sum_{i=1}^n(\hat y_i-\overline y_i)^2}{\sum_{i=1}^n(y_i-\overline y_i)^2} R2==SSTSSM=i=1n(yiyi)2i=1n(y^iyi)2

  • 关于模型解释部分和未解释部分的说明
    在这里插入图片描述

  • 代码

from sklearn.metrics import r2_score
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error 
from sklearn.metrics import r2_score
 
mean_absolute_error(y_test,y_predict)
mean_squared_error(y_test,y_predict)
r2_score(y_test,y_predict)

校正决定系数( R 2 a d j u s t e d R^2adjusted R2adjusted

消除样本数量和特征数量的影响。

R 2 a d j u s t e d = 1 − ( 1 − R 2 ) ( n − 1 ) n − p − 1 R^2 adjusted=1-\frac{(1-R^2)(n-1)}{n-p-1} R2adjusted=1np1(1R2)(n1)

(n为样本数量,p为特征数量)

三、聚类模型评估(待补充)

轮廓系数

平均轮廓系数(silhouette_score) – 一般轮廓系数>0.5,认为是还可以的模型

calinski和harabaz得分

四、交叉验证

交叉验证的基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set)。首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。

无论分类还是回归模型,都可以利用交叉验证,进行模型评估

from sklearn.cross_validation import cross_val_score
print(cross_val_score(knn, X_train, y_train, cv=4))
print(cross_cal_score(lr, X, y, cv=2))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值