# ML碎碎念

ML碎碎念

[对偶学习：一种新的机器学习范式](http://weibo.com/ttarticle/p/show?id=2309404050111117306404)

## 正负样本不均衡

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

解决：\
1\. 采样，采出均衡的样本\
2\. 加权，对分错加权？对负类样本加权？

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

["处理不均衡数据 (机器学习)"](https://zhuanlan.zhihu.com/p/24814085)\
[从重采样到数据合成：如何处理机器学习中的不平衡分类问题？](https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==\&mid=2650724464\&idx=1\&sn=1f34358862bacfb4c7ea17c864d8c44d)

1.  更多数据 &#x20;

    更换评价方式，比如F1 &#x20;

    重组数据，使之平衡。比如重采样，或者砍掉多的那类数据   &#x20;

    使用其他算法，比如决策树  &#x20;

    修改算法，比如sigmoid的阈值 &#x20;

## 分类器的评估

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

### recall和precision

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

* TP: 预测为正， 现实为正 &#x20;
* FP: 预测为正， 现实为负 &#x20;
* FN: 预测为负， 现实为正 &#x20;
* TN: 预测为负， 现实为负 &#x20;

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

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

### ROC

[ROC和AUC介绍以及如何计算AUC](http://alexkong.net/2013/06/introduction-to-auc-and-roc/) （感谢此人，写的如此清晰）\
[ROC曲线-阈值评价标准](http://blog.csdn.net/abcjennifer/article/details/7359370)

> 在一个二分类模型中，对于所得到的连续结果，假设已确定一个**阀值**，比如说 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\_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
$$

总的样本对： $$C_M^1 * C_N^1 = M*N$$\
故AUC值就是：$$(sum(rank\_i) - M(M+1)/2) / (M*N)$$

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

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

![](https://2270971654-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7DcNFhVrwIk3Tks_pB%2Fsync%2F0de49affc47d58871a3ddaee66858e9ea73a6004.png?generation=1589383934832473\&alt=media)

> 图来自张方宇

**AUC与Gini系数的关系**

$$Gini=2×AUC−1$$

![](https://2270971654-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7DcNFhVrwIk3Tks_pB%2Fsync%2Fe1a7837e274b866e57cba6f1818e7b0226f26693.png?generation=1589383934764056\&alt=media)

> 图来自欧阳若飞

### 直接使用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指标含义的理解](http://blog.csdn.net/dinosoft/article/details/43114935) ，或者用 scikit-learn/sklearn/metrics/ranking.py 。

[机器学习和统计里面的auc怎么理解？](https://www.zhihu.com/question/39840928)\
[One-Pass AUC Optimization](http://cs.nju.edu.cn/zhouzh/zhouzh.files/publication/aij16opauc.pdf)

[机器学习模型评价(Evaluating Machine Learning Models)-主要概念与陷阱](http://blog.csdn.net/heyongluoyao8/article/details/49408319)\
[分类之性能评估指标](http://blog.csdn.net/dream_angel_z/article/details/50867951)

[ROC Analysis](http://mlwiki.org/index.php/ROC_Analysis)

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

### 需要多少训练样本

当训练样本的数量与模型参数数量的比率达到10:1之后，模型得分基本稳定在0.85，该比率便可以作为良好性能模型的一种定义。\
[数据模型需要多少训练数据](http://www.afenxi.com/post/5559)

### 交叉检验和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/](http://11031509.blog.51cto.com/11021509/1726995/)

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