分类模型评价方法

2783 字 · 654 阅读 · 2023 年 05 月 09 日

本文已更新,你可以访问 AI By Doing 以获得更好的阅读体验。
本篇文章需 特别授权许可,内容版权归作者所有,未经授权,禁止转载。

介绍

前面的分类文章中,我们使用了准确率这一种方法对模型进行评价。实际上,分类模型的评价方法还有很多,本次试验将会了解其它常用方法以便于对分类模型评价有更全面的掌握。

知识点

  • 准确率
  • 查准率
  • 召回率
  • F1 值
  • ROC 曲线

分类模型的评价方法前面的文章中仅介绍了准确率这一种,那么接下来我们将全面了解分类模型常用的评价指标。为了更好地理解,这里将使用逻辑回归来建立信用卡持卡人风险分类预测模型。

数据集介绍

数据集为 CSV 文件,可以使用 Pandas 读取数据集并预览。

import pandas as pd

df = pd.read_csv(
    "http://labfile.oss.aliyuncs.com/courses/1109/credit_risk_train.csv")  # 读取数据文件
df.head()

该数据集包含 10 列特征,以及一列类别标签。其中:

  • 第 1 ~ 6 列为客户近期历史账单信息。(特征)
  • 第 7 列为该客户年龄。(特征)
  • 第 8 列为该客户性别。(特征)
  • 第 9 列为该客户教育程度。(特征)
  • 第 10 列为该客户婚姻状况。(特征)
  • 第 11 列为客户持卡风险状况。(分类标签:LOW, HIGH)

我们的目的,是利用该数据集训练一个信用卡持卡人风险预测模型,并对模型进行评价。首先,按照机器学习建模的流程,需要将数据集划分为训练集和测试集。

虽然上面的数据集看起来已经非常整洁,但是你会发现第 7,8,9 列的特征数据为类别型(Female / Male)。所以,这里我们在划分数据集的同时,会使用数据预处理中介绍过的独热编码将类别型特征转换为数值型特征。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import scale

df.RISK = df.RISK.replace({"LOW": 0, "HIGH": 1})  # 将分类标签替换为数值,方便后面计算

train_data = df.iloc[:, :-1]  # 特征数据列
train_data = pd.get_dummies(train_data)  # 对特征数据进行独热编码
train_data = scale(train_data)  # 规范化处理

train_target = df['RISK']  # 目标数据列

# 划分数据集,训练集占 70%,测试集占 30%
X_train, X_test, y_train, y_test = train_test_split(
    train_data, train_target, test_size=0.3, random_state=0)

X_train.shape, X_test.shape, y_train.shape, y_test.shape

接下来,我们使用 scikit-learn 建立逻辑回归分类模型。使用训练数据完成模型训练,并使用测试数据对模型进行评价。使用 scikit-learn 训练模型的过程非常简单,实例化相应模型的类之后,使用 fit() 即可完成训练。

from sklearn.linear_model import LogisticRegression

model = LogisticRegression(solver='lbfgs')  # 定义逻辑回归模型
model.fit(X_train, y_train)  # 使用训练数据完成模型训练

对于分类模型而言,我们一般会使用准确率来对模型进行评价。详细来讲,通过已经训练好的模型在测试集上进行预测,从而计算出预测的准确率。

准确率 Accuracy

信用卡风险预测模型中,目标值对应了两个类别,常被称之为二分类问题。在二分类问题中,我们常常会定义正类和负类,例如这里我们定 HIGH 为 正类,LOW 为负类(你也可以反向定义)。那么,下面就可以给出实际类别(行名)和预测类别(列名)的混淆矩阵。

信用风险 HIGH LOW
HIGH True Positive (TP) False Negative (FN)
LOW False Positive (FP) True Negative (TN)

上表详细来讲:

  • TP:将正类预测为正类数 → 预测正确
  • TN:将负类预测为负类数 → 预测正确
  • FP:将负类预测为正类数 → 预测错误
  • FN:将正类预测为负类数 → 预测遗漏

根据该混淆矩阵,我们就可以给出分类模型的常用评价指标的计算方式了。

准确率及正确分类的测试样本个数占测试实例总样本个数的比例。那么,准确率(准确度)计算公式就为:

$$ Accuracy = \frac{TP+TN}{TP+TN+FP+FN} \tag{1}$$

当然,为了下面实现方便我们也可以将分类准确率写成下面的形式:

$$ acc=\frac{\sum_{i=1}^{N}I(\bar{y_{i}}=y_{i})}{N} \tag{2}$$

式中,$N$ 表示数据总条数,$\bar{y_{i}}$ 表示第 $i$ 条数据的种类预测值,$y_{i}$ 表示第 $i$ 条数据的种类真实值,$I$ 同样是指示函数,表示 $\bar{y_{i}}$ 和 $y_{i}$ 相同的个数。

首先,我们需要得到模型的预测结果。这一步也非常简单,只需要使用 predict 方法即可。

y_pred = model.predict(X_test)  # 输入测试集特征数据得到预测结果
y_pred
import numpy as np

def get_accuracy(test_labels, pred_lables):
    # 准确率计算公式,根据公式 2 实现
    correct = np.sum(test_labels == pred_lables)  # 计算预测正确的数据个数
    n = len(test_labels)  # 总测试集数据个数
    acc = correct/n
    return acc

现在,只需要输入真实标签 y_test 和模型预测标签 y_pred 即可。

get_accuracy(y_test, y_pred)  # 计算模型预测准确率

你也可以直接使用准确率的 scikit-learn 计算方法:sklearn.metrics.accuracy_score(y_true, y_pred)

from sklearn.metrics import accuracy_score

accuracy_score(y_test, y_pred)  # 传入真实类别和预测类别

实际上,scikit-learn 建模时也可以直接使用 model.score() 求得分类准确率:

model.score(X_test, y_test)  # 传入测试数据特征和类别

上面,我们就说完了常用的 3 种分类准确率计算方法。分类模型作为机器学习中最常遇到的建模问题,除了使用「准确率」对模型进行评价,实际上还有另外几种常用的性能评价指标,在此一并介绍。

查准率 Precision

查准率又称精确率,即正确分类的正例个数占分类为正例的实例个数的比例。

$$ Precision = \frac{TP}{TP+FP} \tag{3}$$

查准率的 scikit-learn 计算方法:sklearn.metrics.precision_score(y_true, y_pred)

from sklearn.metrics import precision_score

precision_score(y_test, y_pred)

召回率 Recall

召回率又称查全率,即正确分类的正例个数占实际正例个数的比例。

$$ Recall = \frac{TP}{TP+FN} \tag{4}$$

召回率的 scikit-learn 计算方法:sklearn.metrics.recall_score(y_true, y_pred)

from sklearn.metrics import recall_score

recall_score(y_test, y_pred)

F1 值

F1 值是查准率和召回率的加权平均数

$$ F1 = \frac{2*(Precision * Recall)}{Precision + Recall} \tag{5}$$

F1 相当于精确率和召回率的综合评价指标,对衡量数据更有利,也比较常用。

F1 值的 scikit-learn 计算方法:sklearn.metrics.f1_score(y_true, y_pred)

from sklearn.metrics import f1_score

f1_score(y_test, y_pred)

ROC 曲线

部分分类模型中(如:逻辑回归),通常会设定一个阈值,并规定大于该阈值为正类,小于则为负类。所以,当我们减小阀值时,将会有更多的样本被划分到正类。这样会提高正类的识别率,但同时也会使得更多的负类被错误识别为正类。

所以,ROC 曲线的目的在用形象化该变化过程,从而评价一个分类器好坏。

ROC 曲线中有两个指标,分别是 TPR 和 FPR,公式如下:

$$ TPR = \frac{TP}{TP+FN} \tag{6a}$$
$$ FPR = \frac{FP}{FP+TN} \tag{6b}$$

其中,TPR 代表能将正例分对的概率(召回率),而 FPR 则代表将负例错分为正例的概率。

ROC 曲线中,我们将横轴定为 FPR,纵轴定为 TPR,从而可以直观看出 FPR 与 TPR 之间的关系。

那么:

  • 当 FPR=0,TPR=0 时,意味着将每一个实例都预测为负例。
  • 当 FPR=1,TPR=1 时,意味着将每一个实例都预测为正例。
  • 当 FPR=0,TPR=1 时,意味着为最优分类器点。

那么,一个优秀分类器对应的 ROC 曲线应该尽量靠近左上角。当曲线越接近于 45 度对角线,则分类器效果越差。

ROC 曲线的 scikit-learn 计算方法:sklearn.metrics.roc_curve(y_true, y_score)

虽然使用 ROC 曲线来表示分类器好坏很直观,但人们往往更喜欢使用数值来评价分类器,此时就提出了 AUC 的概念。AUC 的全称为 Area Under Curve,意思是曲线下面积,即 ROC 曲线下面积。

  • $AUC=1$:完美分类器。
  • $0.5<AUC<1$:分类器优于随机猜测。
  • $AUC=0.5$:分类器和随机猜测的结果接近。
  • $AUC<0.5$:分类器比随机猜测的结果还差。

AUC 的 scikit-learn 计算方法:sklearn.metrics.auc(fpr, tpr)

下面,我们就绘制出本次预测结果的 ROC 曲线:

from matplotlib import pyplot as plt
%matplotlib inline

from sklearn.metrics import roc_curve
from sklearn.metrics import auc

y_score = model.decision_function(X_test)
fpr, tpr, _ = roc_curve(y_test, y_score)
roc_auc = auc(fpr, tpr)

plt.plot(fpr, tpr, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()

小结

这篇文章介绍了分类预测后常用的几个评价指标,它们分别是:准确率,查准率,召回率,F1 值,ROC 曲线。对于这几种方法,接下来要多做练习并熟练掌握。


系列文章

本篇文章需 特别授权许可,内容版权归作者所有,未经授权,禁止转载。