LLE 簡介
導言
在過去幾周裡,我一直對應用於法語的 NER 任務很感興趣。你知道嗎?我遇到了 LLE:漏洞無處不在。
我想知道這是否是法語或 NER 任務獨有的現象,所以我決定從 Hugging Face Hub 下載數百個資料集,以評估它們的質量。而你不會喜歡下面讀到的內容。
方法
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 上找到。
![]() |
|---|
| 檢視 Hugging Face 檢視器,讓它不那麼刺眼 |
資料集中的列應按以下方式解釋:
dataset_name:分析的資料集名稱。如果名稱中包含逗號,則表示該資料集包含多個子集。例如,glue,sst2表示正在分析glue的sst2子集。如果名稱中包含括號,則表示我們只分析括號內的標籤。這是因為一個數據集可能包含多列可用作標籤(可能用於多個不同任務)。例如,如果我們以conll2003為例,它包含ner_tags和pos_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_test、text_leaks_valid_wrt_test和text_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_test、text_and_label_leaks_valid_wrt_test和text_and_label_duplication_test的值之和除以測試集長度。對於conll2003(ner_tags),列值為 9.818%。difference_annotation_in_train_and_validation_splits:訓練集text_leaks_train_wrt_test和text_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 年我們仍然在訓練模型,而這些資料集的質量尚未驗證?
當我們處理這麼多噪音時,我們真的配得上被稱為資料科學家嗎?

