开源AI食谱文档

使用Cleanlab检测文本数据集中的问题

Hugging Face's logo
加入Hugging Face社区

并获得增强型文档体验

开始使用

Open In Colab

使用Cleanlab检测文本数据集中的问题

作者:Aravind Putrevu

在本篇5分钟快速入门教程中,我们使用Cleanlab检测在线银行客户服务请求(文本)组成意图分类数据集中的各种问题。我们考虑了Banking77-OOS数据集的一个子集,其中包含1000个客户服务请求,根据其意图将其分类为10个类别(您可以在任何文本分类数据集上运行相同的代码)。Cleanlab自动识别我们数据集中不良的示例,包括错误标记的数据、超出范围的示例(异常值)或其他模棱两可的示例。在深入建模数据之前,请考虑过滤或更正此类不良示例!

本教程中我们将执行的操作概述

  • 使用预训练的Transformer模型从客户服务请求中提取文本嵌入

  • 在文本嵌入上训练一个简单的逻辑回归模型,以计算样本外预测概率

  • 使用这些预测和嵌入运行Cleanlab的Datalab审计,以识别诸如:标签问题、异常值和数据集中的近似重复等问题。

快速入门

已经从在现有标签集上训练的模型中获得了(样本外)pred_probs?也许您也有一些数值型features?运行以下代码以查找数据集中任何潜在的标签错误。

注意:如果在Colab上运行,可能需要使用GPU(选择:运行时 > 更改运行时类型 > 硬件加速器 > GPU)

from cleanlab import Datalab

lab = Datalab(data=your_dataset, label_name="column_name_of_labels")
lab.find_issues(pred_probs=your_pred_probs, features=your_features)

lab.report()
lab.get_issues()

安装所需依赖项

您可以使用pip安装本教程所需的所有软件包,如下所示

!pip install -U scikit-learn sentence-transformers datasets
!pip install -U "cleanlab[datalab]"
import re
import string
import pandas as pd
from sklearn.metrics import accuracy_score, log_loss
from sklearn.model_selection import cross_val_predict
from sklearn.linear_model import LogisticRegression
from sentence_transformers import SentenceTransformer

from cleanlab import Datalab
import random
import numpy as np

pd.set_option("display.max_colwidth", None)

SEED = 123456  # for reproducibility
np.random.seed(SEED)
random.seed(SEED)

加载并格式化文本数据集

from datasets import load_dataset

dataset = load_dataset("PolyAI/banking77", split="train")
data = pd.DataFrame(dataset[:1000])
data.head()
>>> raw_texts, labels = data["text"].values, data["label"].values
>>> num_classes = len(set(labels))

>>> print(f"This dataset has {num_classes} classes.")
>>> print(f"Classes: {set(labels)}")
This dataset has 7 classes.
Classes: {32, 34, 36, 11, 13, 46, 17}

让我们查看数据集中第 i 个示例

>>> i = 1  # change this to view other examples from the dataset
>>> print(f"Example Label: {labels[i]}")
>>> print(f"Example Text: {raw_texts[i]}")
Example Label: 11
Example Text: What can I do if my card still hasn't arrived after 2 weeks?

数据存储为两个 NumPy 数组

  1. raw_texts 以文本格式存储客户服务请求话语
  2. labels 存储每个示例的意图类别(标签)
自带数据 (BYOD)?

您可以轻松地将上述内容替换为您自己的文本数据集,并继续本教程的其余部分。

接下来,我们将文本字符串转换为更适合作为机器学习模型输入的向量。

我们将使用预训练 Transformer 模型中的数字表示作为我们文本的嵌入。 句子转换器 库提供了用于计算文本数据这些嵌入的简单方法。在这里,我们加载预训练的 electra-small-discriminator 模型,然后将我们的数据通过网络运行以提取每个示例的向量嵌入。

transformer = SentenceTransformer("google/electra-small-discriminator")
text_embeddings = transformer.encode(raw_texts)

我们随后的机器学习模型将直接对 text_embeddings 的元素进行运算,以便对客户服务请求进行分类。

定义分类模型并计算样本外预测概率

利用预训练网络执行特定分类任务的一种典型方法是添加线性输出层,并在新数据上微调网络参数。但是,这在计算上可能很密集。或者,我们可以冻结网络的预训练权重,并且只训练输出层,而无需依赖 GPU。在这里,我们通过在提取的嵌入之上拟合 scikit-learn 线性模型来方便地做到这一点。

为了识别标签问题,cleanlab 需要模型对每个数据点进行概率预测。但是,对于模型先前训练过的数据点,这些预测将是过拟合的(因此不可靠)。cleanlab 旨在仅用于样本外预测类概率,即在训练期间从模型中排除的数据点上。

在这里,我们使用带有交叉验证的逻辑回归模型,获取数据集每个示例的样本外预测类概率。确保 pred_probs 的列相对于类的排序顺序正确排序,对于 Datalab 而言,该顺序为:按类名进行词典排序。

model = LogisticRegression(max_iter=400)

pred_probs = cross_val_predict(model, text_embeddings, labels, method="predict_proba")

使用 Cleanlab 查找数据集中的问题

给定特征嵌入和从任何模型获得的(样本外)预测类概率,cleanlab 可以快速帮助您识别数据集中质量较低的示例。

在这里,我们使用 Cleanlab 的 Datalab 来查找数据中的问题。Datalab 提供了几种加载数据的方法;我们将简单地将训练特征和噪声标签包装在一个字典中。

data_dict = {"texts": raw_texts, "labels": labels}

审核数据所需的全部操作就是调用 find_issues()。我们将上面获得的预测概率和特征嵌入传递进来,但根据您感兴趣的问题类型,您不一定需要提供所有这些信息。提供的输入越多,Datalab 可以在数据中检测到的问题类型就越多。使用更好的模型生成这些输入将确保 cleanlab 更准确地估计问题。

lab = Datalab(data_dict, label_name="labels")
lab.find_issues(pred_probs=pred_probs, features=text_embeddings)

输出将如下所示

Finding null issues ...
Finding label issues ...
Finding outlier issues ...
Fitting OOD estimator based on provided features ...
Finding near_duplicate issues ...
Finding non_iid issues ...
Finding class_imbalance issues ...
Finding underperforming_group issues ...

Audit complete. 62 issues found in the dataset.

审核完成后,使用 report 方法查看结果

>>> lab.report()
Here is a summary of the different kinds of issues found in the data:

    issue_type  num_issues
       outlier          37
near_duplicate          14
         label          10
       non_iid           1

Dataset Information: num_examples: 1000, num_classes: 7


---------------------- outlier issues ----------------------

About this issue:
	Examples that are very different from the rest of the dataset 
    (i.e. potentially out-of-distribution or rare/anomalous instances).
    

Number of examples with this issue: 37
Overall dataset quality in terms of this issue: 0.3671

Examples representing most severe instances of this issue:
     is_outlier_issue  outlier_score
791              True       0.024866
601              True       0.031162
863              True       0.060738
355              True       0.064199
157              True       0.065075


------------------ near_duplicate issues -------------------

About this issue:
	A (near) duplicate issue refers to two or more examples in
    a dataset that are extremely similar to each other, relative
    to the rest of the dataset.  The examples flagged with this issue
    may be exactly duplicated, or lie atypically close together when
    represented as vectors (i.e. feature embeddings).
    

Number of examples with this issue: 14
Overall dataset quality in terms of this issue: 0.5961

Examples representing most severe instances of this issue:
     is_near_duplicate_issue  near_duplicate_score near_duplicate_sets  distance_to_nearest_neighbor
459                     True              0.009544               [429]                      0.000566
429                     True              0.009544               [459]                      0.000566
501                     True              0.046044          [412, 517]                      0.002781
412                     True              0.046044               [501]                      0.002781
698                     True              0.054626               [607]                      0.003314


----------------------- label issues -----------------------

About this issue:
	Examples whose given label is estimated to be potentially incorrect
    (e.g. due to annotation error) are flagged as having label issues.
    

Number of examples with this issue: 10
Overall dataset quality in terms of this issue: 0.9930

Examples representing most severe instances of this issue:
     is_label_issue  label_score  given_label  predicted_label
379           False     0.025486           32               11
100           False     0.032102           11               36
300           False     0.037742           32               46
485            True     0.057666           17               34
159            True     0.059408           13               11


---------------------- non_iid issues ----------------------

About this issue:
	Whether the dataset exhibits statistically significant
    violations of the IID assumption like:
    changepoints or shift, drift, autocorrelation, etc.
    The specific violation considered is whether the
    examples are ordered such that almost adjacent examples
    tend to have more similar feature values.
    

Number of examples with this issue: 1
Overall dataset quality in terms of this issue: 0.0000

Examples representing most severe instances of this issue:
     is_non_iid_issue  non_iid_score
988              True       0.563774
975             False       0.570179
997             False       0.571891
967             False       0.572357
956             False       0.577413

Additional Information: 
p-value: 0.0

标签问题

报告表明,cleanlab 在我们的数据集中识别出许多标签问题。我们可以使用 get_issues 方法查看哪些示例被标记为可能标记错误,以及每个示例的标签质量分数,指定 label 作为参数来关注数据中的标签问题。

label_issues = lab.get_issues("label")
label_issues.head()
is_label_issue label_score given_label predicted_label
0 False 0.903926 11 11
1 False 0.860544 11 11
2 False 0.658309 11 11
3 False 0.697085 11 11
4 False 0.434934 11 11

此方法返回一个数据框,其中包含每个示例的标签质量分数。这些数值分数介于 0 和 1 之间,分数越低表示示例越有可能标记错误。数据框还包含一个布尔列,指定每个示例是否被识别为存在标签问题(表示其可能标记错误)。

我们可以获取标记有标签问题的示例的子集,并按标签质量分数排序,以查找数据集中 5 个最有可能标记错误的示例的索引。

>>> identified_label_issues = label_issues[label_issues["is_label_issue"] == True]
>>> lowest_quality_labels = label_issues["label_score"].argsort()[:5].to_numpy()

>>> print(
...     f"cleanlab found {len(identified_label_issues)} potential label errors in the dataset.\n"
...     f"Here are indices of the top 5 most likely errors: \n {lowest_quality_labels}"
... )
cleanlab found 10 potential label errors in the dataset.
Here are indices of the top 5 most likely errors: 
 [379 100 300 485 159]

让我们回顾一些最有可能的标签错误。

在这里,我们显示了数据集中被识别为最有可能的标签错误的前 5 个示例,以及它们的给定(原始)标签和来自 cleanlab 的建议替代标签。

data_with_suggested_labels = pd.DataFrame(
    {"text": raw_texts, "given_label": labels, "suggested_label": label_issues["predicted_label"]}
)
data_with_suggested_labels.iloc[lowest_quality_labels]

上述命令的输出将如下所示

text given_label suggested_label
379 我计划进行的转账的汇率是从哪个特定来源提取的? 32 11
100 你能分享一下卡的追踪号码吗? 11 36
300 如果我需要兑现外币转账,那该怎么办? 32 46
485 我的货币兑换是否被多收了费用? 17 34
159 有没有办法在应用程序中查看我的卡? 13 11

这些是 cleanlab 在此数据中识别出的非常明显的标签错误!请注意,given_label 未能正确反映这些请求的意图,无论是谁制作此数据集,都犯了许多错误,在对数据建模之前必须解决这些错误。

异常值问题

根据报告,我们的数据集中包含一些异常值。我们可以通过 get_issues 查看哪些示例是异常值(以及一个量化每个示例在数据集中出现的典型程度的数值质量分数)。我们根据 cleanlab 的异常值质量分数对结果 DataFrame 进行排序,以查看数据集中最严重的异常值。

outlier_issues = lab.get_issues("outlier")
outlier_issues.sort_values("outlier_score").head()

输出将如下所示

is_outlier_issue outlier_score
791 True 0.024866
601 True 0.031162
863 True 0.060738
355 True 0.064199
157 True 0.065075
lowest_quality_outliers = outlier_issues["outlier_score"].argsort()[:5]

data.iloc[lowest_quality_outliers]

最低质量异常值的示例输出将如下所示

index text label
791 提取挂起是什么意思? 46
601 交易中收取 1 美元费用。 34
863 我的 ATM 取款仍在挂起 46
355 解释银行间汇率 32
157 丢失的卡已找到,想要将其放回应用程序 13

我们看到 cleanlab 已经识别出此数据集中似乎不是正确的客户请求的条目。此数据集中异常值似乎是超出范围的客户请求和其他与意图分类无关的无意义文本。仔细考虑此类异常值是否会对您的数据建模产生不利影响,如果会,请考虑将其从数据集中删除。

近似重复问题

根据报告,我们的数据集中包含一些近似重复的示例集。我们可以通过 get_issues 查看哪些示例是(近似)重复的(以及量化每个示例与其在数据集中最近邻的不同程度的数值质量分数)。我们根据 cleanlab 的近似重复质量分数对结果 DataFrame 进行排序,以查看数据集中最接近重复的文本示例。

duplicate_issues = lab.get_issues("near_duplicate")
duplicate_issues.sort_values("near_duplicate_score").head()

上述结果显示了 cleanlab 认为哪些示例是近似重复的(其中 is_near_duplicate_issue == True 的行)。在这里,我们看到示例 459 和 429 是近似重复的,示例 501 和 412 也是如此。

让我们查看这些示例以了解它们有多相似。

data.iloc[[459, 429]]

示例输出

index text label
459 我在国外购买了一些东西,但使用了错误的汇率。 17
429 我在海外购买了一些东西,但使用了错误的汇率。 17
data.iloc[[501, 412]]

示例输出

index text label
501 你使用的汇率非常糟糕。这不可能是官方的银行间汇率。 17
412 你使用的汇率很糟糕。这不可能是官方的银行间汇率。 17

我们发现这两组请求确实非常相似!在数据集中包含近似重复项可能会对模型产生意外影响,并且要注意不要将它们拆分到训练/测试集中。从常见问题解答了解有关处理数据集中近似重复项的更多信息。

非独立同分布问题(数据漂移)

根据报告,我们的数据集似乎不是独立同分布 (IID) 的。数据集的整体非 IID 分数(显示在下方)对应于统计检验的p 值,该检验用于确定数据集中样本的排序是否与其特征值之间的相似性相关。较低的p 值强烈表明数据集违反了 IID 假设,这是从数据集中产生的结论(模型)泛化到更大群体所需的关键假设。

p_value = lab.get_info("non_iid")["p-value"]
p_value

在这里,我们的数据集被标记为非 IID,因为行恰好按原始数据中的类别标签排序。如果我们记得在模型训练和数据分割之前打乱行,这可能是良性的。但是,如果您不知道为什么您的数据被标记为非 IID,那么您应该担心潜在的数据漂移或数据点之间意外的交互(它们的值可能在统计上不独立)。仔细考虑未来的测试数据可能是什么样子(以及您的数据是否代表您关心的总体)。您不应该在非 IID 测试运行之前打乱您的数据(这会使其结论无效)。

如上所示,cleanlab 可以自动筛选出数据集中最可能出现的问题,以帮助您更好地整理数据集以进行后续建模。使用此筛选列表,您可以决定是否修复这些标签问题或从数据集中删除无意义或重复的示例,以获得用于训练下一个机器学习模型的更高质量的数据集。cleanlab 的问题检测可以使用您最初训练的任何类型模型的输出运行。

Cleanlab 开源项目

Cleanlab 是一个标准的数据中心 AI 软件包,旨在解决凌乱的真实世界数据的质量问题。

请考虑为 Cleanlab Github 仓库加星,我们欢迎为该项目做出贡献

< > 在 GitHub 上更新