鹤啸九天 自律更自由,平凡不平庸 Less is More

机器学习模型评估方法-The-Evaluation-of-Machine Learning

Notes(温馨提示):

  1. ★ 首次阅读建议浏览:导航指南
  2. 右上角工具条搜索文章,右下角二维码关注微信公众号(鹤啸九天),底栏分享、赞赏、评论
  3. ★ 转载请注明文章来源,知识点积累起来不容易,水滴石穿,绳锯木断,谢谢理解
  4. ★ 如有疑问,邮件讨论,欢迎贡献优质资料


总结

回归MSE/分类CE?

回归、分类的损失函数:

  • 回归问题常用mse作为损失函数,隐含的预设是数据误差符合高斯分布
  • 分类问题常用交叉熵则是以数据分布服从多项式分布为前提。离散数据

回归问题能用交叉熵吗

  • 可以,虽然交叉熵用在回归问题看起来有些越俎代庖,「狗拿耗子多管闲事」,但「黑猫白猫能捉老鼠就是好猫」,搞清楚数据特点、使用场景,loss选择就能更贴合实际,最终的效果才是硬道理。

本质上回归应该用什么样的损失函数取决于数据分布。损失函数的选择本身也是一种先验偏好,选择mse意味着认为数据误差符合高斯分布,选择交叉熵则表示你倾向于认为数据接近多项式分布。如果你的先验直觉比较准确,符合实际情况,那模型效果应该会更好一些。 多项式分布一般和离散数据相关,但如果连续数据分桶后接近多项式分布,那选用mse可能就不合时宜了。

本质上,损失函数的选择是取决于对数据分布假设,不同的loss形式隐式地有对数据分布的要求,需要仔细分析数据特点进行判断。至于为什么A分布对应甲损失函数,B分布却对应乙损失函数,这也是一个值得展开的话题,简单来说这是最大熵原理约束下的选择。如对于高斯噪音分布,选择mse是满足最大熵要求的,它没有在高斯分布的假设之外增加额外的先验偏好。

知乎

【2022-8-20】为什么回归问题用 MSE?

  • 解答1:回归时,数据的残差有正有负,取平方求和后可以很简单的衡量模型的好坏。同时因为平方后容易求导数,比取绝对值还要分情况讨论好用 —— 经验主导,没有指出本质
  • 解答2:MSE对于偏差比较大的数据惩罚得比较多,但是会被outlier影响,同时MSE的优化目标是平均值,而MAE的优化目标是中位数。即如果我们的数据集足够大,对于同一个x会有多个y,MSE的目标是尽可能让预测值接近这些y的平均值。同时在做gradient descent的时候,MSE的梯度可以在越接近最小值的地方越平缓,这样不容易步子扯大了。而MAE的梯度一直不变,得手动调整learning rate。
  • 解答3:根据中心极限定理,误差服从正态分布,此时使得样本似然函数最大等价于使得MSE最小——Ian的《Deep Learning》

常见业务指标

渗透率与覆盖率

拿QQ音乐举例覆盖率:

  • 覆盖率:使用QQ音乐的用户/线上音乐户规模
    • 这里用户包括了vip用户和普通用户,也就是说覆盖率和用户是否消费无关,和使用该产品的用户数量多少相关
  • 渗透率:qq音乐的销售额/用户在音乐领域消费的总规模
    • 通俗来说就是,你赚到的钱占这个行业的赚到的钱的多少

作者:西瓜真甜啊

【2022-2-11】滴滴渗透率指什么?

滴滴订单数3800万,是美国的五倍,但是渗透率只有1%,怎么算渗透率?

  • 我们今天还只看城镇人口,中国城镇人口有8亿人口,每个人一天出门一次到两次,所以8亿人每天出行大概是13亿次左右,大概是11-13亿次左右这么一个数量,我们今天提供1400万次的出行除以13亿次,这个渗透率是1%,这个是我们目前看到的市场空间。而旧金山这个数据是多少呢?是15%,也就是说我们的市场空间是巨大的。

柳青在这一情景下说的渗透率是指“市场渗透率”,表示的是一种产品或服务在市场上的覆盖程度。

用百分数表示的,公式如下:

  • 市场渗透率 = 商品的现有需求量 / 商品的潜在需求量

而滴滴得出1%的算法是:中国城镇人口有8亿人口,每个人一天出门一次到两次,所以8亿人每天出行大概是13亿次左右,大概是在11-13亿次左右,用滴滴现在提供的1400万次出行除以13亿次,这个渗透率是1%,也是滴滴目前看到的市场空间。

分类

  • 参考:深入理解AUC
  • 在机器学习的评估指标中,AUC是一个最常见也是最常用的指标之一。
  • AUC本身的定义是基于几何的,但是其意义十分重要,应用十分广泛。

介绍

混淆矩阵:

pred_label/true_label Positive Negative
Positive TP FP
Negtive FN TN

如上表所示,行表示预测的label值,列表示真实label值。

TP,FP,FN,TN分别表示如下意思:

  • TP(true positive):表示样本的真实类别为正,最后预测得到的结果也为正;
  • FP(false positive):表示样本的真实类别为负,最后预测得到的结果却为正;
  • FN(false negative):表示样本的真实类别为正,最后预测得到的结果却为负;
  • TN(true negative):表示样本的真实类别为负,最后预测得到的结果也为负. 根据以上几个指标,可以分别计算出Accuracy、Precision、Recall(Sensitivity,SN),Specificity(SP), img
  • Accuracy:表示预测结果的精确度,预测正确的样本数除以总样本数。
    • $Accuracy=(TP+TN)/(TP+FP+FN+TN)$
  • Precision,准确率,表示预测结果中,预测为正样本的样本中,正确预测为正样本的概率;
    • $Precision=TP/(TP+FP)$
  • Recall,召回率,表示在原始样本的正样本中,最后被正确预测为正样本的概率;
    • $Recall=TP/(TP+FN)$
  • Specificity,常常称作特异性,它研究的样本集是原始样本中的负样本,表示的是在这些负样本中最后被正确预测为负样本的概率。

实际中,往往希望得到的precision和recall都比较高,比如当FN和FP等于0的时候,他们的值都等于1。但是,它们往往在某种情况下是互斥的,比如这种情况,50个正样本,50个负样本,结果全部预测为正,那么它的precision为1而recall却为0.5.所以需要一种折衷的方式,因此就有了F1-score。

  • F1-score表示的是precision和recall的调和平均评估指标
  • 类似的还有MCC

一张图总结:img

img

总结

  • auc只能用于binary classifier 评价
  • 分类器只需要计算出预测概率分数,不需要自己设置threshold。 一个threshold会算出一个点,一般会自动尝试所有threshold,最后形成一个曲线。以下就不考虑threshold。
  • Auc变化其实等价于左上角的面积(绿色部分)变化。 这个面积和两类数据的概率分布的重叠面积成正比 (容易分错类的部分)。 根各数据分布的重叠部分成正比。(这个数据不一定是原始数据,而是通过特征工程和模型高纬投影后的,各类数据分布)好的分类器,把两类分的很开,概率分布重叠小,左上面积小,auc大。最坏的情况是随机,概率分布完全重叠,auc是直线。

PR曲线

P-R曲线中,P为中precision,即精准度,R为图中recall,即召回率。

AP的计算,此处参考的是PASCAL  VOC  CHALLENGE的2010年之前计算方法。首先设定一组阈值,[0, 0.1, 0.2, …, 1]。然后对于recall大于每一个阈值(比如recall>0.3),我们都会得到一个对应的最大precision。这样,我们就计算出了11个precision。AP即为这11个precision的平均值。这种方法英文叫做11-point interpolated average precision。​

AP/mAP

原文链接

【2023-4-11】目标检测中的“神奇指南”——平均精度(mAP)

AP值的计算需要一系列指标做铺垫,涉及的名词:

  • (1)IOU:IOU是一个比值,是预测框与实际框的相交部分与两者全部面积的比值;
  • (2)TP:被正确地划分为正例的个数,即实际为正例且被分类器划分为正例的实例数;
  • (3)FP:被错误地划分为正例的个数,即实际为负例但被分类器划分为正例的实例数;
  • (4)FN:被错误地划分为负例的个数,即实际为正例但被分类器划分为负例的实例数;
  • (5)TN:被正确地划分为负例的个数,即实际为负例且被分类器划分为负例的实例数。

IOU是预测边界框和参考边界框的交集和并集之间的比率,利用这个比值,可以知晓每个检测结果的正确性。

  • 将IOU与阈值进行比较,最常用的阈值是0.5,如果 IoU > 0.5,那么认为这是一个正确检测,否则认为这是一错误的检测。

mAP作为预测目标位置及类别类算法的性能度量指标,对评估目标定位模型、目标检测模型以及实例分割模型非常有用。

  • 计算出所有检测框的IOU值,求解其P与R,最终得出mAP值,利用这些平均精度值,便可以轻松地判断模型对任何给定类别的性能。

F 指标

Fbeta-measure 是一种可配置的单分指标,用于根据对正类的预测来评估二元分类模型

F1

P和R同等重要

F-Measure = ((1 + 1^2) * Precision * Recall) / (1^2 * Precision + Recall)
F-Measure = (2 * Precision * Recall) / (Precision + Recall)

代码计算方式

from sklearn.metrics import fbeta_score
from sklearn.metrics import f1_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score

# perfect precision, 50% recall
y_true = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
y_pred = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
p = precision_score(y_true, y_pred)
r = recall_score(y_true, y_pred)
f = fbeta_score(y_true, y_pred, beta=0.5)
print('Result: p=%.3f, r=%.3f, f=%.3f' % (p, r, f))

F_beta

Fbeta 是 F 的抽象,调和均值计算中的精度和召回率的平衡, 由beta系数控制。

Fbeta = ((1 + beta^2) * Precision * Recall) / (beta^2 * Precision + Recall)

beta 参数用于 Fbeta-measure。

  • beta=2, 称为 F2-measure 或 F2-score。
  • beta=1, 称为 F1-measure 或 F1-score

beta 参数的三个常见值:

  • F0.5-Measure (beta=0.5):精度上的权重更大,召回的权重更小。
  • F1-Measure (beta=1.0):平衡准确率和召回率的权重。
  • F2-Measure (beta=2.0):精度权重较小,召回权重较大
from sklearn.metrics import fbeta_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score

# perfect precision, 50% recall
y_true = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
y_pred = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
p = precision_score(y_true, y_pred)
r = recall_score(y_true, y_pred)
f = fbeta_score(y_true, y_pred, beta=1.0) # beta=1
f = fbeta_score(y_true, y_pred, beta=2.0) # beta=2
print('Result: p=%.3f, r=%.3f, f=%.3f' % (p, r, f))

AUC

多分类

  • 【2021-8-6】多分类模型Accuracy, Precision, Recall和F1-score的超级无敌深入探讨
  • 具体场景(如不均衡多分类)中到底应该以哪种指标为主要参考呢?
  • 多分类模型和二分类模型的评价指标有啥区别?
  • 多分类问题中
    • 为什么Accuracy = micro precision = micro recall = micro F1-score?
    • 什么时候用macro, weighted, micro precision/ recall/ F1-score?

Accuracy是分类问题中最常用的指标,它计算了分类正确的预测数与总预测数的比值。但是,对于不平衡数据集而言,Accuracy并不是一个好指标。如100张图片中91张图片是「狗」,5张是「猫」,4张是「猪」,训练一个三分类器,能正确识别图片里动物的类别。其中,狗这个类别就是大多数类 (majority class)。当大多数类中样本(狗)的数量远超过其他类别(猫、猪)时,如果采用Accuracy来评估分类器的好坏,即便模型性能很差 (如无论输入什么图片,都预测为「狗」),也可以得到较高的Accuracy Score(如91%)。此时,虽然Accuracy Score很高,但是意义不大。当数据异常不平衡时,Accuracy评估方法的缺陷尤为显著。因此需要引入Precision (精准度),Recall (召回率)和F1-score评估指标。考虑到二分类和多分类模型中,评估指标的计算方法略有不同

在多分类(大于两个类)问题中,假设我们要开发一个动物识别系统,来区分输入图片是猫,狗还是猪。给定分类器一堆动物图片,产生了如下结果混淆矩阵。

  • 混淆矩阵中,正确的分类样本(Actual label = Predicted label)分布在左上到右下的对角线上。其中,Accuracy的定义为分类正确(对角线上)的样本数与总样本数的比值。Accuracy度量的是全局样本预测情况。而对于Precision和Recall而言,每个类都需要单独计算其Precision和Recall。

如果想评估该识别系统的总体功能,必须考虑猫、狗、猪三个类别的综合预测性能。那么,到底要怎么综合这三个类别的Precision呢?是简单加起来做平均吗?通常来说, 我们有如下几种解决方案(也可参考scikit-learn官网

总结

How to avoid machine learning pitfalls: a guide for academic researchers

  • 不要对不平衡的数据集使用准确度(accuracy)指标。这个指标常用于分类模型,不平衡数据集应采用kappa系数马修斯相关系数(MCC)指标。

kappa系数

【2021-9-13】kappa系数简介

Kappa系数是一个用于一致性检验的指标,也可以用于衡量分类的效果。因为对于分类问题,所谓一致性就是模型预测结果和实际分类结果是否一致。kappa系数的计算是基于混淆矩阵的,取值为-1到1之间,通常大于0。可分为五组来表示不同级别的一致性:

  • 0.0~0.20 极低的一致性(slight)
  • 0.21~0.40 一般的一致性(fair)
  • 0.41~0.60 中等的一致性(moderate)
  • 0.61~0.80 高度的一致性(substantial)
  • 0.81~1 几乎完全一致(almost perfect)

基于混淆矩阵的kappa系数计算公式如下:

  • 其中,p0=对角线元素之和/矩阵所有元素之和,及acc,pe是所有类别分别对应的“实际与预测数量的乘积”之总和,除以“样本总数的平方”

对于不均衡数据集,acc失灵,所以用kappa系数,惩罚模型“偏向性”的指标来代替acc。而根据kappa的计算公式,越不平衡的混淆矩阵,pe越高,kappa值就越低,正好能够给“偏向性”强的模型打低分。

代码:

import numpy as np
 
# 计算混淆矩阵的kappa
def kappa(confusion_matrix):
    pe_rows = np.sum(confusion_matrix, axis=0)
    pe_cols = np.sum(confusion_matrix, axis=1)
    sum_total = sum(pe_cols)
    pe = np.dot(pe_rows, pe_cols) / float(sum_total ** 2)
    po = np.trace(confusion_matrix) / float(sum_total)
    return (po - pe) / (1 - pe)
# 无偏向的混淆矩阵
balance_matrix = np.array(
    [
        [2,  1,  1],
        [1,  2,  1],
        [1,  1,  2]
    ]
)
# 有偏向的混淆矩阵
unbalance_matrix = np.array(
    [
        [0,  0,  3],
        [0,  0,  3],
        [0,  0,  6]
    ]
)
kappa_balance = kappa(balance_matrix)
print("kappa for balance matrix: %s" % kappa_balance)

kappa_unbalance = kappa(unbalance_matrix)
print("kappa for unbalance matrix: %s" % kappa_unbalance)
kappa for balance matrix: 0.25
kappa for unbalance matrix: 0.0

# --------- sklearn ----------
#sklearn计算kappa
from sklearn.metrics import cohen_kappa_score
y_true = [2, 0, 2, 2, 0, 1]
y_pred = [0, 0, 2, 2, 0, 2]
kappa_value = cohen_kappa_score(y_true, y_pred)
print("kappa值为 %f" % kappa_value)
# kappa值为 0.428571
# --------- tensorflow ------------
# tensorflow计算kappa
import tensorflow as tf

y_t = tf.constant(y_true)
y_p = tf.constant(y_pred)
kappa, update = tf.contrib.metrics.cohen_kappa(y_t, y_p, 3)
with tf.Session() as sess:
    sess.run(tf.local_variables_initializer())
    print(kappa.eval(), update.eval())
    print(kappa.eval(), update.eval())

MCC系数

马修斯相关系数(MCC)是机器学习中衡量二分类的分类性能的指标。该指标考虑了真阳性、真阴性和假阳性和假阴性,通常认为该指标是一个比较均衡的指标,即使是在两类别的样本失衡时,也可以应用它。MCC本质上是一个描述实际分类与预测分类之间的相关系数,它的取值范围为

  • 1时表示对受试对象的完美预测
  • 0时表示预测的结果还不如随机预测的结果
  • -1是指预测分类和实际分类完全不一致

MCC介绍

代码:

import pandas as pd
from math import sqrt

def get_data():
    df = pd.read_csv('data.csv')
    TP = df.iloc[0]["zero"]
    FP = df.iloc[1]["zero"]
    FN = df.iloc[0]["one"]
    TN = df.iloc[1]["one"]
    return TP,FP,FN,TN

def calculate_data(TP,FP,FN,TN):
    numerator = (TP * TN) - (FP * FN) #马修斯相关系数公式分子部分
    denominator = sqrt((TP + FP) * (TP + FN) * (TN + FP) * (TN + FN)) #马修斯相关系数公式分母部分
    result = numerator/denominator
    return result

if __name__ == '__main__':
  # ----- 自定义 -------
  TP,FP,FN,TN = get_data()
  result = calculate_data(TP,FP,FN,TN)
  print(result) #打印出结果
  # ------- sklearn --------
  from sklearn.metrics import matthews_corrcoef
  y_true = [+1, +1, +1, -1]
  y_pred = [+1, -1, +1, +1]
  matthews_corrcoef(y_true, y_pred)

Macro-average方法

该方法最简单,直接将不同类别的评估指标(Precision/ Recall/ F1-score)加起来求平均,给所有类别相同权重。该方法能够平等看待每个类别,但是它的值会受稀有类别影响。

  • [公式]
  • [公式]

Weighted-average方法

该方法给不同类别不同权重(权重根据该类别的真实分布比例确定),每个类别乘权重后再进行相加。该方法考虑了类别不平衡情况,它的值更容易受到常见类(majority class)的影响。

  • [公式] (W代表权重,N代表样本在该类别下的真实数目)
  • [公式]
  • [公式]

Micro-average方法

该方法把每个类别的TP, FP, FN先相加之后,在根据二分类的公式进行计算。

  • [公式]
  • [公式]

其中,特别有意思的是,Micro-precision和Micro-recall竟然始终相同!这是为啥呢?

这是因为在某一类中的False Positive样本,一定是其他某类别的False Negative样本。听起来有点抽象?举个例子,比如说系统错把「狗」预测成「猫」,那么对于狗而言,其错误类型就是False Negative,对于猫而言,其错误类型就是False Positive。于此同时,Micro-precision和Micro-recall的数值都等于Accuracy,因为它们计算了对角线样本数和总样本数的比值,总结就是:

  • [公式]

代码

import numpy as np
import seaborn as sns
from sklearn.metrics import confusion_matrix
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score, average_precision_score,precision_score,f1_score,recall_score

# create confusion matrix
y_true = np.array([-1]*70 + [0]*160 + [1]*30)
y_pred = np.array([-1]*40 + [0]*20 + [1]*20 + 
                  [-1]*30 + [0]*80 + [1]*30 + 
                  [-1]*5 + [0]*15 + [1]*20)
cm = confusion_matrix(y_true, y_pred)
conf_matrix = pd.DataFrame(cm, index=['Cat','Dog','Pig'], columns=['Cat','Dog','Pig'])

# plot size setting
fig, ax = plt.subplots(figsize = (4.5,3.5))
sns.heatmap(conf_matrix, annot=True, annot_kws={"size": 19}, cmap="Blues")
plt.ylabel('True label', fontsize=18)
plt.xlabel('Predicted label', fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.savefig('confusion.pdf', bbox_inches='tight')
plt.show()

损失函数

简介

损失函数用来评价模型的预测值和真实值不一样的程度,损失函数越好,通常模型的性能越好。不同的模型用的损失函数一般也不一样。

损失函数分为经验风险损失函数和结构风险损失函数。

  • 经验风险损失函数指预测结果和实际结果的差别
  • 结构风险损失函数是指经验风险损失函数加上正则项。

【2021-10-13】机器学习初学者都应该知道的5类回归损失函数, 原文

  • 最小化的函数称为“损失函数”,损失函数衡量的是模型预测预期结果的能力,最常用的最小化损失函数的方法是“梯度下降法”,把损失函数想象成起伏的山脉,梯度下降法就像从山上滑下来到达最低点。
  • 没有一个损失函数适用于所有类型的数据,它取决于许多因素,包括异常值的存在,机器学习算法的选择,梯度下降法的时间效率和预测的置信度等。

函数总结

  • 损失函数大致可分为两类:分类损失和回归损失。回归函数预测数量,分类函数预测标签

常用的回归损失函数和分类损失函数

  • (1)回归:MAE/MSE/Huber loss(平滑MAE)/Log cosh loss/Quantile loss
  • (2)分类:Log loss/Focal loss/KL Divergence(或相对熵)/Exponential loss/Hinge loss

函数拟合

多项式函数拟合

多项式拟合: np.polyfit

import numpy as np
import matplotlib.pyplot as plt
x = [10,20,30,40,50,60,70,80]
x = np.array(x)
print('x is :\n',x)
num = [174,236,305,334,349,351,342,323]
y = np.array(num)
print('y is :\n',y)
# f1 为各项的系数,3 表示想要拟合的最高次项是多少。
f1 = np.polyfit(x, y, 3)
# p1 为拟合的多项式表达式
p1 = np.poly1d(f1)
print('p1 is :\n',p1)

plt.plot(x, y, 's',label='original values')
yvals = p1(x) #拟合y值
plt.plot(x, yvals, 'r',label='polyfit values')

自定义函数拟合: curve_fit

对于自定义函数拟合,不仅可以用于直线、二次曲线、三次曲线的拟合,它可以适用于任意形式的曲线的拟合,只要定义好合适的曲线方程即可

from scipy.optimize import curve_fit
x = [20,30,40,50,60,70]
x = np.array(x)
num = [453,482,503,508,498,479]
y = np.array(num)

# 这里的函数可以自定义任意形式。
def func(x, a, b,c):
    return a*np.sqrt(x)*(b*np.square(x)+c)

# popt返回的是给定模型的最优参数。我们可以使用pcov的值检测拟合的质量,其对角线元素值代表着每个参数的方差。
popt, pcov = curve_fit(func, x, y)
a = popt[0] 
b = popt[1]
c = popt[2]
yvals = func(x,a,b,c) #拟合y值
plot1 = plt.plot(x, y, 's',label='original values')
plot2 = plt.plot(x, yvals, 'r',label='polyfit values')

激活函数

【2022-8-20】常见的激活函数, 一文概览深度学习中的激活函数

  • 如果使用线性激活函数(恒等激励函数),那么,神经网络仅将输入线性组合再输出,在这种情况下,深层(多个隐藏层)神经网络与只有一个隐藏层的神经网络没有任何区别
  • 两层使用线性激活函数的神经网络,可以简化成单层的神经网络,对于多个隐藏层的神经网络同样如此。因此,想要使神经网络的多个隐藏层有意义,需要使用非线性激活函数,也就是说想要神经网络学习到有意思的东西只能使用非线性激活函数。
  • 需要一个非线性决策边界(non-linear decision boundary)来分离非线性数据集

总结

不是所有的函数都可以作为激活函数, 激活函数至少应该满足以下几点:

  • 可微性:因为优化方法是基于梯度的,这个性质是必须的
  • 单调性:当激活函数是单调的时候,能够保证单层网络是凸函数
  • 输出值的范围:激活函数的输出值的范围可以有限也可以无限。当输出值是有限的时候,基于梯度的优化方法会更加稳定,因为特征的表示受有限权值的影响更加显著;当输出值是无限的时候,模型的训练会更加高效,不过在这种情况下,一般需要更小的learning rate

从目前来看,常见的激活函数多是分段线性和具有指数形状的非线性函数

  • 线性激活函数:这是一种简单的线性函数,公式为:f(x) = x。基本上,输入到输出过程中不经过修改
  • 非线性激活函数:用于分离非线性可分的数据,是最常用的激活函数。非线性方程控制输入到输出的映射。非线性激活函数有 Sigmoid、Tanh、ReLU、LReLU、PReLU、Swish 等。

  • 所有激活函数的导数值都是严格或不严格的大于零——这意味着输入值越大,输出值越大;反之,输入值越小,输出值越小。
  • 参考:激活函数

sigmoid(logistic回归)

公式

  • $ y(x)=1/(1+exp^(1x)) $

sigmoid函数的值域为(0,1)

Sigmoid 三个主要缺陷:

  1. 梯度消失:注意:Sigmoid 函数趋近 0 和 1 的时候变化率会变得平坦,也就是说,Sigmoid 的梯度趋近于 0。神经网络使用 Sigmoid 激活函数进行反向传播时,输出接近 0 或 1 的神经元其梯度趋近于 0。这些神经元叫作饱和神经元。因此,这些神经元的权重不会更新。此外,与此类神经元相连的神经元的权重也更新得很慢。该问题叫作梯度消失。因此,想象一下,如果一个大型神经网络包含 Sigmoid 神经元,而其中很多个都处于饱和状态,那么该网络无法执行反向传播。
  2. 不以零为中心:Sigmoid 输出不以零为中心的。
  3. 计算成本高昂:exp() 函数与其他非线性激活函数相比,计算成本高昂。
#导入相关库
import matplotlib.pyplot as plt
import numpy as np 

#函数
g=lambda z:1/(1+np.exp(-x))

start=-10 #输入需要绘制的起始值(从左到右)
stop=10 #输入需要绘制的终点值
step=0.01#输入步长
num=(stop-start)/step #计算点的个数
x = np.linspace(start,stop,num)
y = g(x)

fig=plt.figure(1)
plt.plot(x, y,label='sigmoid')
plt.grid(True)#显示网格

plt.legend()#显示旁注#注意:不会显示后来再定义的旁注
plt.show(fig)

tanh

tanh函数是sigmoid函数向下平移和收缩后的结果

Tanh 激活函数又叫作双曲正切激活函数(hyperbolic tangent activation function)。

  • 与 Sigmoid 函数类似,Tanh 函数也使用真值,但 Tanh 函数将其压缩至-1 到 1 的区间内。
  • 与 Sigmoid 不同,Tanh 函数的输出以零为中心,因为区间在-1 到 1 之间。
  • 可以将 Tanh 函数想象成两个 Sigmoid 函数放在一起。Tanh 函数的使用优先性高于 Sigmoid 函数。负数输入被当作负值,零输入值的映射接近零,正数输入被当作正值。

唯一的缺点是:

  1. Tanh 函数也会有梯度消失的问题,因此在饱和时也会「杀死」梯度。

sigmoid和tanh激活函数有共同的缺点:

  • 在z很大或很小时,梯度几乎为零,因此使用梯度下降优化算法更新网络很慢。
import matplotlib.pyplot as plt
import numpy as np 

#函数
g=lambda z:(np.exp(z)-np.exp(-z))/(np.exp(z)+np.exp(-z))

start=-10 #输入需要绘制的起始值(从左到右)
stop=10 #输入需要绘制的终点值
step=0.01#输入步长
num=(stop-start)/step #计算点的个数
x = np.linspace(start,stop,num)
y = g(x)

fig=plt.figure(1)
plt.plot(x, y,label='tanh')
plt.grid(True)#显示网格

plt.legend()#显示旁注
plt.show(fig)

relu(修正线性单元)

为了解决梯度消失问题,另一个非线性激活函数——修正线性单元(rectified linear unit,ReLU),该函数明显优于前面两个函数,是现在使用最广泛的函数。

由于sigmoid和tanh的缺点,因此relu激活函数成为了大多数神经网络的默认选择。

当输入 x<0 时,输出为 0,当 x> 0 时,输出为 x。该激活函数使网络更快速地收敛。它不会饱和,即它可以对抗梯度消失问题,至少在正区域(x> 0 时)可以这样,因此神经元至少在一半区域中不会把所有零进行反向传播。由于使用了简单的阈值化(thresholding),ReLU 计算效率很高。

但是 ReLU 神经元也存在一些缺点:

  1. 不以零为中心:和 Sigmoid 激活函数类似,ReLU 函数的输出不以零为中心。
  2. 前向传导(forward pass)过程中,如果 x < 0,则神经元保持非激活状态,且在后向传导(backward pass)中「杀死」梯度。这样权重无法得到更新,网络无法学习。当 x = 0 时,该点的梯度未定义,但是这个问题在实现中得到了解决,通过采用左侧或右侧的梯度的方式。

但是relu也存在缺点:

  • 在$z$小于0时,斜率即导数为0,因此引申出下面的 leaky relu 函数,但是实际上leaky relu使用的并不多。
import matplotlib.pyplot as plt
import numpy as np 

#函数
g=lambda z:np.maximum(0,z)

start=-10 #输入需要绘制的起始值(从左到右)
stop=10 #输入需要绘制的终点值
step=0.01#输入步长
num=(stop-start)/step #计算点的个数
x = np.linspace(start,stop,num)
y = g(x)

fig=plt.figure(1)
plt.plot(x, y,label='relu')
plt.grid(True)#显示网格

plt.legend()#显示旁注
plt.show(fig)

Leaky relu

为了解决 ReLU 激活函数中的梯度消失问题,当 x < 0 时,使用 Leaky ReLU——该函数试图修复 dead ReLU 问题。

该函数试图缓解 dead ReLU 问题。

Leaky ReLU 的概念是:

  • 当 x < 0 时,它得到 0.1 的正梯度。
  • 该函数一定程度上缓解了 dead ReLU 问题,但是使用该函数的结果并不连贯。
  • 尽管它具备 ReLU 激活函数的所有特征,如计算高效、快速收敛、在正区域内不会饱和。

Leaky ReLU 可以得到更多扩展。不让 x 乘常数项,而是让 x 乘超参数,这看起来比 Leaky ReLU 效果要好。该扩展就是 Parametric ReLU。

import matplotlib.pyplot as plt
import numpy as np 

#函数
g=lambda z:np.maximum(0.01*z,z)

start=-100 #输入需要绘制的起始值(从左到右)
stop=50 #输入需要绘制的终点值
step=0.01#输入步长
num=(stop-start)/step #计算点的个数
x = np.linspace(start,stop,num)
y = g(x)

fig=plt.figure(1)
plt.plot(x, y,label='relu')
plt.grid(True)#显示网格

plt.legend()#显示旁注
plt.show(fig)

Parametric ReLU

引入了一个随机的超参数alpha,它可以被学习,因为可以对它进行反向传播。这使神经元能够选择负区域最好的梯度,有了这种能力,它们可以变成 ReLU 或 Leaky ReLU。

总之,最好使用 ReLU,但是可以使用 Leaky ReLU 或 Parametric ReLU 实验一下,看看它们是否更适合你的问题。

Softsign

Softsign是tanh激活函数的另一个替代选择,从图中可以看到它和tanh的曲线极其相似,不过相比于tanh,Sotsign的曲线更平坦,导数下降的更慢一点,这个特性使得它可以缓解梯度消失问题,可以更高效的学习。

不过,Sofsign的导数相比tanh计算要更麻烦一点

SoftPlus

SoftPlus可以作为ReLu的一个不错的替代选择,可以看到与ReLU不同的是,SoftPlus的导数是连续的、非零的、无处不在的,这一特性可以防止出现ReLU中的“神经元死亡”现象。

然而,SoftPlus是不对称的,不以0为中心,存在偏移现象;而且,由于其导数常常小于1,也可能会出现梯度消失的问题。

Maxout

Maxout出现在ICML2013上,作者Goodfellow将maxout和dropout结合后,号称在MNIST, CIFAR-10, CIFAR-100, SVHN这4个数据上都取得了start-of-art的识别率。

可以注意到,ReLU 和 Leaky-ReLU 都是它的一个变形。这个激活函数有点大一统的感觉,因为maxout网络能够近似任意连续函数,且当 为0时,退化为ReLU。Maxout能够缓解梯度消失,同时又规避了ReLU神经元死亡的缺点,但增加了参数和计算量。

Swish

该函数又叫作自门控激活函数,由谷歌的研究者发布. 根据论文,Swish 激活函数的性能优于 ReLU 函数。

在 x 轴的负区域曲线的形状与 ReLU 激活函数不同,因此,Swish 激活函数的输出可能下降,即使在输入值增大的情况下。大多数激活函数是单调的,即输入值增大的情况下,输出值不可能下降。而 Swish 函数为 0 时具备单侧有界(one-sided boundedness)的特性,它是平滑、非单调的。更改一行代码再来查看它的性能,似乎也挺有意思

0-1损失函数(zero-one loss)

0-1损失是指预测值和目标值不相等为1, 否则为0:

[公式]

特点:

  • (1)0-1损失函数直接对应分类判断错误的个数,但是它是一个非凸函数,不太适用.
  • (2)感知机就是用的这种损失函数。但是相等这个条件太过严格,因此可以放宽条件,即满足 [公式] 时认为相等,
    • [公式]

MAE 平均绝对值损失函数 (L1损失)

平均绝对误差(Mean Absolute Error,MAE),绝对偏差平均值即平均偏差,指各次测量值的绝对偏差绝对值的平均值。平均绝对误差可以避免误差相互抵消的问题,因而可以准确反映实际预测误差的大小。

解释:

  • 范围[0,+∞),和MSE、RMSE类似,当预测值和真实值的差距越小,则模型越好;相反则越差。

平均绝对误差(MAE)是用于回归模型的另一个损失函数,MAE是目标值和预测值之间绝对差的总和的平均值

绝对值损失函数是计算预测值与目标值的差的绝对值:

[公式]

MAPE 平均绝对百分比误差

平均绝对百分比误差(Mean Absolute Percentage Error,MAPE),平均绝对百分比误差之所以可以描述准确度是因为平均绝对百分比误差本身常用于衡量预测准确性的统计指标,如时间序列的预测。参考

计算公式:

  • mape
  • MAPE就是mae 多了个分母。

解释:

  • 和上面的MAE相比,在预测值和真实值的差值下面分母多了一项,除以真实值。
  • 范围[0,+∞),MAPE 为0%表示完美模型,MAPE 大于 100 %则表示劣质模型。

Mape

  • 好处:提供了一个便于比较的benchmark,即0值,当预测的y和真实的y完全相同的时候,Mape值最小为0,因此mape的结果约接近于0越好
  • 然而比较致命的缺点:当真实值yi很小的时候,一点点的误差,mape的计算结果就很大;

注意

  • 当真实值有数据等于0时,存在分母0除问题,该公式不可用!
# ------ 调用包 ----
from fbprophet.diagnostics import performance_metrics

df_p = performance_metrics(df_cv)
df_p.head()
# -------- 原生版 -----
def evalmape(preds, dtrain):
  gaps = dtrain.get_label()
  err = abs(gaps-preds)/gaps
  err[(gaps==0)] = 0
  err = np.mean(err)*100
  return 'error',err

SMAPE 对称平均绝对百分比误差

对称平均绝对百分比误差(Symmetric Mean Absolute Percentage Error,SMAPE)

  • smape

解释:

  • 与MAPE相比,加了对称,其实就是将分母变为了真实值和预测值的中值。和MAPE的用法一样,范围[0,+∞),MAPE 为0%表示完美模型,MAPE 大于 100 %则表示劣质模型。
  • smape是针对mape的问题的修正指标,可以较好的避免mape因为真实值yi小而计算结果太大的问题;

注意

  • 当真实值有数据等于0,而预测值也等于0时,存在分母0除问题,该公式不可用!
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/12/21 15:05
# @Author  : 府学路18号车神
# @Email   :yurz_control@163.com
# @File    : Evaluation_index.py

import numpy as np
from sklearn import metrics

# 将sklearn的也封装一下吧
# MSE
def mse(y_true, y_pred):
    res_mse = metrics.mean_squared_error(y_true, y_pred)
    return res_mse
# RMSE
def rmse(y_true, y_pred):
    res_rmse = np.sqrt(metrics.mean_squared_error(y_true, y_pred))
    return res_rmse

# MAE
def mae(y_true, y_pred):
    res_mae = metrics.mean_absolute_error(y_true, y_pred)
    return res_mae

# sklearn的库中没有MAPE和SMAPE,下面根据公式给出算法实现
# MAPE
def mape(y_true, y_pred):
    res_mape = np.mean(np.abs((y_pred - y_true) / y_true)) * 100
    return res_mape

# SMAPE
def smape(y_true, y_pred):
    res_smape = 2.0 * np.mean(np.abs(y_pred - y_true) / (np.abs(y_pred) + np.abs(y_true))) * 100
    return res_smape

# main
if __name__=='__main__':

    # 由于没有用模型,这里就随机出几个值来测试下吧
    y_true = np.random.random(10)
    print(y_true)
    y_pred = np.random.random(10)
    print(y_pred)
    # MSE
    print(mse(y_true, y_pred))
    # RMSE
    print(rmse(y_true, y_pred))
    # MAE
    print(mae(y_true, y_pred))
    # MAPE
    print(mape(y_true, y_pred)) # 得到的值直接看成百分比即可
    # SMAPE
    print(smape(y_true, y_pred)) # 得到的值直接看成百分比即可

MSE 平均平方损失函数 (L2损失)

均方误差(MSE)是最常用的回归损失函数,MSE是目标变量和预测值之间距离的平方和

平方损失函数标准形式如下:

[公式]

特点:

  • (1)经常应用与回归问题s

MSE与MAE的比较(L2损失与L1损失的比较)

  • 使用平方误差更容易解决,但是使用绝对误差更有鲁棒性(MAE比MSE对异常值更稳健)
  • 由于MSE平方了误差(y - y_predicted = e),若e大于1,误差(e)的将会增加很多。如果我们有一个离群值,e的值会大大增大,且MSE的值会远远大于e,这将会使MSE损失模型比MAE损失模型给与离散值更多的权重。若将RMSE作为损失的模型进行调整,损失模型将最小化异常点,而牺牲其他观测值,这回降低其整体性能
  • MAE梯度始终使相同的,这意味着即使损失值很小,梯度也会很大
  • 不均衡数据集下,两种损失函数都不好 → ①转换目标变量,②用别的损失函数,如Huber损失
# true: Array of true target variable
# pred: Array of predictions
 
def mse(true, pred):
  return np.sum((true - pred)**2)
    
def mae(true, pred):
  return np.sum(np.abs(true - pred))
 
# also available in sklearn
 
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error

Huber损失,平滑平均绝对误差(Smooth Mean Absolute Error)

为什么使用Huber Loss?

  • MAE一个大问题:梯度是一个比较大的常数,这可能导致在使用梯度下降训练结束时,丢失了最小值。
  • 对于MSE,梯度随着损失函数接近其最小值而减小,从而更容易找到最小值。
  • Huber损失在在最小值附近减小了梯度,而且比MSE更健壮。 因此,Huber损失结合了MSE和MAE的优点,然而,Huber损失的问题是我们可能需要训练超参数δ,这是一个迭代的过程。

与平方误差损失相比,Huber损失对数据中的异常值不那么敏感,它在0处也是可微的。当误差很小的时候就变成了二次误差,误差有多小才能变成二次函数取决于超参数 δ (delta),这个超参数是可调的。取值选择很关键!

  • 当超参数 δ ~ 0 时,Huber损失方法接近MAE;
  • 当超参数 δ ~ ∞ 时,Huber损失方法接近MSE。
  • 公式
  • 曲线,不同颜色的曲线表示不同的超参数(真实值等于0)

log对数损失函数

log对数损失函数的标准形式如下:

[公式]

特点:

  • (1) log对数损失函数能非常好的表征概率分布,在很多场景尤其是多分类,如果需要知道结果属于每个类别的置信度,那它非常适合。
  • (2)健壮性不强,相比于hinge loss对噪声更敏感。
  • (3)逻辑回归的损失函数就是log对数损失函数。

Log-Cosh损失

Log-Cosh是回归任务中使用的另一个函数,它比L2更平滑,Log-cosh是预测误差的双曲线余弦的对数。

  • Log-Cosh损失函数与预测值的曲线(真实值等于0):
  • 优点:
    • 当 x 较小时,log(cosh(x))近似等于(x**2)/2;
    • x较大时,近似等于 abs(x) - log(2)。这意味这“logcosh”的工作原理与MSE非常相似,但不会受到偶尔出现异常值的影响。
  • 它具有Huber损失的所有优点,且在任何情况下都是可微的。

为什么我们需要二阶导 ?

  • 许多ML模型实现(如XGBoost)都使用牛顿方法来寻找最优值,这就是为什么使用二阶微分(Hessian)的原因。对于像XGBoost这样的ML框架,两次可微函数更受欢迎。

xgboost的目标函数:

其中g_i和h_i分别是损失函数l的一阶微分和二阶微分:

但是logcosh损失并不完美,当预测值与真实值偏差较大时,梯度和二阶微分是一个常数,不符合xgboost的分割条件 。

Huber和Log-cosh损失函数的Python代码

# huber loss
def huber(true, pred, delta):
    loss = np.where(np.abs(true-pred) < delta , 0.5*((true-pred)**2), delta*np.abs(true - pred) - 0.5*(delta**2))
    return np.sum(loss)
 
# log cosh loss
def logcosh(true, pred):
    loss = np.log(np.cosh(pred - true))
    return np.sum(loss)

指数损失函数(exponential loss)

指数损失函数的标准形式如下:

[公式]

特点:

  • (1)对离群点、噪声非常敏感。经常用在AdaBoost算法中。

分位数损失

大多数预测问题中,我们常常对预测中的不确定性感兴趣。需要了解预测的范围区间估计,而不是估计),即想要预测一个区间而不是一个点时,分位数损失函数是有用的。

最小二乘回归的预测区间是基于残差(y-y_hat)在各自变量值之间具有恒定方差的假设。既不能相信违背这一假设的线性回归模型,也不能抛弃将线性回归模型作为基准来拟合的想法,因为使用非线性函数或基于树构建模型并非更好。

这就是分位数损失和分位数回归发挥作用的地方,基于分位数损失的回归为残差提供了合理的预测区间,即使残差的方差不是常数或非正态分布。

示例:最小二乘法

  • 左图为同方差的数据,右图为异方差的数据,运用最小二乘法后的线性回归结果
  • 分位数为0.05和0.95的分位数回归:虚线表示基于0.05和0.95的分位数损失的回归

分位数的回归是在给定预测变量的条件下,估计响应变量的条件分位数。分位数损失实际上是MAE的扩展,当分位数为0.5时,它就是MAE。

这个想法是根据想要给予正误差或负误差更多的值来选择分位数值,损失函数通过分位数来给高估的预测值或低估的预测值不同的惩罚权重,比如设置分位数 γ = 0.25时,分位数损失函数会给高估的预测值更多的惩罚,尽量保持预测值略低于中位数。

分位数损失函数

  • 分位数 γ 的值在0和1之间,预测值和分位数回归损失函数的关系如下图(真实值等于0)

用这个损失函数来计算神经网络和基于树模型的预测区间,下面是一个用于梯度增强树回归的sklearn实现实例:

Hinge 损失函数

Hinge损失函数标准形式如下:

[公式]

特点:

  • (1)hinge损失函数表示如果被分类正确,损失为0,否则损失就为 [公式] 。SVM就是使用这个损失函数。
  • (2)一般的 [公式] 是预测值,在-1到1之间, [公式] 是目标值(-1或1)。其含义是, [公式] 的值在-1和+1之间就可以了,并不鼓励 [公式] ,即并不鼓励分类器过度自信,让某个正确分类的样本距离分割线超过1并不会有任何奖励,从而使分类器可以更专注于整体的误差。
  • (3) 健壮性相对较高,对异常点、噪声不敏感,但它没太好的概率解释。

感知损失(perceptron loss)函数

感知损失函数的标准形式如下:

[公式]

特点:

  • (1)是Hinge损失函数的一个变种,Hinge loss对判定边界附近的点(正确端)惩罚力度很高。而perceptron loss只要样本的判定类别正确的话,它就满意,不管其判定边界的距离。它比Hinge loss简单,因为不是max-margin boundary,所以模型的泛化能力没 hinge loss强。

交叉熵损失函数 (Cross-entropy loss function)

交叉熵损失函数的标准形式如下:

[公式]

注意公式中 [公式] 表示样本, [公式] 表示实际的标签, [公式] 表示预测的输出, [公式] 表示样本总数量。

特点:

  • (1)本质上也是一种对数似然函数,可用于二分类和多分类任务中。

二分类问题中的loss函数(输入数据是softmax或者sigmoid函数的输出):

[公式]

多分类问题中的loss函数(输入数据是softmax或者sigmoid函数的输出):

[公式]

(2)当使用sigmoid作为激活函数的时候,常用交叉熵损失函数而不用均方误差损失函数,因为它可以完美解决平方损失函数权重更新过慢的问题,具有“误差大的时候,权重更新快;误差小的时候,权重更新慢”的良好性质。

最后奉献上交叉熵损失函数的实现代码:cross_entropy.

CTC loss

CTC Loss讲解

Focal loss

Focal loss出自计算机视觉目标检测领域,作者是斩获多届顶会best paper的何凯明。虽然出自目标检测,但是focal loss的思想在各个领域上都起到了很大的作用。总体上讲,Focal Loss是一个缓解分类问题中类别不平衡、难易样本不均衡的损失函数。传统交叉熵损失函数的形式为:

[公式]

其中,y为真值,p为预测概率,我们进一步可以将预测概率表示为:

于是上述交叉熵的表达式可以简化为:

[公式]

我们再来看一下Focal loss的具体形式:

[公式]

对比可以看到,focal loss相较于交叉熵多了两项 [公式][公式] . 这两项分别对应着前面提到的分类问题中类别不平衡、难易样本不均衡。 [公式] 的作用与前面加权交叉熵中的权重一样,用于处理类别不平衡,而[公式] 则用于处理难易样本不均衡。其实很容易理解,当 [公式] 较大的时候,说明样本比较容易被模型分类,此时 [公式] 的值就会较小。反之 [公式] 较小,样本难分, [公式] 就会加大。所以这也是一种加权。

TensorFlow对于focal loss同样没有封装,所以依然得我们自己自定义:

def test_softmax_focal_ce_3(gamma, alpha, logits, label):
    epsilon = 1.e-8
    logits = tf.nn.sigmoid(logits)
    logits = tf.clip_by_value(logits, epsilon, 1. - epsilon)
 
    weight = tf.multiply(label, tf.pow(tf.subtract(1., logits), gamma))
    if alpha is not None:  
        alpha_t = alpha
    else:
        alpha_t = tf.ones_like(label)
    xent = tf.multiply(label, -tf.log(logits))
    focal_xent = tf.multiply(alpha_t, tf.multiply(weight, xent))
    reduced_fl = tf.reduce_sum(focal_xent, axis=1)
    return tf.reduce_mean(reduced_fl)

NCE Loss

  • 当分类的类别很多时,模型很难训练,而且训练速度很慢,nec_loss可以解决这种问题,在word2vec模型训练过程中,不同的词向量的个数可能有上百万个,这样直接采用softmax分类的方式是不太可行的,nce_loss可以采用随机负采样,相比hierarhical softmax可以大幅度提高性能。

  • 参考:知乎qiao

ROC

  • 在试图弄懂AUC和ROC曲线之前,一定要彻底理解混淆矩阵的定义
  • 混淆矩阵中有着Positive、Negative、True、False的概念,其意义如下:
    • 称预测类别为1的为Positive(阳性),预测类别为0的为Negative(阴性)。
    • 预测正确的为True(真),预测错误的为False(伪)。
  • 对上述概念进行组合,就产生了如下的混淆矩阵:
  • 由此引出True Positive Rate(真阳率)、False Positive(伪阳率)两个概念
  • 其实TPRate就是TP除以TP所在的列,FPRate就是FP除以FP所在的列,二者意义如下:
    • TPRate的意义是所有真实类别为1的样本中,预测类别为1的比例。
    • FPRate的意义是所有真实类别为0的样本中,预测类别为1的比例。
  • AUC即ROC曲线下的面积,而ROC曲线的横轴是FPRate,纵轴是TPRate,当二者相等时,即y=x,如下图:
    • 分类器对于正例和负例毫无区分能力,和抛硬币没什么区别——最差情况
    • 认为AUC的最小值为0.5(当然也存在预测相反这种极端的情况,AUC小于0.5,这种情况相当于分类器总是把对的说成错的,错的认为是对的,那么只要把预测类别取反,便得到了一个AUC大于0.5的分类器)
  • 希望得到的效果
    • 对于真实类别为1的样本,分类器预测为1的概率(即TPRate),要大于真实类别为0而预测类别为1的概率(即FPRate),即y>x
  • 最理想:既没有真实类别为1而错分为0的样本——TPRate一直为1,也没有真实类别为0而错分为1的样本——FP rate一直为0,AUC为1,这便是AUC的极大值。

【2021-9-17】你真的理解ROC与AUC吗? 含AUC图解

  • 一个优秀模型的AUC接近于1,这意味着它具有良好区分性能。理想的分类结果,两条曲线完全分离,ROC曲线完全与边界重叠
  • AUC ∈ [0 , 1], 两个曲线重叠时,模型会引入假正和假负的错误。根据阈值可以最大化和最小化他们。当AUC是0.7是意味着模型有70%的机会能够区分正负类。
  • 而当 AUC 为 0.5 时,意味着该模型没有任何类别分离能力,等于随机猜测。
  • 一个坏的模型的AUC接近0,这意味着它具有最差的可分性(可能并不非常正确)。
  • AUC=0时,模型把类别预测反了(实际没有多少意义)

AUC是什么

  • 在统计和机器学习中,常常用AUC来评估二分类模型的性能。AUC的全称是 area under the curve,即曲线下的面积。
  • 通常这里的曲线指的是受试者操作曲线(Receiver operating characteristic, ROC)
  • 相比于准确率、召回率、F1值等依赖于判决阈值的评估指标,AUC则没有这个问题。

ROC曲线早在第二次世界大战期间就被使用在电子工程和雷达工程当中,被用于军事目标检测。 后来,ROC曲线也被应用到心理学、医学、机器学习和数据挖掘等领域的模型性能评估。

对于二分类问题,预测模型会对每一个样本预测一个得分s或者一个概率p。 然后,可以选取一个阈值t,让得分s>t的样本预测为正,而得分s<t的样本预测为负。 这样一来,根据预测的结果和实际的标签可以把样本分为4类:

  正样本 负样本
预测为正 TP(真正例) FP(假正例)
预测为负 FN(假负例) TN(真负例)

随着阈值t选取的不同,这四类样本的比例各不相同。定义真正例率TPR和假正例率FPR为:

\[\text{TPR} = \frac{\text{TP}}{\text{TP} + \text{FN}} \\ \text{FPR} = \frac{\text{FP}}{\text{FP} + \text{TN}}\]

对于真正例率TPR,分子是得分>t里面正样本的数目,分母是总的正样本数目。 而对于假正例率FPR,分子是得分>t里面负样本的数目,分母是总的负样本数目。 因此,如果定义$N_+(t), N_-(t)$分别为得分大于t的样本中正负样本数目,$N_+, N_-$为总的正负样本数目, 那么TPR和FPR可以表达为阈值t的函数

\[\text{TPR}(t) = \frac{N_+(t)}{N_+} \\ \text{FPR}(t) = \frac{N_-(t)}{N_-}\]

随着阈值t的变化,TPR和FPR在坐标图上形成一条曲线,这条曲线就是ROC曲线。TPR又被成为sensitivity(灵敏度),(1-FPR)又被成为specificity(特异度)

显然,如果模型是随机的,模型得分对正负样本没有区分性,那么得分大于t的样本中,正负样本比例和总体的正负样本比例应该基本一致。 也就是说

\[\frac{N_+(t)}{N_-(t)} = \frac{N_+}{N_-}\]

结合上面的式子可知TPR和FPR相等,对应的ROC曲线是一条直线!

反之,如果模型的区分性非常理想,也就是说正负样本的得分可以完全分开,所有的正样本都比负样本得分高,此时ROC曲线表现为「 字形。 因为正例得分都比负例搞,所以要么TPR=0要么FPR=0!

ROC曲线

实际的模型的ROC曲线则是一条上凸的曲线,介于随机和理想的ROC曲线之间。而ROC曲线下的面积,即为AUC!

\[\text{AUC} = \int_{t=\infty}^{-\infty} y(t) d x(t)\]

这里的x和y分别对应TPR和FPR,也是ROC曲线的横纵坐标。

  • AUC的优化目标:TPR和(1-FPR)
  • F1的优化目标:Recall和Precision

AUC的概率解释

概率解释的证明

AUC常常被用来作为模型排序好坏的指标,原因在于AUC可以看做随机从正负样本中选取一对正负样本,其中正样本的得分大于负样本的概率! 这个结论很容易证明,考虑随机取得这对正负样本中,负样本得分在$[t, t+\Delta t]$之间的概率为

\[\begin{align*} & P(t \le s_- < t+\Delta t) \\ = &P( s_- \gt t) - P(s_- > t+\Delta t) \\ = & \frac{N_-(t) - N_-(t+\Delta t)}{N_-} \\ = & x(t) - x(t +\Delta t) = - \Delta x(t) \end{align*}\]

如果$\Delta t$很小,那么该正样本得分大于该负样本的概率为

\[P(s_+ > s_- | t \le s_- < t+\Delta t) \\ \approx P(s_+ > t) = \frac{N_+(t)}{N_+} = y(t)\]

所以,

\[\begin{align*} & P(s_+ > s_- ) \\ = & \sum P(t \le s_- < t+\Delta t) P(s_+ > s_- | t \le s_- < t+\Delta t) \\ = & -\sum y(t) \Delta x(t) \\ = & -\int_{t=-\infty}^{\infty} y(t) d x(t) \\ = & \int_{t=\infty}^{-\infty} y(t) d x(t) \end{align*}\]

注意积分区间,$t=-\infty$对应ROC图像最右上角的点,而$t=\infty$对应ROC图像最左下角的点。所以,计算面积是$\int_{t=\infty}^{-\infty}$。 可以看出,积分项里面实际上是这样一个事件的概率:随机取一对正负样本,负样本得分为t且正样本大于t! 因此,对这个概率微元积分就可以到正样本得分大于负样本的概率!

AUC的排序特性

根据上述概率解释,AUC实际上在说一个模型把正样本排在负样本前面的概率! 所以,AUC常用在排序场景的模型评估,比如搜索和推荐等场景! 这个解释还表明,如果将所有的样本的得分都加上一个额外的常数,并不改变这个概率,因此AUC不变! 因此,在广告等需要绝对的点击率场景下,AUC并不适合作为评估指标,而是用logloss等指标。

AUC对正负样本比例不敏感

利用概率解释,还可以得到AUC另外一个性质,对正负样本比例不敏感。 在训练模型的时候,如果正负比例差异比较大,例如正负比例为1:1000,训练模型的时候通常要对负样本进行下采样。当一个模型训练完了之后,用负样本下采样后的测试集计算出来的AUC和未采样的测试集计算的AUC基本一致,或者说前者是后者的无偏估计! 如果采样是随机的,对于给定的正样本,假定得分为$s_+$,那么得分小于$s_+$的负样本比例不会因为采样而改变! 例如,假设采样前负样本里面得分小于$s_+$的样本占比为70%,如果采样是均匀的,即$>s_+$的负样本和$<s_+$的负样本留下的概率是相同的,那么显然采样后这个比例仍然是70%! 这表明,该正样本得分大于选取的负样本的概率不会因为采样而改变,也就是$y(t)dx(t)$是不变的,因此,AUC也不变!

相比于其他评估指标,例如准确率、召回率和F1值,负样本下采样相当于只将一部分真实的负例排除掉了,然而模型并不能准确地识别出这些负例,所以用下采样后的样本来评估会高估准确率;因为采样只对负样本采样,正样本都在,所以采样对召回率并没什么影响。这两者结合起来,最终导致高估F1值!

AUC的计算

AUC可以直接根据ROC曲线,利用梯形积分进行计算。此外,还有一个比较有意思的是,可以 利用AUC与Wilcoxon-Mann-Whitney测试的U统计量的关系,来计算AUC。这可以从AUC的概率意义推导而来。

假设我们将测试集的正负样本按照模型预测得分 从小到大 排序,对于第$j$个正样本,假设它的排序为 $r_j$, 那么说明排在这个正样本前面的总样本有 $r_j - 1$个,其中正样本有 $j-1$个(因为这个正样本在所有的正样本里面排第j), 所以排在第j个正样本前面(得分比它小)的负样本个数为 $r_j - j$个。也就是说,对于第j个正样本来说,其得分比随机取的一个负样本大(排序比它靠后)的概率是 $(r_j - j) / N_-$,其中$N_-$是总的负样本数目。所以,平均下来,随机取的正样本得分比负样本大的概率为

\[\frac{1}{N_+} \sum_{j=1}^{N_+}(r_j - j)/N_- = \frac{\sum_{j=1}^{N_+}r_j - N_+(N_+ + 1)/2}{N_+N_-}\]

所以

\[AUC = \frac{\sum_{j =1}^{N_+} r_j - N_+(N_+ + 1)/2}{N_+ N_-}\]

因此,很容易写出计算AUC的SQL代码

select
	(ry - 0.5*n1*(n1+1))/n0/n1 as auc
from(
	select
		sum(if(y=0, 1, 0)) as n0,
		sum(if(y=1, 1, 0)) as n1,
		sum(if(y=1, r, 0)) as ry
	from(
		select y, row_number() over(order by score asc) as r
		from(
			select y, score
			from some.table
		)A
	)B
)C

AUC的优化

采用极大似然估计对应的损失函数是logloss,因此极大似然估计的优化目标并不是AUC。 在一些排序场景下,AUC比logloss更贴近目标,因此直接优化AUC可以达到比极大似然估计更好的效果。 实际上,pairwise的目标函数就可以看做一种对AUC的近似。因为损失函数都是作用与正负样本得分差之上! 例如,

类型 公式
rank-SVM $\max(0, - s_+ + s_- + \Delta)$
rank-net $\log (1 + \exp(- (s_+ - s_-)))$
指数损失 $\exp(- (s_+ - s_-))$
TOP 损失 $\sum_s \max(0, - s_c + s + \Delta)$

显然,这些损失函数都是对\(s_+<s_-\)的正负样本对进行惩罚! 此外,也有一些其它对AUC近似度更好的损失函数,例如

\[\mathbf{E} \left[ (1-w^T(s_+ - s_-))^2 \right] = \frac{1}{n_+n_-} \sum_{i=1}^{n_+} \sum_{j=1}^{n_-} (1-w^T(s_{i}^+ - s_{j}^-))^2\]

$s_i^+, s_j^-$分别表示正例和负例的得分。 这解释了为什么某些问题中,利用排序损失函数比logloss效果更好,因为在这些问题中排序比概率更重要

AUC要到多少才算好的模型

AUC越大表示模型区分正例和负例的能力越强,那么AUC要达到多少才表示模型拟合的比较好呢?在实际建模中发现,预测点击的模型比预测下单的模型AUC要低很多,在月活用户里面预测下单和日活用户里面预测下单的AUC差异也很明显,预测用户未来1小时下单和预测未来1天的下单模型AUC差异也很大。这表明,AUC非常依赖于具体任务。

以预测点击和预测下单为例,下单通常决策成本比点击高很多,这使得点击行为比下单显得更加随意,也更加难以预测,所以导致点击率模型的AUC通常比下单率模型低很多。

那么月活用户和日活用户那个更容易区分下单与不下单用户呢?显然月活用户要容易一些,因为里面包含很多最近不活跃的用户,所以前者的AUC通常要高一些。

对于预测1小时和预测1天的模型,哪一个更加困难?因为时间越长,用户可能发生的意料之外的事情越多,也越难预测。举个极端的例子,预测用户下一秒中内会干啥,直接预测他会做正在干的事情即可,这个模型的准确率就会很高,但是预测长期会干啥就很困难了。所以对于这两个模型,后者更加困难,所以AUC也越低。

数据标注

【2022-9-25】标注工具总结

标注工具

工具名 开闭源 作者 体验地址 总结 备注
IEPY 开源 - 文档, 工程完整,有用户管理系统。前端略重,对用户不是非常友好 安装失败
DeepDive 开源 stanford 前端代码,demo,失效, 前端比较简单,用户界面友好 汉化版:DeepDiveChineseApps,DeepDive_Chinese
BRAT 开源 - demo,git地址, 英文  
SUTDAnnotator 开源 - 论文 非web,pythonGUI,但比较轻量 -
Snorkel - - demo,论文    
Prodigy 闭源 spaCy同家公司Explosion.ai 示例, 支持模型加载+主动学习,体验不错,但要收费 -
标注精灵 闭源 国内 - 中文环境,收费  
标注客户端 开源 - - python开发,大而全 -
ImageNet的GUI标注工具 开源 - - 图像标注 -
Universal Data Tool 开源 国外 - 通用数据(标注)工具:用简单的网络界面/桌面应用协作标注图像、文本、文档等数据 安装失败
MarkTool 开源 个人 基于web的通用文本标注工具,支持大规模实体标注、关系标注、事件标注、文本分类、基于字典匹配和正则匹配的自动标注以及用于实现归一化的标准名标注,同时也支持文本的迭代标注和实体的嵌套标注  
Chinese-Annotator 开源     仿照Prodigy,主动学习,详情介绍 讨论区
label-studio 开源 - ,后端纯python编写,使用了flask,前端:React + MST 界面相对美观,部署方便,可以明晰了解任务的完成度,支持图像、文本和音频等多种数据格式和多种任务数据的标注,但速度慢,没有账号体系 介绍
doccano 开源   doccano demo, 代码一站式文本标注工具, 中文  
           

评分

Elo机制

【2023-5-26】什么才是真正的Elo机制

什么是Elo?

Elo Rating System 是由匈牙利裔美国物理学家 Arpad Elo 创建的一个衡量各类对弈活动水平的评价方法,是当今对弈水平评估的公认的权威方法。

  • 被广泛用于博弈类比赛,国际象棋围棋足球篮球等运动。网络游戏英雄联盟魔兽世界内的竞技对战系统也采用此分级制度。
  • 电影 《社交网络》中 , 创办了 Facebook 的 Mark ZuckerbergEduardo Saverin 在 Harvard 读大二时, 一夜间搭建了网站 Facemash。这个网站每次会展示两张不同女生的照片,用户选择自己认为更好看的一张。每次选择后,便进入下一组女生照片的评选。最终, Facemash 将计算出全校女生的长相排名。这其中所用的算法,就是 Elo Rating System

Elo不是游戏首创,在体育竞技中十分常见。篮球、乒乓球、围棋、国际象棋等等,都会使用Elo来衡量运动员的水平。

  • 系统基于统计学, 只是一种参考,并不能绝对衡量出运动员实力。
    • 体育竞技本身就是一种十分复杂的游戏,一场比赛的输赢受到许多因素的影响,运动员的状态、运气、心理素质、场地氛围等等,都可能左右一场比赛。
  • 设计之初,Elo Rating System 仅是一个国际象棋选手的排名系统。
    • Elo 成为公认最权威的方法,是因为比之前所有评分系统都先进,更容易准确反应一个选手的真实水平。
    • 1970年,国际棋联正式开始使用这个评分系统。
    • Elo遭1V1对抗时用的最多,预测多人对抗游戏并不是它的强项

Elo 原理

Elo评级系统是如何运行的呢?

Elo 用一个数字来衡量运动员的水平,每场比赛结束后,赢家会从输家那里获得积分。两名运动员之间的积分差异决定一场比赛后,获得或者失去的积分。

  • 如果评分的运动员获胜,那么只会从评分低的运动员那里,获得一点点积分。
  • 相反 如果评分的运动员爆冷,就会抢走评分高的运动员大量积分。
  • 如果平局,评分的运动员,同样会抢走评分低的运动员一定的积分。

注意

  • 只要运动员的场次足够多,Elo就会真实地反应出运动员的真实水平

如何实现对象的评价和排名

  • Elo假设每个玩家在每盘游戏中的表现是一个正态分布的随机变量
  • 尽管选手在不同的游戏中发挥可能差异很大,但每位选手在一段时间内表现的平均值变化很小。
  • Elo用随机变量的平均值来代表选手的真正水平。
  • 简单的说:每个选手在每盘游戏中的发挥都是不稳定的,80的实力可能发挥出85,或者发挥出75, 但是随着比赛的不断进行,可以越来越多的趋近80这个真实水准。而ELO是用这个平均值来作为真实水准

假设: ELO算法的原理及应用

一名选手当前实力受各种因素的影响, 在一定范围内波动,某个时刻用来描述其实力的函数应当符合正态分布

两名选手进行对战时的预期胜率

  • D为两者的分差。

利用了最小二乘法,得到与它的函数图向相近的另外的一个函数

当玩家A与玩家B的分差为D时,玩家A对玩家B的期望胜率为P(D)

  • 玩家分数相同时,对战预期胜率为50%,分差越大,玩家之间的胜率差距也就越大,当分差大于400时,低分玩家的预期胜率将不足10%。
  • 取K=32时,玩家结束一场比赛后的实际得分数如图所示。可以看到玩家战胜比自己低800分的选手后(有近100%的胜率)基本不得分。

Elo 用一个数字衡量运动员水平,每场比赛结束后,赢家会从输家那里获得积分。

  • 两名运动员之间的积分差异,决定一场比赛后,获得或者失去的积分。
  • 如果评分高的运动员获胜,那么只会从评分低的运动员那里,获得一点点积分
  • 相反,如果评分低的运动员爆冷,就会抢走评分高的运动员大量积分。
  • 如果平局,评分低的运动员,同样会抢走评分低的运动员一定的积分。

只要运动员的场次足够多,Elo就会真实地反应出运动员的真实水平。

Ra: A选手当前分数
Rb: B选手当前分数

# Ea: 预期A选手的胜负值
Ea = 1/(1+10^[(Rb-Ra)/400])

# Eb: 预期B选手的胜负值
Eb = 1/(1+10^[(Ra-Rb)/400])

E值也是预估的双方胜率,所以 Ea + Eb = 1

Sa: 实际胜负值,胜 = 1, 平 = 0.5, 负 = 0
K: 每场比赛能得到的最大分数,魔兽里 k=32 

R'a: A选手一场比赛之后的积分
R'a = Ra + K(Sa-Ea)

R'b: B选手一场比赛之后的积分
R'b = Rb + K(Sa-Eb)

举例

A队1500分,B队1600分,则
预估A队的胜负值 Ea = 1/(1+10^[(1600-1500)/400]) = 0.36
预估B队的胜负值 Eb = 1/(1+10^[(1500-1600)/400]) = 0.64

假设A队赢了,
A队最终得分为 R'a = 1500 + 32*(1-0.36) = 1500+20.5 = 1520, 赢20分,B队输20分。
假设B队赢了,
B队最终得分为 R'b = 1600 + 32*(1-0.64) = 1600 + 11.52 = 1612, 赢12分,A队输12分。

这就是为什么你赢高分队分数多,输给低分的输的也多,赢低分的分数很少。
其实K值就是这个方程的极限,所以理论上你最多可以赢一个队伍32分,实际上29-30已经差不多了,赢了不得分也是有可能的。

但是,Elo评分系统基于统计学,只是一种参考,并不能绝对衡量出运动员的实力。

  • 体育竞技本身就是一种十分复杂的游戏,一场比赛的输赢受到许多因素的影响,运动员的状态、运气、心理素质、场地氛围等等,都可能左右一场比赛。
  • 电竞是Elo应用最广泛的领域. CSGO、守望先锋、魔兽世界都采用Elo机制,或者Elo机制的升级版-Glicko-2

Elo之所以能成为公认最权威的方法,是因为它比之前所有的评分系统都先进,更容易更准确反应一个选手的真实水平。

  • 1970年,国际棋联正式开始使用这个评分系统。

Elo遭1V1对抗时用的最多,预测多人对抗游戏并不是强项。

Elo 会赋予每位玩家一个相同的初始积分,并进行以下计算:

  1. 根据积分差计算双方获胜概率;
  2. 每位玩家根据对方积分和游戏结果所表现出的水平分;
  3. 得出游戏后的积分变化。

Elo 工作模式总结:

  1. Elo 会给出玩家一场对局的获胜概率。Elo 积分相差越大,积分高的一方获胜概率就越大;
  2. 每场对局后,对阵双方都会进行一部分积分交换,胜者得分,败者失分;
  3. 如果两名玩家的积分相差很大,代表高分方获胜的概率极大,因此 即便赢了也涨不了多少分,败方也掉不了多少分。但倘若被低分方爆出冷门,那高分 方将失去大量分数。

Elo缺点

Elo Rating System 的缺点

任何算法系统都有优缺点,Elo 也不例外。

  • 初期的盲目性
    • Elo 积分在达到合理(趋近真实)水平之前需要一个过程。比如一个 2000 分的玩家玩小号,遇到的对手大概都是 1400 分水平,这时候 Elo 积分是不能准 确反映他的实力的。经过几局对战,这名玩家的积分会逐渐达到合理水平。这个 过程就是 Elo 积分的收敛过程。
  • 对时间不敏感
    • Elo 积分不会随着时间变化,当一位玩家很长时间没有游戏的时候,他的水 平可能会上下浮动,但他的 Elo 积分并不会随之改变。尤其对于顶尖玩家而言, 这时候的积分排名未必能反映玩家间真实的实力排名。

Elo 改进

Elo本来是一个好东西,但是游戏厂家一般都会对Elo进行魔改,这也是不同游戏,玩家对elo感知不同的原因。改得不好,简直就是一场灾难。

Elo 初次进入玩家视野,是王者荣耀策划 Donny 2018年在微博上发的一条关于匹配机制的解释。

关键点:

  1. 段位和Elo值共同决定匹配对手和队友;
  2. 如果等待时间过长,则放大Elo的寻找范围;
  3. 利用勇者积分机制,让玩家快速达到真实实力所在段位;

这些都是体育竞技中的Elo所没有的。因为这些特别的规则,玩家一些现象很容易解释,比如:

  • 王者荣耀中,为什么王者局,可以匹配到星耀2(星耀晋级后是王者段位)的玩家,这时因为这名星耀2玩家的Elo太高,已经达到了最强王者段位的水平。反之,最强王者匹配到星耀局,说明 Elo太低了。
  • 如此一来,又会出现一些问题。星耀2玩家因为Elo分数高去打王者局,在其他玩家实力大致相当的前提下,如果这名玩家实力是荣耀王者(最强王者50星),那么对手很容易被碾压。如果这名玩家是靠运气连胜导致Elo分数太高,又会成为队伍的累赘。

事实证明,双方实力大致相当的对局非常少。因为这名玩家需要足够多的场次,Elo值才能真实反应他的水平,而且即便如此,也不能排除他心情好,练一把英雄的情况……

再比如强行将匹配时长加入Elo机制中。

  • 玩家匹配等待时间过长,则放大Elo的寻找范围。

换句话说,假设9名最强王者玩家的Elo值都是1500分左右,但此时死活就是找不到一个1500分左右的最强王者玩家,那么系统就会扩大范围,强行匹配一个Elo 1600分,或者Elo 1400分的玩家。毫无疑问,出现这种情况,对局本身就不是公平的,更没有50%的胜率可言。

电竞中的Elo算法最大的问题是: 不能保证双方玩家的水平相当。

  • 对方70%能赢,己方30%能赢,结果阵容怎么好,英雄理解怎么到位,操作怎么溜,就是有一个坑货,怎么都赢不了。

关于Elo的错误认识。

  • 强行50%胜率
  • 拿败方MVP下把容易输
  • 隐藏分很高,下局逆风局
  • 连胜后必定连跪

换一种算法,是否能避免这种现象的出现?

  • 答案是不能,但可能减少。不能避免,是因为你总有达到属于自己实力段位的时候,总有运气爆棚连胜的时候,也会有运气差的时候。只要有一种算法,能保证双方在选阵容前,胜率是50%,双方水平相当,这种现象就会减少。

让我来告诉你,什么才是真正的Elo机制

Elo 实践

【2023-8-4】Elo Python实践代码

def expected_score(r1, r2):
    return 1 / (1 + 10**((r2 - r1) / 400))

def update_elo(r1, r2, score1):
    e1 = expected_score(r1, r2)
    e2 = expected_score(r2, r1)
    return r1 + K * (score1 - e1), r2 + K * ((1 - score1) - e2)

# K is a constant factor that determines how much ratings change
K = 32
# Convert scores to numeric values
score1 = 1 if score1 == 'A' else 0 if score1 == 'B' else 0.5
score2 = 1 if score2 == 'B' else 0 if score2 == 'A' else 0.5

# Average the scores
score = (score1 + score2) / 2

# Update ELO ratings
r1, r2 = prompt_ratings[prompt1], prompt_ratings[prompt2]
r1, r2 = update_elo(r1, r2, score)

评分卡

  • KDD的2019年会上,俄罗斯联邦储蓄银行(Sberbank)发布的论文《E.T.-RNN: Applying Deep Learning to Credit Loan Applications》,这是一篇将深度学习应用于风控领域的一个不错的探索
    • 传统评分卡方法: 信用评分是银行业务基础指标,经典的信用评分方法基于用户的申请单信息,用户的信用历史和其他关联的金融信息。传统的评分卡多采用经典的机器学习算法比如逻辑回归,GBDT,LighgtGBM等算法预测用户的贷后表现。
    • 尽管经典机器学习算法广泛应用且效果不错,但有以下不足:
      • 需要大量的特征工程工作和行业领域知识
      • 对于白户(无信用历史)的用户,很难给定评分
      • 传统算法模型没有充分利用用户数据
    • 论文提出了一种基于深度学习的评分卡算法,该方法基于到户交易数据利用RNN模型预测申请贷款用户的信用分。算法名称ETRNN全称Embedding Transactional Recurrent Neural Network,主要是利用用户的借记卡和信用卡的交易数据,只要用户有信用卡或者借记卡,就可以利用该方法。与传统的信用评分方法相比,ETRNN算法有以下有点:
      • 首先该方法效果超过了传统的方法。
      • 该方法基于用户的交易数据,不需要大量的特征工程方法和领域知识。
      • 该方法并部需要申请人除交易数据之外的其他数据,这意味着可以快速授信,改善用户体验。
      • 用户交易数据很难仿造。
      • 即使白户也可以利用交易数据评分。
    • 传统的评分卡方法,往往是对用户的交易流水历史做一些聚合,得到一些特征;而深度学习方法直接利用用户的交易流水数据,更好的利用用户消费的时序信息。

什么是信用评分卡模型?

评分卡模型又叫做信用评分卡模型,最早由美国信用评分巨头FICO公司于20世纪60年代推出,在信用风险评估以及金融风险控制领域中广泛使用。银行利用评分卡模型对客户的信用历史数据的多个特征进行打分,得到不同等级的信用评分,从而判断客户的优质程度,据此决定是否准予授信以及授信的额度和利率。相较资深从业人员依靠自身的经验设置的专家规则,评分卡模型的使用具有很明显的优点:

  • 判断快速:系统只需要按照评分卡逐项打分,最后通过相应的公式计算出总分,即可准确判断出是否为客户授信以及额度和利率。
  • 客观透明:评分卡模型的标准是统一的,无论是客户还是风险审核人员,都可以通过评分卡一眼看出评分结果和评判依据。
  • 应用范围广:由于评分卡的评分项是客观计算,其得出的分数具有广泛的参考性和适用性。例如,生活中常见的支付宝芝麻信用分,就是依据评分卡模型计算得出。

评分卡模型在银行不同的业务阶段体现的方式和功能也不一样。按照借贷用户的借贷时间,评分卡模型可以划分为以下三种:

  • 贷前申请评分卡(Application score card),又称为A卡
    • 更准确地评估申请人的未来表现(违约率),降低坏帐率
    • 加快(自动化)审批流程, 降低营运成本
    • 增加审批决策的客观性和一致性,提高客户满意度
  • 贷中行为评分卡(Behavior score card),又称为B卡
    • 更好的客户管理策略, 提高赢利
    • 减少好客户的流失
    • 对可能拖欠的客户,提早预警
  • 贷后催收评分卡(Collection score card),又称为C卡
    • 优化催收策略,提高欠帐的回收率
    • 减少不必要的催收行为,降低营运成本

评分卡模型示例:

一个用户总的评分等于基准分加上对客户各个属性的评分。举个例子某客户年龄为27岁,性别为男,婚姻状况为已婚,学历为本科,月收入为10000,那么他的评分为:223+8+4+8+8+13=264

评分效果评估

专家训练场的评估分为三段:房源自述、小贝问答、推荐房源。最终的评分结果根据上述三个部分加权得到,现阶段没有完整数据可以标注,需要对各个阶段先进行评估,确保各阶段的评估合理。其中,推荐房源可以根据经纪人推荐的房源和系统候选房源进行对比,这个指标不需要评估,另外两个指标涉及意图识别及加权策略,需要进行评估。

评估使用基于pair-wise的方式,通过分析对比结果与评分之间的关系得出评估是否合理:

  • 如果相对好的数据评分相对高,则评价合理
  • 如果相对好的数据评分相对低,则评价不合理

文本为VR带看经纪人训练场中经纪人的文本,标注目标为标注文本A相对于文本B的好坏程度,数字的含义如下:

  • -2(很差),-1(较差),0(差不多),1(较好),2(很好)

标注的数据有两个部分:

  • (1)房源自述,对应的title为narrate,比较的时候参考以下标准:
    • 基础素质(讲解房源、小区、配套等)
  • (2)小贝问答,对应的title为show,比较的时候参考以下标准:
    • 服务态度(标注开场白、结束语等)
    • 需求理解与挖掘(理解客户需求,挖掘客户需求,比如购房意愿、金额等)

评分结果的验证分为以下几个方面:

  • (1)分数分布验证,检验是否为正态分布。如VR带看里,房源自述+小贝问答两种语料,检查概率分布
  • (2)一致性检验,即定性检验,检查标注的好坏是否与分差保持一致
    • 例如:文本A相对于文本B是1,文本A的分数是90,文本B是80,因为90 > 80,所以这条数据是通过一致性检验的。
    • 房源自述和小贝问答的一致率均大于 90%,说明一致率很高,简单理解评分的好坏准确率为90%以上。
  • (3)分值检验,即定量检验,检查标注的好坏程度是否与分差保持正比关系
    • 如果标注结果与分差正相关,那么打分的结果是比较合理的。
    • 例如:标注结果为文本A1相对于文本B1是1,实际分差为10分,标注结果为文本A2相对于文本B2是2,实际分差为20分,标注结果与分差是正相关的,说明评分的分数合理。
  • 参考

评分卡模型

如何搭信用评分卡模型?有了上面的评分卡示例,接下来需要考虑的是如何生成类似上面的表格:

  • 变量特征是如何选取的?
    • 剔除跟目标变量不太相关的特征, 涉及:变量两两相关性分析, 变量的多重共线性分析
    • 消除由于线性相关的变量,避免特征冗余
    • 减轻后期验证、部署、监控的负担
    • 保证变量的可解释性
  • 特征的变量范围是如何进行划分的?对变量进行分箱来实现变量的分段
    • 分箱的定义:①对连续变量进行分段离散化②将多状态的离散变量进行合并,减少离散变量的状态数
    • 常见的分箱类型:
      • ①无监督分箱。 无监督分箱仅仅考虑了各个变量自身的数据结构,并没有考虑自变量与目标变量之间的关系,因此无监督分箱不一定会带来模型性能的提升。
        • 等频分箱:把自变量按从小到大的顺序排列,根据自变量的个数等分为k部分,每部分作为一个分箱。
        • 等距分箱:把自变量按从小到大的顺序排列,将自变量的取值范围分为k个等距的区间,每个区间作为一个分箱。
        • 聚类分箱:用k-means聚类法将自变量聚为k类,但在聚类过程中需要保证分箱的有序性。
      • ②有监督分箱,包括 Split 分箱和 Merge 分箱
        • Split 分箱是一种自上而下(即基于分裂)的数据分段方法。Split 分箱和决策树比较相似,切分点的选择指标主要有 Entropy,Gini 指数和 IV 值等。
        • Merge 分箱,是一种自底向上(即基于合并)的数据离散化方法。Merge 分箱常见的类型为Chimerge分箱。
      • ③ChiMerge 分箱
        • ChiMerge 分箱是目前最流行的分箱方式之一,其基本思想是如果两个相邻的区间具有类似的类分布,则这两个区间合并;否则,它们应保持分开。Chimerge通常采用卡方值来衡量两相邻区间的类分布情况。
  • 每个字段的分值是如何设定的?

变量选择方法: 更多方法请参考:机器学习之特征选择方法

  • 【2021-7-27】风险控制:信用评分卡模型

  • 【2021-3-21】深入浅出评分卡的逻辑回归原理
  • 信贷评分卡的建模过程中,使用最多的算法就是逻辑回归(logistics regression)函数。下面,我们将围绕下面几点详细地讲述逻辑回归的数学来源和业务用途:
    • 什么是逻辑回归函数?
    • 为什么评分卡要使用逻辑回归函数?
    • 经济意义下逻辑回归函数的由来?(从金融角度揭示)
    • 怎么产生标准评分卡?(评分卡分数的线性转换)
      • 模型最终的产出还得是分数,上述的 s(x) 为对数比率分数,想要转化为千分制的分数还必须进行分数线性转化:
      • 以下2个假设用于定义分数刻度:
        • log 比率为 1:1的时候,分数为500分;
        • 好坏比(odds)每增加一倍,分数增加20分。
      • 解出,所以
      • 分数输出: 经过特征筛选、证据权重的计算、系数的回归,对每个特征分组都计算出一个分数,得出如下标准评分卡格式
    • 逻辑回归-标准评分卡的实操。
  • 银行决定是否给个人或企业贷款的关键因素是对未来违约概率的预测,逻辑回归函数能提供此技术支持。假设某银行挑选了 n 个特征进入评分卡给客户进行准入评分,且这 n 个特征包含了能判断客户是好还是坏的充分信息,若是想预测某个客户在将来违约的概率,那么只需要收集该客户的n个特征信息,代入公式,就得到一个介于(0,1)之间的值,称为好客户的概率。
  • 在逻辑回归函数的作用下,可以将客户的特征信息(如婚姻、年龄、历史以往信贷表现等)综合起来并转化为一个概率值,该值给银行预测客户好坏提供了一个直观依据。即 p(z) 值越大,证明该客户在将来违约的概率越小。

基本流程

  • (1)是否有label,如果有,需要先做特征分析,剔除无关特征
    • 正式建模之前,一般会对特征工程挖掘到的特征集进行筛选,以选择相关性高、稳定性强的特征,作为入模变量。
    • 常用特征筛选一般会考虑如下几方面:
      • 1)特征覆盖率(cover rate),选取覆盖率达到一定阈值的特征;
      • 2)特征相关性:如根据特征本身的KS值、IV或卡方值,选择与建模label相关性高的特征;
      • 3)特征稳定性:比如通过衡量特征的PSI,选择随时间波动性尽可能小的特征。
      • 此外,还可以通过VIF、相关性系数等指标,排除特征之间的共线性。
  • (2)特征重要度数值+专家经验,制定组合方式,得到初步分数
  • (3)全局分布调整,转换到正太分布N(u,σ),u<及格线,保证分数具备区分度
  • (4)打分反馈闭环,根据用户反馈,补充到label中,回到(1)

无监督评分卡也有些方法,如基于专家经验的层次分析法,熵权法等

评分卡建模

  • 机器学习在信用评分卡中的应用
  • 特征和样本标签准备好后,评分卡建模的过程则比较自然。虽然深度学习等技术在互联网领域已大行其道,在信用评分卡建模中,逻辑回归或GBDT等仍然是目前主流的建模算法。一方面是金融领域对特征的可解释性要求会更高,通过LR或GBDT建模,比较容易直观得到每个特征在模型结果中的权重,并根据业务经验解释权重系数的合理性。另一方面,实际评分卡建模中,一般入模特征维度并不高。在低维度建模中,LR和GBDT已经可以取得比较可观的效果。

模型评估

  • 模型建立后,需要对模型的预测能力、稳定性进行评估。信用评分模型常用的评估指标为KS、AUC等。 考虑到金融业务反馈周期长的特点,除了划分训练集、测试集外,通常会预留一段训练样本时间段之外的数据集,作为OOT(跨时间)集合,以测量模型在时间上的稳定性。
  • 评分分布图的区分度
    • 如果通过评分能将好坏用户完全区隔开来,那是理想中最好的评分卡模型,但实际情况中好坏用户的评分会有一定程度的重叠,我们要做的就是尽量减小重叠程度。
    • 好坏用户的得分分布最好都是正态分布,如果呈双峰或多峰分布,那么很有可能是某个变量的得分过高导致,这样对评分卡的稳定性会有影响。
    • 摘自:评分卡模型的评估方法论, github 代码
  • 一文读懂评分卡的IV、KS、AUC、GINI指标
  • 当一张评分卡构建完成时,筛选出一组特征生成了分数,我们会想要知道这个分数是否靠谱,即是否可以依赖这个分数将好坏客户区分开来,这个时候就需要评判评分卡有效性的指标。
  • 测量评分卡好坏区分能力的指标有许多,本文就为大家介绍几个常用的定量指标:
    • 散度(分数为连续函数)与信息比率(IV);
    • KS值
    • ③ ROC曲线、AUROC值与GINI系数。

散度与信息比率

  • 散度为信息比率的连续版本。而评分卡分数是基于有限样本计算出的分数分布,并不一定是完全连续函数,所以就衍生出了离散版本的散度—-信息比率IV。
  • 在实际应用当中,IV值通常用来筛选变量,IV值越大,该变量的好坏区分能力越强。在评分卡建模的过程中,利用IV值筛选变量也是非常重要的一个环节。
  • 从IV值的公式中,易得变量的分组越多,IV值越大。但是分组分的太多,就会使得每个分组的数据量变少,导致细项分组的分布不稳定。所以,我们在使用IV值筛选变量的时候,不能为了提高IV值一味地将分箱的数目提高,也要兼顾变量的业务含义和分布的稳定性。

KS值

  • KS值是一个衡量好坏客户分数距离的上限值,具体做法为将对于各个分数区间对应的好坏客户累计占比进行相减,取最大值。
    • 为什么F(s|B)为凹函数、F(s|G)为凸函数?
    • 为什么F(s|B)-F(s|G)存在极大值(最大值)?
    • 为什么F(s|B)曲线在F(s|G)曲线之上?

ROC曲线与AUROC值

  • ROC曲线也是评分卡度量指标中常用的指标工具,在介绍KS统计量的时候,其分布函数是由好客户和坏客户对应的累计概率密度函数F(s|B)与F(s|G)随着分数s变化的图形,而ROC曲线是好客户的累计概率密度相对于坏客户的累计概率密度函数的图形
  • 根据上文的分析,得出越接近B点的曲线,好坏客户的区分能力越强,这个时候,ROC曲线与X轴围成的面积就越大。由此,衍生出ROC曲线关于X轴面积的指标AUROC(Area under the ROC curve)。

GINI曲线

  • AUROC值是ROC曲线和X轴的面积,GINI系数定义为ROC曲线和对角线AC之间的面积占对角线AC曲线围成面积比,即
    • 如果该评分系统异常完美,AUC曲线过点B(0,1),这个时候GINI=1;
    • 如果评分卡毫无区分度,那么AUC曲线即为AC曲线,这时GINI=0;
  • 所以,GINI系数是一个介于(0,1)之间的函数,该值越大,模型的区分能力越强。

实战

  • Python实现的半自动评分github地址,整个脚本的大概流程是:
    • PSI预筛选 –> 特征分箱 –> IV筛选特征 –> 相关性/多重共线性筛选 –> woe单调调整 – > 显著性筛选 –> 系数一致筛选 –> 建模 –> 模型评估 –> 标准评分转换

结束


支付宝打赏 微信打赏

~ 海内存知已,天涯若比邻 ~

Share

Similar Posts

Related Posts

下一篇 Docker学习笔记

标题:算法模型部署-Model Serving

摘要:如何将算法模型部署到线上?有哪些方法、工具及经验?

标题:Docker学习笔记

摘要:K8S,Docker 技术笔记

Comments

--disqus--

    My Moment ( 微信公众号 )
    欢迎关注鹤啸九天