搜索推荐评价指标

ROC

ROC的全称是“受试者工作特征”(Receiver Operating Characteristic)曲线,首先是由二战中的电子工程师和雷达工程师发明的,用来侦测战场上的敌军载具(飞机、船舰),也就是信号检测理论。之后很快就被引入了心理学来进行信号的知觉检测。此后被引入机器学习领域,用来评判分类、检测结果的好坏。

ROC曲线和 AUC (Area Uder ROC Curve)值常作为二分类学习器的性能指标。

ROC 曲线的横纵轴分别为 FPR 和 TPR:

  • FPR:负类样本中分类错误的样本比例。\(FPR = \frac{FP}{FP + TN}\)
  • TPR:正类样本中分类正确的样本比例。\(TPR = \frac{TP}{TP + FN}\)灵敏度,对应precision/recall中的recall 检出率)

灵敏度和特异度 是统计学中用来表征二项分类测试特征的数据,在统计学中也被称为统计分类,在医学中广为使用。与灵敏度度对偶的是特异度(Specificity,也称为真阴性率)。

混淆矩阵:

Groud Truth \ Prediction 预测-正 预测-负
正例 TP FN
负例 FP TN

绘制 ROC 曲线

对所有样本按预测 score 值从大到小排列,依次取每个样本的score值(去掉相等重复的)作为阈值threshold,将所有样本中score >= threshold 的样本预测为正样本,反之预测为负样本,计算得到不同阈值下的FPR、TPR。阈值取得越多,绘制出的ROC曲线越光滑。

计算过程简化为:

  • FPR:该样本之前(包括该样本)实际为负类的样本个数除总负类样本数;
  • TPR:该样本之前(包括该样本)实际为正类的样本个数除总正类样本数;

ROC曲线数据点的计算代码示例:

def roc_curve(scores, labels):
    """ 正类为1, 负类为 0,scores为正类的预测值
    """
    # 对样本标签按 scores 从大到小排序
    labels = [x for y, x in sorted(zip(scores, labels), reverse=True)]

    length = len(labels)
    pos_cnt = sum(labels)
    neg_cnt = length - pos_cnt
    fpr = [0] * (length + 1)
    tpr = [0] * (length + 1)
    for i in range(1, length+1):
        tp = sum(labels[:i])
        fp = i - tp
        fpr[i] = fp / neg_cnt
        tpr[i] = tp / pos_cnt
    return fpr, tpr

进行模型的性能比较时,若一个学习器A的ROC曲线被另一个学习器B的ROC曲线完全包住,则称B的性能优于A。若A和B的曲线发生了交叉,则不能断言哪个模型更好,此时就需要根据 ROC 曲线下的面积 AUC 值进行比较。AUC 值的计算可以根据 ROC 点进行近似估计。

AUC

计算AUC

AUC 最普遍的定义是 ROC 曲线下的面积。但另一种定义更常用,分别随机从正负样本集中抽取一个正样本,一个负样本,正样本的预测值大于负样本的概率。根据古典概率模型得出AUC的计算公式:

\[AUC={\sum \textbf{1}(score_{pos}>score_{neg})\over N_{pos}\cdot N_{neg}} \]

分母是正负样本总的组合数,分子是正样本预测值大于负样本的组合数。通常先对预测score进行从大到小排序,统计每个标签为正的样本后边的负样本的个数。

还可以用走网格法来记忆:从坐标原点开始,依次取从大到小排序后的样本,遇到标签为正的样本向上(y轴)走一步(步长:正样本总数的倒数),遇到标签为负的样本向右(x轴)走一步(步长:负样本总数的倒数)。走完之后数路线下与x轴之间的网格数,除以总网格数(原点终点与x轴y轴构成的矩形面积)就得到AUC。

每个正样本右边的网格都是负样本,因此将y轴上的每个正样本右侧的负样本数累加起来除以总网格数就是AUC。不难理解,这种走的过程和依次取每个样本的score值作为阈值进行曲线瞄点的过程是一样的。

代码示例:

def auc_score(scores, labels):
    """labels为0、1两种取值, scores为正类的预测值
       数每个正类之前有几个负类
       算 auc_score = 1 - n_auc
       # 从大到小排序,数每个正类之后的负类个数,更易理解,但需要两重循环
    """
    # 对样本标签按 scores 从大到小排序
    labels = [x for y, x in sorted(zip(scores, labels), reverse=True)]

    neg_cnt = 0
    n_auc = 0
    n = len(labels)
    for i in range(n):
        y_i = labels[i]
        neg_cnt += (1 - y_i)
        n_auc += y_i * neg_cnt
    n_auc /= 1.0 * (neg_cnt * (n - neg_cnt))
    return 1 - n_auc

AUC取值越大说明模型越可能将正样本排列在负样本前面. AUC还有一些统计特性: AUC等于随机挑选一个正样本和负样本时分类器将正样本排前面的概率; AUC和Wilcoxon Test of Ranks等价; AUC还和Gini系数有联系: Gini+1=2 x AUC。

ROC 曲线上哪一点对应的模型最好

不同性能的算法对应着 ROC 空间上不同的点,如果能够确定所有样例中真实正例的比例 \(\text{pos}\) 和真实负例的比例 \(\text{1 - pos}\),那么模型的精度就可以表示为 \(\rm{pos \cdot TPR + (1 - pos) \cdot (1 - FPR)}\)。根据这个数量关系可以得出,虽然不同的模型具有不同的 \(\text{TPR}\)\(\text{FPR}\),但它们的精度是可以相等的。在 ROC 空间上,这些精度相同的点都落在同一条斜率为 \(\text{(1 - pos) / pos}\),也就是负例与正例比值的直线上,这样的直线就被称为等精度线(iso-accuracy lines)。

由此,正例和负例的比例就可以作为已知的先验信息指导模型的选择。如果正例和负例的比例约为 2:1,那就可以在 ROC 空间上作一条斜率为 1/2 且经过 (0, 1) 的直线,并向右下方平行移动。当平移的直线与 ROC 曲线相交时,交点所对应的模型就是适用于这个先验信息的最优模型。

当然,这里所谓的“最优模型”是比较主观的,视优化目标的不同,“最优模型”的选择也不同,除了上述的选择方式,还可以考虑下列优化目标:

  • 相加:max(TPR+(1-FPR)) 或 \(\rm{\max( pos \cdot TPR + (1 - pos) \cdot (1 - FPR))}\)
  • 相乘:max(TPR(1-FPR)) 或 \(\rm{\max( pos \cdot TPR \cdot (1 - pos) \cdot (1 - FPR))}\)
  • 距离左上角(0,1)点的距离最小化

多分类与sklearn实现

在多分类任务中利用one vs rest方式计算各个类别的混淆矩阵,使用如下平均方式

  1. macro:分别求出每个类,再进行算术平均
    • 优点:直观、易懂,并且方便实现
    • 缺点:实际情况下可能不同类别拥有不同的重要性,宏平均会导致计算结果受不常用类别的影响
  2. weighted:加权累加每个类别
  3. micro:全局计算。将所有混淆矩阵累加在一起,然后计算TPR/FPR/AUC
  4. samples:适用于样本不平衡的情况,参考详解sklearn的多分类模型评价指标

sklearn包含roc与auc的实现:roc_curve()代码参考文档

示例代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc

y = np.array([1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0 ,1, 0, 0, 0, 1, 0, 1, 0])
scores = np.array([0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1])

fpr,tpr,threshold = roc_curve(y, scores, pos_label=1)
roc_auc = auc(fpr, tpr)

plt.figure()
plt.plot(fpr, tpr, 'r-o', label='ROC curve (area=%0.2f)' % roc_auc)
plt.grid()
plt.legend(loc="lower right")
plt.show()

GAUC(Group AUC)

AUC有时候不能满足推荐/广告系统中用户个性化的需求。如在推荐系统领域常为每个用户进行个性化推荐,排序顺序只对该用户有影响,而AUC的计算是全体样本排序后计算的一个值,反映了模型对于整体样本的排序能力

举例说明,假设现有两个用户甲和乙,一共有5个样本其中+表示正样本,-表示负样本。现有两个模型A和B,对5个样本的predict score按从小到大排序如下:

模型A 甲- 甲+ 乙- 甲+ 乙+
模型B 甲- 甲+ 甲+ 乙- 乙+

从以上模型预测结果可以看出,对于用户甲的样本,模型A和B对甲的正样本打分都比其负样本高;对于用户乙的样本也是如此,因此分别对于用户甲和乙来说,这两个模型的效果是一样好的。

但这两个模型的AUC的计算结果却相差较大:0.83、0.67. 这和辛普森悖论描述的一致。

用户推荐是一个个性化的场景,不同用户之间的商品排序不好放在一起比较。因此在计算指标时可以考虑分用户计算,消除全局排序的影响。阿里妈妈团队提出使用 **Group AUC **来作为另一个评价指标,先计算各个用户自己的AUC,然后加权平均,公式如下:

\[\rm{GAUC}={\sum_{u_i}(w_{u_i} \cdot \rm{AUC}_{u_i}) \over \sum_{u_i}w_{u_i}} \]

实际计算时,权重可以设为每个用户view或click的次数,并且会滤掉单个用户全是正样本或全是负样本的情况(一方面是消偏,提高置信度;另一方面这种样本导致分母为0无法计算AUC)。

RelaImpr-模型AUC相对值

RelaImpr用来衡量模型间的相对提升,采用模型AUC/GAUC减去随机猜测模型的AUC(0.5)的比值。

\[\rm{RelaImpr = \left(\frac{AUC(measured model) - 0.5}{AUC(base model) - 0.5} - 1 \right)} \times 100\% \]

Precision&Recall(P-R)

precison精确率:预测为正的样本中标签确实为正的比例。

recall召回率:标签为正的样本中被预测为正的比例。

ROC与P-R曲线对比

对比 P-R 图和 ROC 曲线会发现一个有趣的现象,那就是当类别的平衡性,也就是数据中正例和负例的比例发生改变时,这种变化不会给 ROC 曲线带来变化,却会让 P-R 曲线产生明显的改变,为什么会出现这种现象呢?

从混淆矩阵看,ROC的两个指标计算分别对应两个列,也就是不同类别真实输出上的准确率。只要算法不发生变化,那准确率就不会受到样本数的影响。

反过来,PR的两个指标在混淆矩阵里是一行一列,一个考察真实输出的准确率,一个考察预测输出的准确率。当数据类别不平衡导致各类真假正负例的数目改变时,这一行一列在计算比例时就没法保证相同的变化尺度,导致PR曲线变形。

F-score/Accuracy

综合考虑Precision和Recall的调和值(对精确率和召回率赋予不同的权重进行加权调和)。

\[F-Score=(1+\beta ^2)\cdot \frac {Precision\cdot Recall} {\beta^2\cdot Precision + Recall} \]

当β=1时,称为F1-score,这时,精确率和召回率都很重要,权重相同。当有些情况下,我们认为精确率更重要些,那就调整β的值小于1,如果我们认为召回率更重要些,那就调整β的值大于1。F2-score即为β=2时.

此外, 准确率和错误率也是常用的评估指标.

\[\begin{align} \rm{准确率(accuracy)} = {TP+TN\over TP+FP+FN+TN} \\ \rm{错误率(error\ rate)} = {FP+FN\over TP+FP+FN+TN} \end{align} \]

排序指标

Discounted Cumulative Gain(DCG)

如果将 P-R 指标用于排序,会有两个明显缺点:

  • 所有item只被分为相关和不相关两档,分类显然太粗糙。
  • 没有考虑位置因素。

DCG解决了 P-R 的这两个问题。对于一个关键词,所有的文档可以分为多个相关性级别,这里以\(rel_1,rel_2,...\)来表示。文章相关性对整个列表评价指标的贡献随着位置的增加而对数衰减,位置越靠后,衰减越严重。

NDCG 是针对测试集的一个排序评价指标。NDCG 这个指标的假设是,在一个排序结果里,相关信息要比不相关信息排得更高,而最相关信息需要排在最上面,最不相关信息排在最下面。任何排序结果一旦偏离了这样的假设,就会受到“扣分”或者说是“惩罚”。

NDCG 是考虑到评分的排序,需要从CG开始说起。CG(cumulative gain,累计增益)可以用于评价基于打分/评分的个性推荐系统。假设我们推荐k个物品,这个推荐列表的累计增益计算公式如下:

\[CG_k=\sum_{i=1}^k \text{rel}_i \]

\(\text{rel}_i\) 表示第 i 个物品的相关性或者评分。假设我们共推荐k个电影,\(\text{rel}_i\) 可以是用户对第i部电影的评分。

比如豆瓣给用户推荐了五部电影: M1,M2,M3,M4,M5,该用户对这五部电影的评分分别是:5, 3, 2, 1, 2

那么这个推荐列表的CG等于 CG5=5+3+2+1+2=13.

CG没有考虑推荐的次序,在此基础之后我们引入对物品顺序的考虑,就有了DCG(discounted CG),折扣累积增益。公式如下:

\[DCG_k=\sum_{i=1}^k \frac{2^{\text{rel}_i}-1}{\log_2(i+1)} \]

那么这个推荐列表的DCG等于

\[DCG_5=\frac{2^5-1}{\log_2 2}+\frac{2^3-1}{\log_2 3}+\frac{2^2-1}{\log_2 4}+\frac{2^1-1}{\log_2 5}+\frac{2^2-1}{\log_2 6}=31+4.4+1.5+0.4+1.2=38.5 \]

对于排序引擎而言,不同请求的结果列表长度往往不相同。当比较不同排序引擎的综合排序性能时,不同长度请求之间的DCG指标的可比性不高。DCG没有考虑到推荐列表和每个检索中真正有效结果个数,目前在工业界常用的是Normalized DCG(NDCG),它假定能够获取到某个请求的前p个位置的完美排序列表,这个完美列表的分值称为Ideal DCG(IDCG),NDCG等于DCG与IDCG比值。所以NDCG是一个在0到1之间的值。

完美结果下的DCG,即IDCG的定义如下:

\[\text{IDCG}_p=\sum_{i=1}^{|REL|}{2^{rel_i}-1 \over \log_2(i+1)} \]

|REL|代表按照相关性排序好的最多到位置p的结果列表。

\[NDCG_k=\frac{DCG_k}{IDCG_k} \]

继续上面的例子,如果相关电影一共有7部:M1,M2,M3,M4,M5,M6,M7,该用户对这七部电影的评分分别是:5, 3, 2, 1, 2 , 4, 0

把这7部电影按评分排序:5, 4, 3, 2, 2, 1, 0,这个情况下的完美DCG是:

\[IDCG_5=\frac{2^5-1}{\log_2 2}+\frac{2^4-1}{\log_2 3}+\frac{2^3-1}{\log_2 4}+\frac{2^2-1}{\log_2 5}+\frac{2^2-1}{\log_2 6}=31+9.5+3.5+1.3+1.2=46.5 \]

所以, \(NDCG_5 = \frac{DCG_5}{IDCG_5}=\frac{38.5}{46.5}=0.827\)

NDCG是0到1的数,越接近1说明推荐越准确。

Expected Reciprocal Rank(ERR)

与DCG相比,除了考虑位置衰减和允许多种相关级别(以R1,R2,R3...来表示)以外,ERR更进了一步,还考虑了排在文档之前所有文档的相关性。举个例子来说,文档A非常相关,排在第5位。如果排在前面的4个文档相关度都不高,那么文档A对列表的贡献就很大。反过来,如果前面4个文档相关度很大,已经完全解决了用户的搜索需求,用户根本就不会点击第5个位置的文档,那么文档A对列表的贡献就不大。

ERR的定义如下:

\[ERR=\sum_{r=1}^n{1\over r}\prod_{i=1}^{r-1}(1-R_i)R_r \]

参考

posted @ 2022-08-12 20:06  康行天下  阅读(330)  评论(0编辑  收藏  举报