更多NLP文章,在github:
https://github.com/DA-southampton/NLP_ability
最近项目遇到了类别不平衡的问题,看了一些方法,做了一些实验,记录如下。一家之言,不对之处,尽请指正。
我自己把处理类别不平衡问题分为两种方法:从根源解决和从表面缓解。
这个想法一般来说是放在最后,不过我放在开头,引起大家重视,我就吃了这个亏。
就是你试了各种方法,比如后面会提到的欠采样过采样等,仍然发现auc上不去,这个时候,可以去考虑一下是不是标注数据有问题。
标注问题其实是整个机器学习或者深度学习的基础,不仅仅是出现在类别不平衡,甚至可以说和类别不平衡没啥关系,囧。
对于这个方法,我其实一直都有疑虑。
一般来说,增加标注数据的同时,正反例数据都会增加,那么增加完标注数据之后仍然是个不平衡的数据集,数据分布没有发生变化。
这样会不会对模型提升效果,这一点我是存疑的。
我自己的方法是增加标注数据之后,清洗负样本的噪声数据,降低平衡比例。
比如欠采样过采样,代价敏感学习这种,给我的感觉都是在表面解决这个类别不平衡的问题,也就是在原来的基础上稍稍提升一点点的表现。
这个时候,如果你可以找到一个很好的特征(或者说多个特征),把原来混为一谈的两类,很好的分开,那么你的两个类别再不平衡也没有问题,你也可以获得很好的效果。
所以去想特征吧。
对于这两种采样方式,一个非常重要的点在于我们是在训练集上做采样,测试集上一定要单独留出来不能做任何更改。
就是把多样本变少,一般来说可以随机欠采样。
但是我觉得需要考虑这么一个问题,欠采样是有很大缺点的,首先就是减少了数据信息,这点毋庸置疑。
还有一点是,欠采样改变了数据分布,模型在此时的数据上表现的很好,但是遇到了真实数据,这个时候是真实的数据分布,模型表现会一塌糊涂。
所以,不仅仅需要欠采样,还需要欠采样n份,做n个模型,集成预测。只不过,这样开销就大了。
除了随机欠采样,我这边在项目中使用了一个小trick可以分享给大家,就是注意去看特征的含义,可以通过特征,特定的去除一些负样本。
比如可以根据发博时间去除近三个月未发博的负样本。在线上样本中,我也会做同样的处理,因为这些负样本本就不再我这个项目的考虑范围之内。这样训练数据分布和真实样本的数据分布并没有发生变化,还减少了负样本的数量。
更准确的说,这个trick是在减少样本中的噪声样本。
过采样就是把少样本变多,两个方法:复制和生成
生成一般就是使用SMOTE方法,看到很多文章说有用,我这里基本没用。
这里还是要说一下开始写的前提,测试集不能变化!!!
如果先做SMOTE,在划分测试集,效果很好,但是这没用,我是要上线的,是面临真实数据的。
两者本质在惩罚把少样本分错的行为,让模型更多的关注少样本。
一般来说,这个只能是有微小提升。
类别不平衡,最好就把数量少的作为正类,后期各方面会少很多麻烦。
具体看一下混淆矩阵,看一下每个类别的f1如何,也可以看一下ROC曲线以及对应的AUC,ROC曲线不受样本不平衡的影响。
总结文章重点:
- 对于类别不平衡,数据是根本,特征很关键,至于别的方法,没啥用。
- 在使用采样的时候,需要注意测试集需要单独留出来不做任何处理,因为之后模型需要处理的是线上数据
- 类别不平衡,最好就把数量少的作为正类,后期各方面会少很多麻烦
分类中解决类别不平衡问题 - Microstrong的文章 - 知乎 https://zhuanlan.zhihu.com/p/36381828
如何处理数据中的「类别不平衡」? - 微调的文章 - 知乎 https://zhuanlan.zhihu.com/p/32940093
严重数据倾斜文本分类,比如正反比1:20~100,适合什么model,查准一般要做到多少可以上线? - 微调的回答 - 知乎 https://www.zhihu.com/question/59236897/answer/500338632
机器学习不平衡数据处理参考 - 小方哥哥的文章 - 知乎 https://zhuanlan.zhihu.com/p/68099299
样本不均衡的处理(Xgboost,pytorch及tensorflow) - quidli的文章 - 知乎 https://zhuanlan.zhihu.com/p/138728186