机器学习中的评估指标

评估指标汇总

Posted by BY on March 18, 2019

机器学习评估指标是机器学习中很重要的一环,这里列一下常见的评估指标以及自己的一些理解。

ACC

这个用的最广的,就是预测正确率。

\[ACC = \frac{right}{all}\]

Precision

\[precision = \frac{TP}{TP + FP}\]

准确率,表示在预估的正例中,真正的正例的占比

Recall

\[recall = \frac{TP}{TP + FN}\]

召回率,表示在所有正例中,预估正确的正例的占比

AUC

AUC,具体计算方法这里不列了,这里主要说一下对AUC的一些理解,公式参见之前文章机器学习常见面试题

为什么AUC这么受欢迎呢?

计算方法

第一种计算方法是按照前面文章中说的,通过计算ROC曲线,然后积分求下面面积的方法,一般的书里都是这么讲的,它比较难理解且难以实现,我们看一种简单的。

首先,AUC是衡量排序能力的,就是说正负样本中,正样本在真实排序中排在负样本前面的概率,即公式为

\[\frac{正样本排在负样本前面的样本对数}{总样本数总对数}\]

那么,假设正样本数目为M,负样本数目为N,则

\[AUC = \frac{ \sum_{i \in positive} rank_i - \frac{M·(M+1)}{2} }{ M · N }\]

首先分母部分好理解,就是正样本数乘以负样本数,就是总样本数,分子部分我们想想,其实就是类似求逆序对,这里\(rank_i\)表示排序后正样本(label为1)的顺序号,比如下面样例中的7,6,3,2。拿7来说,相当于其他都是负样本的情况下样本对数,这样一来就把排在后面的正样本的部分也算进去了,所以在后面要减掉。分子部分为7 + 6 + 3 + 2 - (4 + 3 + 2 + 1),其实后面部分就是这四个的排列数为M · (M+1),则最终AUC为:

\[AUC = \frac{ 7 + 6 + \frac{5 + 4 + 3 + 2}{4} + \frac{5 + 4 + 3 + 2}{4} - \frac{4 * (4 + 1)}{2}}{4 * 3} = \frac {10} {12}\]
ID label score rank
A 1 0.8 7
B 1 0.7 6
C 0 0.5 5
D 0 0.5 4
E 1 0.5 3
F 1 0.5 2
G 0 0.3 1

计算代码为:

python
#!/usr/bin/env python3
import numpy as np
from sklearn.metrics import roc_auc_score

def calc_auc_simple(labels, scores):
    f = list(zip(scores, labels))
    rank = [val2 for val1, val2 in sorted(f, key = lambda x:x[0])]
    rankList = [i+1 for i in range(len(rank)) if rank[i] == 1]
    pos_cnt = np.sum(np.array(labels) == 1)
    neg_cnt = len(labels) - pos_cnt
    auc = (np.sum(rankList) - pos_cnt * (pos_cnt + 1) / 2.0) / (pos_cnt * neg_cnt)
    return auc

def calc_auc(labels, scores):
    f = list(zip(scores, labels))
    sort_f =  sorted(f, key = lambda x:x[0])
    sum_rank = 0.0
    for i in range(len(sort_f)):
        if sort_f[i][1] == 0:
            continue
        left = i
        right = i + 1
        temp = 0.0
        while left >= 0 and sort_f[i][0] == sort_f[left][0]:
            temp += (left + 1)
            left -= 1
        while right < len(sort_f) and sort_f[i][0] == sort_f[right][0]:
            temp += (right + 1)
            right += 1
        sum_rank += temp / (right - left - 1)
    pos_cnt = np.sum(np.array(labels) == 1)
    neg_cnt = len(labels) - pos_cnt
    auc = (sum_rank - pos_cnt * (pos_cnt + 1) / 2.0) / (pos_cnt * neg_cnt)
    return auc

if __name__ == '__main__':
    labels = [0, 1, 1, 0, 0, 1 ,1]
    scores = [0.3, 0.5, 0.5, 0.5, 0.5, 0.7, 0.8]
    print (calc_auc_simple(labels, scores))
    print (calc_auc(labels, scores))
    print 'sklearn AUC:',roc_auc_score(labels, scores)
理解

首先是它反应的是模型的排序能力,它不关心具体的打分Score的绝对值,只关心排序的相对顺序,比如AUC是0.75,我们说随机的选一个正样本和一个负样本,模型打分正样本高于负样本的概率是0.75。

另外,他对采样不敏感,在样本分布不变的情况下,正样本占比10%和占比50%计算的AUC结果差异不大,怎么解释呢?还是前面的例子,随机拿一个正样本,模型预估为score1,因为是随机采样,小于score1的负样本和大于score1的负样本比例不会变化,反之也是。

所以AUC反应的是模型预估样本的排序关系,正负样本的gap越大,AUC越大,如果正负样本完全分开,且特征充分,那么理论上AUC能达到1.0,但是这也仅仅是理想情况,那么我们为什正常线上AUC只有0.7呢?是因为在线上特征集合完全一致,但label不同的数据,学术上称作Bayes Error Rate。为什么要做很多特征工程的事情,就是因为我们想通过在这些数据集合中找到一些特征能够区分开这些样本。

现在有个问题,点击和转化/购买两个行为,一般谁的AUC更高?在AUC相同的情况下,那个的线上表现更好?

首先正常情况下点击的AUC比转化/购买的AUC低,原因是点击的成本更低,或者说决策成本更低,决策路径更短,看懂了稍微有点兴趣就会点击,可能是因为标题中一个词很吸引人或者刚好听朋友说过相关。但是购买/转化正好相反,需要付出的成本更大,决策路径更长,所以更能反应用户的真实兴趣。用前面的话说就是GAP更大,所以AUC更高。

但是相同AUC,点击会比转化/购买表现更好,首先点击的数据量更充足,模型训练更充分。另外转化/购买受场外印象因素较多,比如别人的建议,自己的预算,网上评测等,这些都是没有办法表示在模型中的。所以决策链路长,就会导致中间信息丢失的多,而线上可能更线上AUC表现越不好。

那么如果一个AUC高的模型上到线上反而表现不如老的AUC低的怎么办,首先第一个防止特征穿越,比如我们用请求时间序列类特征,或者用户的当日点击数之类,可以对比新老模型特征,一般问题出在特征上的可能性最大。

另外线上我们排序的时候,首先会出现一些训练样本中没有见过的新样本。另外线上预估只考虑当前用户的召回list中的顺序问题,而训练的时候我们是整个训练样本的顺序,所以会出现点击率很高的可能给任何用户预估都会score很高,但是有部分用户可能不喜欢甚至讨厌,对于这种情况阿里论文中曾经设计过一个group AUC,意思是只考虑每个用户的排序AUC的均值,公式如下。

\[GAUC = \frac{\sum_{i=1}^n w_i \cdot AUC_i}{\sum_{i=1}^n w_i} = \frac{\sum_{i=1}^n impression_i \cdot AUC_i}{\sum_{i=1}^n impression_i}\]

其中\(impression_i\)表示第i个用户的展示次数,\(AUC_i\)表示第i个用户的AUC,有时候也称作uAUC。

NDCG

可能大家接触比较多的是MAP,MAP考虑的是0和1的排序。而NDCG则是考虑到评分的排序。

说到NDCG就需要从CG开始说起。

CG(cumulative gain,累计增益)可以用于评价基于打分/评分的个性推荐系统。假设我们推荐k个物品,这个推荐列表的\(CG_k\)计算公式如下:

\[CG_k = \sum_{i=1}^k rel_i\]

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

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

5, 3, 2, 1, 2

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

\(CG_5\)=5+3+2+1+2=13.

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

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

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

5, 3, 2, 1, 2

那么这个推荐列表的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没有考虑到推荐列表和每个检索中真正有效结果个数,所以最后我们引入NDCG(normalized discounted CG),顾名思义就是标准化之后的DCG。

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

其中IDCG是指ideal DCG,也就是完美结果下的DCG。

继续上面的例子,如果相关电影一共有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说明推荐越准确。