開源 AI 食譜文件

使用 Cleanlab 檢測文字資料集中的問題

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

Open In Colab

使用 Cleanlab 檢測文字資料集中的問題

作者:Aravind Putrevu

在這個 5 分鐘的快速入門教程中,我們將使用 Cleanlab 來檢測一個意圖分類資料集中的各種問題。該資料集由一家網上銀行的 (文字) 客戶服務請求組成。我們考慮了 Banking77-OOS 資料集 的一個子集,其中包含 1000 個客戶服務請求,這些請求根據其意圖被分為 10 個類別 (您可以在任何文字分類資料集上執行相同的程式碼)。Cleanlab 能夠自動識別我們資料集中的不良樣本,包括錯誤標註的資料、超出範圍的樣本 (離群點) 或其他模糊的樣本。在深入進行資料建模之前,請考慮過濾或修正這些不良樣本!

本教程內容概覽:

  • 使用預訓練的 Transformer 模型從客戶服務請求中提取文字嵌入

  • 在文字嵌入上訓練一個簡單的邏輯迴歸模型,以計算樣本外 (out-of-sample) 預測機率

  • 使用這些預測和嵌入執行 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 模型的數值表示作為我們文字的嵌入。 Sentence Transformers 庫提供了計算文字資料嵌入的簡單方法。這裡,我們載入預訓練的 `electra-small-discriminator` 模型,然後透過網路執行我們的資料來提取每個示例的向量嵌入。

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

我們後續的機器學習模型將直接操作 `text_embeddings` 的元素,以便對客戶服務請求進行分類。

定義分類模型並計算樣本外預測機率

利用預訓練網路進行特定分類任務的典型方法是新增一個線性輸出層,並在新資料上微調網路引數。然而,這可能計算量很大。或者,我們可以凍結網路的預訓練權重,只訓練輸出層,而無需依賴 GPU。這裡我們透過在提取的嵌入之上擬合一個 scikit-learn 線性模型來方便地實現這一點。

為了識別標籤問題,cleanlab 需要模型對每個資料點進行機率預測。然而,對於模型之前訓練過的資料點,這些預測會 *過擬合* (因此不可靠)。cleanlab 僅用於處理 **樣本外** (out-of-sample) 的預測類別機率,即在模型訓練期間未見過的資料點。

這裡我們使用邏輯迴歸模型和交叉驗證,為資料集中的每個示例獲取樣本外預測類別機率。請確保 `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 的離群點質量得分對結果資料幀進行排序,以檢視資料集中最嚴重的離群點。

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]

質量最低的離群點的示例輸出如下

索引 text (文字) label (標籤)
791 提款待定是什麼意思? 46
601 交易中有 1 美元的費用。 34
863 我的 atm 取款仍然待定 46
355 解釋銀行間匯率 32
157 丟失的卡找到了,想把它放回應用程式中 13

我們看到,cleanlab 已經識別出此資料集中的條目似乎不是正常的客戶請求。此資料集中的離群點似乎是超出範圍的客戶請求以及其他無意義的文字,這對於意圖分類沒有意義。請仔細考慮這類離群點是否會對您的資料建模產生不利影響,如果是,請考慮將它們從資料集中移除。

近似重複問題

根據報告,我們的資料集包含一些近似重複的樣本集。我們可以透過 `get_issues` 檢視哪些樣本是 (近似) 重複的 (以及一個量化每個樣本與其資料集中最近鄰居差異程度的數值質量得分)。我們透過 cleanlab 的近似重複質量得分對結果資料幀進行排序,以檢視資料集中最接近重複的文字樣本。

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]]

示例輸出

索引 text (文字) label (標籤)
459 我在國外買東西,但用了錯誤的匯率。 17
429 我在海外買東西,但用了錯誤的匯率。 17
data.iloc[[501, 412]]

示例輸出

索引 text (文字) label (標籤)
501 你們使用的匯率真的很差。這不可能是官方的銀行間匯率。 17
412 你們使用的匯率很差。這不可能是官方的銀行間匯率。 17

我們看到這兩組請求確實非常相似!在資料集中包含近似重複項可能會對模型產生意想不到的影響,並且要警惕將它們分散在訓練集和測試集中。從 常見問題解答 中瞭解更多關於處理資料集中近似重複項的資訊。

非獨立同分布 (Non-IID) 問題 (資料漂移)

根據報告,我們的資料集似乎不是獨立同分布 (IID) 的。資料集的整體非 IID 得分 (如下所示) 對應於一個統計檢驗的 `p-value`,該檢驗用於判斷資料集中樣本的順序是否與其特徵值之間的相似性相關。較低的 `p-value` 強烈表明資料集違反了 IID 假設,這是從資料集中產生的結論 (模型) 能夠泛化到更大總體的關鍵假設。

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

在這裡,我們的資料集被標記為非 IID,因為在原始資料中,行恰好按類別標籤排序。如果我們記得在模型訓練和資料分割之前對行進行洗牌,這可能是良性的。但如果您不知道為什麼您的資料被標記為非 IID,那麼您應該擔心潛在的資料漂移或資料點之間的意外互動 (它們的值可能在統計上不是獨立的)。仔細考慮未來的測試資料可能是什麼樣子 (以及您的資料是否代表您所關心的總體)。在非 IID 測試執行之前,您不應該對資料進行洗牌 (這會使其結論無效)。

如上所示,cleanlab 可以自動列出資料集中最可能的問題,幫助您更好地整理資料集以進行後續建模。有了這份問題清單,您可以決定是修復這些標籤問題,還是從資料集中刪除無意義或重複的樣本,以獲得更高質量的資料集來訓練您的下一個機器學習模型。cleanlab 的問題檢測可以與您最初訓練的 *任何* 型別模型的輸出一起執行。

Cleanlab 開源專案

Cleanlab 是一個標準的以資料為中心的 AI 軟體包,旨在解決現實世界中混亂資料的資料質量問題。

請考慮給 Cleanlab Github 程式碼倉庫一個 Star,我們歡迎對該專案做出貢獻

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.