点击上方,选择星标或置顶,每天给你送干货!
阅读大概需要15分钟
跟随小博主,每天进步一丢丢
文 | JayLou娄杰(NLP算法工程师,信息抽取方向)
编 | 北大小才女小轶
美 | Sonata
在实际工作中,你是否遇到过这样一个问题或痛点:无论是通过哪种方式获取的标注数据,数据标注质量可能不过关,存在一些错误?亦或者是数据标注的标准不统一、存在一些歧义?特别是badcase反馈回来,发现训练集标注的居然和badcase一样?如下图所示,QuickDraw、MNIST和Amazon Reviews数据集中就存在错误标注。
为了快速迭代,大家是不是常常直接人工去清洗这些“脏数据”?(笔者也经常这么干~)。但数据规模上来了咋整?有没有一种方法能够自动找出哪些错误标注的样本呢?基于此,本文尝试提供一种可能的解决方案——置信学习。
本文的组织架构是:
那什么是置信学习呢?这个概念来自于ICML2020的一篇由MIT和Google联合提出的paper:《[Confident Learning: Estimating Uncertainty in Dataset Labels][1] 》。论文提出的置信学习(confident learning,CL)是一种新兴的、具有原则性的框架,以识别标签错误、表征标签噪声并应用于带噪学习(noisy label learning)。
原文链接:https://arxiv.org/abs/1911.00068 Arxiv访问慢的小伙伴也可以在订阅号后台回复关键词【0630】下载论文PDF。
笔者注:笔者乍一听「置信学习」挺陌生的,但回过头来想想,好像干过类似的事情,比如:在某些场景下,对训练集通过交叉验证来找出一些可能存在错误标注的样本,然后交给人工去纠正。此外,神经网络的成功通常建立在大量、干净的数据上,标注错误过多必然会影响性能表现,带噪学习可是一个大的topic,有兴趣可参考这些文献 https://github.com/subeeshvasu/Awesome-Learning-with-Label-Noise。
废话不说,首先给出这种置信学习框架的优势:
笔者注:置信学习找出的「标注错误的样本」,不一定是真实错误的样本,这是一种基于不确定估计的选择方法。
论文最令人惊喜的一点就是作者这个置信学习框架进行了开源,并命名为cleanlab,我们可以pip install cleanlab
使用。
我们要想找出错误标注的样本,通过使用cleanlab操作十分简单,我们仅仅需要提供两个输入,然后只需要1行code就可以找出标注数据中的错误:
from cleanlab.pruning import get_noise_indices
# 输入
# s:噪声标签
# psx: n x m 的预测概率概率,通过交叉验证获得
ordered_label_errors = get_noise_indices(
s=numpy_array_of_noisy_labels,
psx=numpy_array_of_predicted_probabilities,
sorted_index_method='normalized_margin', # Orders label errors
)
这个输入是啥?很简单,一个输入是原始的样本标签(由于这些标签可能存在错误,我们称之为「噪声标签」吧~),另一个输入就是通过对训练集交叉验证,来预测的每一个样本在不同标签类别下的概率,这是一个nXm的概率矩阵(n为数据集大小,m为标签类别总数)。
我们来看看cleanlab在MINIST数据集中找出的错误样本吧,是不是感觉很🐂~
如果你不只是想找到错误标注的样本,还想把这些标注噪音clean掉之后重新继续学习,那3行codes也可以搞定,这时候连交叉验证都省了~
from cleanlab.classification import LearningWithNoisyLabels
from sklearn.linear_model import LogisticRegression
# 其实可以封装任意一个你自定义的模型.
lnl = LearningWithNoisyLabels(clf=LogisticRegression())
lnl.fit(X=X_train_data, s=train_noisy_labels)
# 对真实世界进行验证.
predicted_test_labels = lnl.predict(X_test)
笔者注:上面虽然只给出了CV领域的例子,但置信学习也适用于NLP啊~此外,
cleanlab
可以封装任意一个你自定义的模型,以下机器学习框架都适用:scikit-learn, PyTorch, TensorFlow, FastText。
置信学习开源工具cleanlab
操作起来比较容易,但置信学习背后也是有着充分的理论支持的。事实上,一个完整的置信学习框架,需要完成以下三个步骤(如置信学习框架图所示):
接下来,我们对上述3个步骤进行详细阐述。
我们定义噪声标签为 ,即经过初始标注(也许是人工标注)、但可能存在错误的样本;定义真实标签为 ,但事实上我们并不会获得真实标签,所以通常是采取交叉验证对真实标签进行估计。此外,定义样本总数为 ,类别总数为 。
为了估计联合分布,共需要4步:
看到这里,也许你会问为什么要估计这个联合分布呢?其实这主要是为了下一步方便我们去clean噪声数据。此外,这个联合分布
其实能充分反映真实世界中噪声(错误)标签和真实标签的分布,随着数据规模的扩大,这种估计方法与真实分布越接近(原论文中有着严谨的证明,由于公式推导繁杂这里不再赘述,有兴趣的同学可以详细阅读原文~后文也有相关实验进行证明)。
看到这里,也许你还感觉公式好麻烦,那下面我们通过一个具体的例子来展示上述计算过程:
在得到噪声标签和真实标签的联合分布
,论文共提出了5种方法过滤错误样本。我们仍然以前面给出的示例进行说明:
上述这些过滤样本的方法在cleanlab
也有提供,我们只要提供2个输入、1行code即可clean错误样本:
import cleanlab
# 输入
# s:噪声标签
# psx: n x m 的预测概率概率,通过交叉验证获得
# Method 3:Prune by Class (PBC)
baseline_cl_pbc = cleanlab.pruning.get_noise_indices(s, psx, prune_method='prune_by_class',n_jobs=1)
# Method 4:Prune by Noise Rate (PBNR)
baseline_cl_pbnr = cleanlab.pruning.get_noise_indices(s, psx, prune_method='prune_by_noise_rate',n_jobs=1)
# Method 5:C+NR
baseline_cl_both = cleanlab.pruning.get_noise_indices(s, psx, prune_method='both',n_jobs=1)
在过滤掉错误样本后,根据联合分布
将每个类别i下的损失权重修正为 :其中.然后采取Co-Teaching[2]框架进行。
如上图所示,Co-teaching的基本假设是认为noisy label的loss要比clean label的要大,于是它并行地训练了两个神经网络A和B,在每一个Mini-batch训练的过程中,每一个神经网络把它认为loss比较小的样本,送给它其另外一个网络,这样不断进行迭代训练。
上面我们介绍完成置信学习的3个步骤,本小节我们来看看这种置信学习框架在实践中效果如何?在正式介绍之前,我们首先对稀疏率进行定义:稀疏率为联合分布矩阵、非对角单元中0所占的比率,这意味着真实世界中,总有一些样本不会被轻易错标为某些类别,如「老虎」图片不会被轻易错标为「汽车」。
上图给出了CIFAR-10中,噪声率为40%和稀疏率为60%情况下,真实联合分布和估计联合分布之间的比较,可以看出二者之间很接近,可见论文提出的置信学习框架用来估计联合分布的有效性;当然,论文也对联合估计有着严谨的推导证明。
上图给出了CIFAR-10中不同噪声情况和稀疏性情况下,置信学习与噪声学习中的其他SOTA方法的比较。例如在40%的噪声率下,置信学习比之前SOTA方法Mentornet的准确率平均提高34%。
论文还将提出置信学习框架应用于真实世界的ImageNet数据集,利用置信学习的PBNR方法找出的TOP32标签问题如上图所示,置信学习除了可以找出标注错误的样本(红色部分),也可以发现多标签问题(蓝色部分,图像可以有多个标签),以及本体论问题:绿色部分,包括“是”(比如:将浴缸标记为桶)或 “有”(比如:示波器标记为CRT屏幕)两种关系。
上图给出了分别去除20%,40%…,100%估计错误标注的样本后训练的准确性,最多移除200K个样本。可以看出,当移除小于100K个训练样本时,置信学习框架使得准确率明显提升,并优于随机去除。
cleanlab
可以很快速的帮你找出那些错误样本!可在分钟级别之内找出错误标注的样本。
接下来,让我们尝试将置信学习应用于自己的项目,找出那些“可恶”的数据噪声吧~
[1] Confident Learning: Estimating Uncertainty in Dataset Labels
[2] Co-teaching: Robust Training of Deep Neural Networks with Extremely Noisy Labels