LLE 简介

社区文章 发布于 2024 年 2 月 1 日

导言

在过去几周里,我一直对应用于法语的 NER 任务很感兴趣。你知道吗?我遇到了 LLE:漏洞无处不在。
我想知道这是否是法语或 NER 任务独有的现象,所以我决定从 Hugging Face Hub 下载数百个数据集,以评估它们的质量。而你不会喜欢下面读到的内容。

image/png


方法

HF Hub 上有超过 10 万个数据集,很难对它们全部进行评估。因此,在我这个小实验中,为了快速获得结果(我只花了 20 小时),我设定了一个有限的框架。具体来说,我专注于“规范”数据集,即不属于 Hub 上任何组织的数据集(这正在改变!),在这些数据集中,我选择了行数小于 1M 的数据集,以便快速下载和分析,最后我专注于 NLP。

在这些数据集中,我排除了那些需要从 Hub 以外的外部来源手动下载数据的、受门槛限制的以及没有测试分割的数据集(否则计算漏洞就没有意义了)。

最终,总共分析了 596 个数据集

下面,我将使用 conll2003 数据集来说明我如何判断数据集中是否存在漏洞。

dataset = load_dataset("conll2003")

def concatenate_columns(example):
    return {'concatenated_column': str(example['tokens'])}
dataset = dataset.map(concatenate_columns)

train_inputs = dataset["train"]["concatenated_column"]
val_inputs = dataset["validation"]["concatenated_column"]
test_inputs = dataset["test"]["concatenated_column"]

leakage_train = set(train_inputs).intersection(set(test_inputs))
leakage_validation = set(val_inputs).intersection(set(test_inputs))

print("Leakage between train split and test split:",len(leakage_train))
print("Leakage between validation split and test split:",len(leakage_validation))
print("Duplicated lines in the train split:", len(train_inputs) - len(set(train_inputs)))
print("Duplicated lines in the validation split:", len(val_inputs) - len(set(val_inputs)))
print("Duplicated lines in the test split:", len(test_inputs) - len(set(test_inputs)))

返回的代码

Leakage between train split and test split: 78
Leakage between validation split and test split: 25
Duplicated lines in the train split: 1350
Duplicated lines in the validation split: 180
Duplicated lines in the test split: 269

这里我们可以看到,除了计算训练集和测试集之间的漏洞以及验证集和测试集之间的漏洞之外,我还计算了每个分割中重复行的数量。
我还没有计算训练集和验证集之间的漏洞,所以这可能是一个遗漏。

实际上,我不打印结果,而是直接将其存储在数据框中,您可以在下面找到它。但我也计算并存储了测试集中有偏差的数据的百分比,即(训练集和测试集之间的漏洞 + 验证集和测试集之间的漏洞 + 测试集中重复的行)/ 测试集长度。
在 Conll2003 的上下文中,这给出了 (78+25+269)/3453*100 = 10.77%。
显然,除非进行修正,否则此数据集不应用于基准测试。

请注意,我接下来将完全重复相同的操作,但除了仅分析将提供给模型的输入外,我还查看了标签

dataset = load_dataset("conll2003")

def concatenate_columns(example):
    return {'concatenated_column': str(example['tokens'])+" "+str(example['ner_tags'])}
dataset = dataset.map(concatenate_columns)

train_inputs = dataset["train"]["concatenated_column"]
val_inputs = dataset["validation"]["concatenated_column"]
test_inputs = dataset["test"]["concatenated_column"]

leakage_train = set(train_inputs).intersection(set(test_inputs))
leakage_validation = set(val_inputs).intersection(set(test_inputs))

print("Leakage between train split and test split:",len(leakage_train))
print("Leakage between validation split and test split:",len(leakage_validation))
print("Duplicated lines in the train split:", len(train_inputs) - len(set(train_inputs)))
print("Duplicated lines in the validation split:", len(val_inputs) - len(set(val_inputs)))
print("Duplicated lines in the test split:", len(test_inputs) - len(set(test_inputs)))

返回的代码

Leakage between train split and test split: 73
Leakage between validation split and test split: 23
Duplicated lines in the train split: 1348
Duplicated lines in the validation split: 179
Duplicated lines in the test split: 266

您可以看到这些数字与前一种情况略有不同。我也将这些数字保存在最终的数据框中。我在这里最感兴趣的是计算两种情况之间的差异,因为这将突出显示是否存在漏洞或重复,以及数据中的注释问题(对于训练集和验证集,无法说明测试集)。
在 Conll2003 的上下文中,这给出了 abs(78-73+25-23) = 8。

然后,将上述过程应用于所有考虑的数据集。


结果

数据展示

所有结果都已集中到一个数据集中,您可以在 Hugging Face Hub 上找到。

image/png
查看 Hugging Face 查看器,让它不那么刺眼

数据集中的列应按以下方式解释:

  • dataset_name:分析的数据集名称。如果名称中包含逗号,则表示该数据集包含多个子集。例如,glue,sst2表示正在分析 gluesst2 子集。如果名称中包含括号,则表示我们只分析括号内的标签。这是因为一个数据集可能包含多列可用作标签(可能用于多个不同任务)。例如,如果我们以 conll2003 为例,它包含 ner_tagspos_tags 两列,它们都是标记分类任务,但一个是 NER,另一个是 POS。因此,上述代码的结果将出现在 conll2003(ner_tags) 行中,以区别于 conll2003(pos_tags)
  • text_leaks_train_wrt_test:训练集与测试集之间的漏洞数量,仅考虑将提供给模型的输入。对于 conll2003(ner_tags),列值为 78。
  • text_leaks_validation_wrt_test:验证集与测试集之间的漏洞数量,仅考虑将提供给模型的输入。对于 conll2003(ner_tags),列值为 25。
  • text_duplication_train:训练集中数据重复的数量,仅考虑将提供给模型的输入。对于 conll2003(ner_tags),列值为 1350。
  • text_duplication_validation:验证集中数据重复的数量,仅考虑将提供给模型的输入。对于 conll2003(ner_tags),列值为 180。
  • text_duplication_test:测试集中数据重复的数量,仅考虑将提供给模型的输入。对于 conll2003(ner_tags),列值为 269。
  • text_test_biased:测试集中偏差数据的百分比,即 text_leaks_train_wrt_testtext_leaks_valid_wrt_testtext_duplication_test 的值之和除以测试集长度。对于 conll2003(ner_tags),列值为 10.049%。
  • text_and_label_leaks_train_wrt_test:训练集与测试集之间的漏洞数量,考虑输入和将提供给模型的标签的串联。对于 conll2003(ner_tags),列值为 73。
  • text_and_label_leaks_validation_wrt_test:验证集与测试集之间的漏洞数量,考虑输入和将提供给模型的标签的串联。对于 conll2003(ner_tags),列值为 23。
  • text_and_label_duplication_train:训练集中数据重复的数量,考虑输入和将提供给模型的标签的串联。对于 conll2003(ner_tags),列值为 1348。
  • text_and_label_duplication_validation:验证集中数据重复的数量,考虑输入和将提供给模型的标签的串联。对于 conll2003(ner_tags),列值为 179。
  • text_and_label_duplication_test:测试集中数据重复的数量,考虑输入和将提供给模型的标签的串联。对于 conll2003(ner_tags),列值为 179。
  • text_and_label_test_biased:测试集中偏差数据的百分比,即 text_and_label_leaks_train_wrt_testtext_and_label_leaks_valid_wrt_testtext_and_label_duplication_test 的值之和除以测试集长度。对于 conll2003(ner_tags),列值为 9.818%。
  • difference_annotation_in_train_and_validation_splits:训练集 text_leaks_train_wrt_testtext_and_label_leaks_train_wrt_test 以及验证集之间的注释差异。对于 conll2003(ner_tags),列值为 8。

最后,请注意,如果单元格包含术语“NR”,则表示计算不相关(实际上,根本不可能)。最常见的情况是数据集只有训练集和测试集。例如,无法计算 text_duplication_val 列,因此显示“NR”。

观察

现在我们已经展示了数据,让我们看看我们得到了什么。

让我们从训练集和验证集开始

分割 泄漏(文本) 泄漏(文本和标签) 重复(文本) 重复(文本和标签)
训练集 54.530% 46.477% 73.322% 69.295%
验证集* 48.544% 39.806% 55.922% 55.922%

*根据非“NR”单元格计算

我们可以看到,在分析的数据集中,有训练集的 46.5% 以上存在泄漏,有验证集的 39.8% 存在泄漏。
同时,在分析的数据集中,有训练集的 69.3% 存在重复数据,有验证集的 55.9% 存在重复数据。


我们继续看测试集

分割 重复(文本) 重复(文本和标签) 偏差(文本) 偏差(文本和标签)
测试 56.544% 50.503% 66.611% 60.570%

超过一半的测试集包含重复数据,60% 包含偏差(重复或泄漏,或两者兼有)。


因此,我们发现大多数数据集在其测试数据集中都包含偏差。但是这些数据集只是轻微的偏差(例如小于 0.1%,这几乎不会影响基准测试),还是相反,是大量的偏差(例如 10%,这将使基准测试毫无意义)?下表提供了更详细的信息。

测试集中允许的偏差百分比 测试集中至少包含指定偏差百分比的数据集百分比
0.1 61.242
0.2 57.215
0.3 52.852
0.4 49.664
0.5 45.638
0.6 42.953
0.7 41.443
0.8 39.597
0.9 35.906
1 34.564
1.5 27.517
2 24.161
2.5 22.819
3 21.141
4 19.631
5 18.456
10 13.926
20 9.228
30 7.718
40 7.215
50 6.040
60 5.201
70 4.362
80 4.195
90 3.188

最后,我们怀疑 33.054% 的数据集可能包含注释问题。


结论与展望

本实验的目的是快速确定 Hugging Face Hub 上某些数据集的质量。
似乎没有重复或泄漏的数据集并非大多数情况。

需要进行更实质性且耗时的工作。
首先,需要分析更多数据集以完善这一初步情况。
其次,必须通过删除重复数据和泄漏来纠正有问题的数据集。
第三,可能需要重新运行在有偏差数据集上训练的模型,使用第二点中纠正后的数据集。目的是能够估计它们的实际性能水平。


最后,我们总结两点。
第一点是提醒读者要警惕。如果您连接数据集,数据集 A 的训练集中的数据项可能不在 A 的测试集中,但可能存在于数据集 B 的测试集中,从而在创建 A+B 数据集时产生泄漏。同样的逻辑也适用于重复数据。
请记住在执行此操作时清理数据集。

第二点是号召采取行动。
是否可以有一个机器人来扫描上传到 Hub 的数据集?它将指示数据集是否可靠,如果不可靠,则指示泄漏和重复数据的数量。
为什么在 2024 年我们仍然在训练模型,而这些数据集的质量尚未验证?
当我们处理这么多噪音时,我们真的配得上被称为数据科学家吗?

社区

注册登录 以发表评论