ML碎碎念

ML碎碎念

对偶学习:一种新的机器学习范式

正负样本不均衡

比如训练集中90%都是正类样本,(这尼玛要是所有的都测为正类,准确率也有90%),这样会容易导致模型会认为全部都是正类?因为错分惩罚太小?

解决: 1. 采样,采出均衡的样本 2. 加权,对分错加权?对负类样本加权?

知乎上观点: 机器学习的训练数据不是看它分布均不均衡,而是看它符不符合原来的分布。如果符合原来的分布,那么训练误差最小化也就意味着整体分布误差的最小化,也就没有必要进行均衡。

"处理不均衡数据 (机器学习)" 从重采样到数据合成:如何处理机器学习中的不平衡分类问题?

  1. 更多数据

    更换评价方式,比如F1

    重组数据,使之平衡。比如重采样,或者砍掉多的那类数据

    使用其他算法,比如决策树

    修改算法,比如sigmoid的阈值

分类器的评估

评估标准有:分类精度,信息检索领域的recall和precision。 但是在ML中常遇到样本分布不均衡,于是提出了新的评价模型:ROC

recall和precision

对于数据测试结果有下面4种情况:

  • TP: 预测为正, 现实为正

  • FP: 预测为正, 现实为负

  • FN: 预测为负, 现实为正

  • TN: 预测为负, 现实为负

精准率precision: TP/ (TP+FP) 召回率recall: TP/(TP + FN)

F1 score=2×recall×precisionrecall+precision\text{F1 score} = \frac{ 2 \times recall \times precision}{ recall + precision}

ROC

ROC和AUC介绍以及如何计算AUC (感谢此人,写的如此清晰) ROC曲线-阈值评价标准

在一个二分类模型中,对于所得到的连续结果,假设已确定一个阀值,比如说 0.6,大于这个值的实例划归为正类,小于这个值则划到负类中。如果减小阀值,减到0.5,固然能识别出更多的正类,也就是提高了识别出的正例占所有正例 的比类,即TPR,但同时也将更多的负实例当作了正实例,即提高了FPR。为了形象化这一变化,在此引入ROC,

ROC曲线可以用于评价一个分类器。

Roc曲线和lift曲线。 Lift曲线侧重于命中率,而不是广撒网,拼命中数。因为的广撒网的广告成本很高。

AUC

AUC (area under curves) 指的是 ROC (receiver operating characteristic)曲线下的面积,该指标能很好的概括不平衡样本分类器的性能。ROC曲线的横轴是FPR (false positive rate 假阳性率,即判断为正例但实际为负例的比例),纵轴是TPR(true positive rate 真阳性率,即判断为正例且实际也为正例的比例)。ROC曲线只对二分分类问题有效。

对某个分类器,我们可以根据其在测试样本上的表现得到一个TPR和FPR点对,构成ROC平面上的一点。调整这个分类器使用的阈值,这样就可以得到一个经过(0,0), (1,1)的曲线,这就是分类器的ROC曲线。其通常的AUC的值介于0.5到1.0之间,较大的AUC代表了较好的performance 。

阀值:比如logistic 回归输出是[0,1]之间的连续值,这个值表示用户点击某广告的概率,这里就涉及一个取舍问题了,这个概率值大于多少归为正类。假如确定一个阀值,比如说 0.6,大于这个值的实例划归为正类,小于这个值则划到负类中,那么根据这个阈值0.6能算出一对TPR和FPR来。

重要一点,AUC跟wilcox-mann-witney test是等价的。假设分类器的输出是样本属于正类的score(置信度),则AUC的物理意义是,任取一对(正负)样本,模型把这一对都区分正确(正样本的预估值比负样本大就算对了)的概率,(正样本的score大于负样本的score的概率?)。具体做法是统计下所有的M_N(M为正类样本的数目,N为负类样本的数目) 个正负样本对中,有多少组中正类样本的score大于负类样本的score。当二元组中正负样本的score相等的时候按照0.5计算。然后除以M_N 。

还有个复杂度小点的算法。先按score对样本排序,然后令最大score对应的样本的rank为n (n=M+N),第二大的score对应的样本的rank为n-1 ,以此类推,那么对于正样本中rank最大的样本,rank_max,有M-1个其他正样本比他的score小,那么就有(rank_max-1)-(M-1) 个负样本比他的score小。则所有正样本的score大于负样本score的个数为sum(正样本的rank) – M(M+1)/2,最后得到的正样本score大于负样本的概率为(sum(正样本的rank) – M(M+1)/2)/(M*N)。

详细过程

M为正类样本的数目,N为负类样本的数目 按score降序排列,但是第一个,即score最大的rank记为n,则最后一个,即score最小的rank记为1.

最大的正例样本rank为rank_max ,则其后还有rank_max-1个位置,则有(rank_max-1)-(M-1) 个负样本比他的score小。 则该正例样本可以和其后的(rank_max-1)-(M-1) 个负样本组成 (rank_max-1)-(M-1) 个 正样本score大于负样本序对。

score第二大的正例样本rank为rank_NO2 ,则其后还有rank_NO2-1个位置,则有(rank_NO2-1)-(M-2) 个负样本比他的score小。同理,可以得到(rank_NO2-1)-(M-2) 个正样本score大于负样本序对。

依次类推,总正样本score大于负样本序对数为:

(rank_max1)(M1)+(rank_NO21)(M2)+(rank_NO31)(M3)+...+(rank_min1)+=sum(rank_i)MM(M1)/2=sum(rank_i)M(M+1)/2(rank\_max-1)-(M-1) + \\ (rank\_NO2-1)-(M-2) + \\ (rank\_NO3-1)-(M-3) + \\ ... + \\ (rank\_min-1) + \\ = sum(rank\_i) - M - M(M-1)/2 \\ = sum(rank\_i) - M(M+1)/2

总的样本对: CM1CN1=MNC_M^1 * C_N^1 = M*N 故AUC值就是:(sum(rank_i)M(M+1)/2)/(MN)(sum(rank\_i) - M(M+1)/2) / (M*N)

从这个细节可以看出,这就是文档对的排序。所以xgboost使用AUC最为分类的loss function时,用的是pairwise。

如何理解AUC等价于 一对正负样本,正样本大于负样本的概率

图来自张方宇

AUC与Gini系数的关系

Gini=2×AUC1Gini=2×AUC−1

图来自欧阳若飞

直接使用AUC作为分类的优化目标

#!/usr/local/bin/python  

def scoreAUC(labels,probs):  
    i_sorted = sorted(range(len(probs)),key=lambda i: probs[i], reverse=True)  
    auc_temp = 0.0  
    TP = 0.0  
    TP_pre = 0.0  
    FP = 0.0  
    FP_pre = 0.0  
    P = 0;  
    N = 0;  
    last_prob = probs[i_sorted[0]] + 1.0  

    for i in range(len(probs)):  
        if last_prob != probs[i_sorted[i]]:   
            auc_temp += (TP+TP_pre) * (FP-FP_pre) / 2.0          
            TP_pre = TP  
            FP_pre = FP  
            last_prob = probs[i_sorted[i]]  
        if labels[i_sorted[i]] == 1:  
            TP = TP + 1  
        else:  
            FP = FP + 1  
    auc_temp += (TP+TP_pre) * (FP-FP_pre) / 2.0  
    auc = auc_temp / (TP * FP)  
    return auc  

def read_file(f_name):  

    f = open(f_name)  
    labels = []  
    probs = []  
    for line in f:  
        line = line.strip().split()  
        try:  
            label = int(line[2])  
            prob = float(line[3])  
        except ValueError:  
            # skip over header  
            continue  
        labels.append(label)  
        probs.append(prob)  
    return (labels, probs)  


def main():  
    import sys  
    if len(sys.argv) != 2:  
        print("Usage: python scoreKDD.py file")  
        sys.exit(2)  
    labels, probs = read_file(sys.argv[1])  

    auc = scoreAUC(labels, probs)  
    print("%f" % auc)  
if __name__=="__main__":  
    main()

代码来自 auc指标含义的理解 ,或者用 scikit-learn/sklearn/metrics/ranking.py 。

机器学习和统计里面的auc怎么理解? One-Pass AUC Optimization

机器学习模型评价(Evaluating Machine Learning Models)-主要概念与陷阱 分类之性能评估指标

ROC Analysis

如果目标数据只有轻微的不平衡,用roc等,但是极端不平衡,可以用SMOTE采样稍微均衡下。

需要多少训练样本

当训练样本的数量与模型参数数量的比率达到10:1之后,模型得分基本稳定在0.85,该比率便可以作为良好性能模型的一种定义。 数据模型需要多少训练数据

交叉检验和AB测试

调参数需要用预测效果来比较还坏,有人可能会问,那该如何测试才能比较客观的检验参数甚至模型的有效性?达观数据的测试方法主要有两种:离线测试和在线测试。离线测试时我们只有训练数据,一般会采用学术界常用的交叉验证方法。如图9所示,我们将训练数据平均分为n份,在这n份数据上进行n次循环,每次取其中一份作为检验集(Validation Set),其他n-1份作为训练集(Training Set)。最后对n次预测的结果求平均,以平均得分来对比不同的参数和模型。n一般取5、10或者20。

离线测试得到满意的性能提升之后,就可以进行在线测试。离线测试效果好,并不意味着上线就能取得满意效果。在线测试采用工业界广泛使用的AB测试,首先我们会从线上切一小部分流量(B流量)给新模型、新参数,将效果和使用原先的模型和参数的主流量(A流量)进行对比,如果效果有所提升,再增加B流量的比例。测试通过了就可以全流量上线。

http://11031509.blog.51cto.com/11021509/1726995/

https://zhuanlan.zhihu.com/p/24825503 【机器学习】Cross-Validation(交叉验证)详解

Last updated