2024-08-29|閱讀時間 ‧ 約 26 分鐘

【資料分析】python機器學習-什麼是標籤欄位不平衡? 造成的影響以及處理辦法

raw-image

在機器學習和數據分析中,「標籤」(Label)通常指的是你想要預測的目標變數,這個變數代表了你模型的輸出結果。「標籤欄位不平衡」指的是在分類問題中,目標變數(即標籤或類別)不同類別的樣本數量分佈不均勻,某些類別的樣本數遠多於其他類別的樣本數。


# 可使用目錄功能快速確認要閱覽的主題


標籤不平衡具體的例子

假設我們有一個紅酒品質預測的數據集,標籤欄位 quality 的值範圍是3到8,代表不同品質的紅酒。如果數據集中的品質標籤分佈如下:

  • quality = 5:6000樣本
  • quality = 6:5000樣本
  • quality = 7:400樣本
  • quality = 8:100樣本
  • quality = 4:50樣本
  • quality = 3:10樣本

這裡我們看到 quality = 5quality = 6 的樣本數遠遠多於其他品質等級的紅酒,這就是標籤不平衡的情況。


不平衡問題的影響

標籤不平衡會對模型的訓練、評估和最終預測性能產生多種不利影響:

1. 模型偏向多數類別

  • 在訓練過程中,機器學習模型會學習如何區分不同的類別。如果數據集中大部分樣本都來自於某一個或幾個類別(多數類別),而其他類別(少數類別)樣本很少,模型會更傾向於預測多數類別,因為這樣可以在訓練數據上獲得更高的準確率。
  • 例如,在上述紅酒品質預測中,模型可能會傾向於預測品質為5或6的紅酒,而忽略品質為7或8的紅酒。結果是模型在少數類別上的預測效果很差。


2. 錯誤分類代價高

  • 對於不平衡數據集,少數類別通常可能代表更重要的業務場景。例如,在醫療診斷中,少數類別可能是“患病”或“有風險”的標籤,錯誤分類這些樣本會帶來嚴重後果。
  • 在紅酒品質預測中,可能品質較高(如7或8)的紅酒樣本是最有價值的,錯誤預測這些樣本的品質可能導致錯誤的商業決策。


3. 評估指標的偏差

  • 在不平衡數據集中,像準確率(accuracy)這樣的評估指標可能會誤導模型的性能。例如,如果90%的樣本來自多數類別,模型只要總是預測多數類別,就能達到90%的準確率,這看似很好,但事實上模型可能在少數類別上表現非常糟糕。
  • 因此,單靠準確率並不能全面反映模型的性能,需要使用更合適的評估指標,如精確率(precision)、召回率(recall)、F1分數等。


4. 模型收斂問題

  • 在訓練過程中,由於多數類別對模型的影響更大,模型可能更快收斂到針對多數類別的解決方案,而忽略少數類別的特徵和模式,這會導致模型在整個數據集上的表現不穩定。


處理標籤不平衡方法選擇參考

  • 過採樣(Oversampling)少數類別:當你希望增加少數類別的樣本數量以平衡數據集,並且不想丟失任何多數類別的信息時,可以選擇過採樣,如 SMOTE。
  • 欠採樣(Undersampling)多數類別:當你想簡化數據集並減少模型訓練時間,且可以接受丟失部分多數類別信息時,選擇欠採樣。
  • 調整類別權重(Class Weights):當你不想改變數據集大小,但希望模型在訓練中更重視少數類別時,調整類別權重是一個不錯的選擇。
  • 生成合成樣本:當少數類別的樣本極少且多樣性不足時,使用 SMOTE 等生成合成樣本的方法來豐富少數類別。
  • 使用適合不平衡數據的評估指標:當你需要全面衡量模型性能,特別是在處理不平衡數據時,選擇精確率、召回率或 F1 分數來替代或補充準確率。
  • 調整決策閾值(Threshold Tuning):當你想通過調整模型的預測行為來改善少數類別的檢出率或減少誤報時,考慮調整決策閾值。
  • 集成方法:當數據集特徵複雜且不平衡嚴重,並且你希望利用多個基模型來提高模型穩定性和泛化能力時,選擇集成方法如隨機森林或 XGBoost。


1. 重採樣(Resampling)

1.1 過採樣(Oversampling)少數類別

  • 原理:過採樣通過增加少數類別的樣本數量來平衡數據集。可以簡單地複製少數類別的樣本,或使用合成方法來生成新的少數類別樣本。
  • 常見方法
    • 簡單複製:直接複製少數類別的現有樣本。
    • SMOTE(Synthetic Minority Over-sampling Technique):通過插值的方法生成新的少數類別樣本。
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report

# 創建一個不平衡的數據集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=2, n_redundant=10,
n_clusters_per_class=1, weights=[0.9, 0.1], flip_y=0, random_state=42)

# 分割數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 使用 SMOTE 進行過採樣
sm = SMOTE(random_state=42)
X_resampled, y_resampled = sm.fit_resample(X_train, y_train)

# 訓練隨機森林模型
model = RandomForestClassifier(random_state=42)
model.fit(X_resampled, y_resampled)

# 在測試集上進行預測
y_pred = model.predict(X_test)

# 顯示分類報告
print(classification_report(y_test, y_pred))


使用 SMOTE(Synthetic Minority Over-sampling Technique)

  • 過採樣優點
    • 增加少數類別的樣本數量,使數據集更加平衡。
    • 生成的新樣本具有多樣性,有助於減少過度擬合的風險。
    • 在不刪除任何多數類別樣本的情況下提高少數類別的代表性。
  • 過採樣缺點
    • 可能生成一些不代表真實分佈的噪聲樣本,尤其是在少數類別分佈不規則時。
    • 在某些情況下,生成的合成樣本可能並沒有提供有用的信息,反而增加了訓練時間和模型的複雜性。


1.2 欠採樣(Undersampling)多數類別

  • 原理:欠採樣通過減少多數類別的樣本數量來平衡數據集。這樣可以強迫模型在有限的多數類別樣本上學習,從而更關注少數類別。
  • 常見方法
    • 隨機欠採樣:隨機刪除多數類別中的樣本。
    • NearMiss:選擇那些與少數類別樣本距離最近的多數類別樣本進行保留。
from imblearn.under_sampling import RandomUnderSampler

# 使用 RandomUnderSampler 進行欠採樣
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_train, y_train)

# 訓練隨機森林模型
model = RandomForestClassifier(random_state=42)
model.fit(X_resampled, y_resampled)

# 在測試集上進行預測
y_pred = model.predict(X_test)

# 顯示分類報告
print(classification_report(y_test, y_pred))


使用 RandomUnderSampler

  • 欠採樣優點
    • 簡化數據集,減少訓練時間和內存需求。
    • 通過強制模型在有限的多數類別樣本上學習,幫助模型更關注少數類別。
  • 欠採樣缺點
    • 可能丟失多數類別的重要信息,導致模型性能下降。
    • 在極端欠採樣的情況下,多數類別的樣本數量過少,可能導致模型過度擬合。


2. 調整類別權重(Class Weights)

  • 原理:通過在模型訓練過程中賦予少數類別更高的權重,來告訴模型少數類別的重要性。這樣,模型在計算損失函數時,少數類別的錯誤會有更大的懲罰。
  • 應用:許多機器學習算法,如支持向量機(SVM)、邏輯回歸(Logistic Regression)、隨機森林(Random Forest)等,都允許通過 class_weight 參數來自動調整類別權重。
# 訓練帶有類別權重的隨機森林模型
model = RandomForestClassifier(class_weight='balanced', random_state=42)
model.fit(X_train, y_train)

# 在測試集上進行預測
y_pred = model.predict(X_test)

# 顯示分類報告
print(classification_report(y_test, y_pred))


在模型中使用 class_weight='balanced'

  • 調整類別權重優點
    • 不需要修改數據集,避免了過採樣或欠採樣可能帶來的數據變形或信息丟失。
    • 容易實現,並且對模型訓練時間的影響較小。
    • 能夠在不改變數據集大小的情況下,提高模型對少數類別的敏感度。
  • 調整類別權重缺點
    • 在某些情況下,權重設置過高可能導致模型過度擬合少數類別。
    • 權重調整不足可能不足以完全解決嚴重的不平衡問題,尤其是在少數類別極為稀少的情況下。


3. 生成合成樣本

  • SMOTE 和其他生成方法(如 ADASYN)可以通過生成合成樣本來平衡數據集。這些方法不僅僅是簡單地複製樣本,而是基於現有樣本之間的距離來生成新樣本。
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report

# 創建一個不平衡的數據集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=2, n_redundant=10,
n_clusters_per_class=1, weights=[0.9, 0.1], flip_y=0, random_state=42)

# 分割數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 使用 SMOTE 進行過採樣
sm = SMOTE(random_state=42)
X_resampled, y_resampled = sm.fit_resample(X_train, y_train)

# 訓練隨機森林模型
model = RandomForestClassifier(random_state=42)
model.fit(X_resampled, y_resampled)

# 在測試集上進行預測
y_pred = model.predict(X_test)

# 顯示分類報告
print(classification_report(y_test, y_pred))


使用 SMOTE 或 ADASYN

  • 生成合成樣本優點
    • 增加少數類別的樣本數量,並且通過插值生成多樣性較高的合成樣本。
    • 適用於少數類別樣本非常稀少的情況,有助於模型更好地學習少數類別的特徵。
  • 生成合成樣本缺點
    • 可能生成不真實或不代表實際情況的樣本,特別是在樣本稀疏或分佈不規則的情況下。
    • 可能增加噪聲,導致模型在測試數據上的泛化能力下降。


4. 使用適合不平衡數據的評估指標

  • 問題:在不平衡數據集上,像準確率(accuracy)這樣的指標可能會誤導模型的性能。
  • 解決方案:使用其他評估指標,如精確率(precision)、召回率(recall)、F1分數、ROC-AUC 曲線等,來全面評估模型的表現。
    • 精確率:關注在所有被模型預測為正類的樣本中,實際為正類的比例。
    • 召回率:關注在所有實際為正類的樣本中,被模型正確識別的比例。
    • F1分數:精確率和召回率的調和平均數,當精確率和召回率之間有較大差異時,F1分數是更好的衡量指標。


使用範例:

【資料分析】python機器學習-使用不同的方法來評估模型準確率


  • 使用適合的評估指標優點
    • 提供了更全面的模型性能評估,尤其在處理不平衡數據時,比單一的準確率指標更有意義。
    • 有助於識別模型在少數類別上的表現,從而進一步優化模型。
  • 使用適合的評估指標缺點
    • 需要在不同指標之間進行權衡(如精確率與召回率之間的平衡),不適合所有情況。
    • 在應用中可能需要多次實驗來找到最合適的指標,這需要額外的時間和計算資源。


5. 調整決策閾值(Threshold Tuning)

  • 原理:大多數分類器默認將預測概率大於 0.5 的樣本分類為正類,但這在不平衡數據集上可能並不合適。通過調整這個閾值,可以提高少數類別的檢出率。
  • 應用:在評估過程中,你可以嘗試不同的閾值,找到最適合不平衡數據集的決策閾值。
from sklearn.metrics import precision_recall_curve

# 獲取預測概率
y_scores = model.predict_proba(X_test)[:, 1]

# 計算精確率、召回率及其對應的閾值
precisions, recalls, thresholds = precision_recall_curve(y_test, y_scores)

# 找到最佳的閾值
f1_scores = 2 * (precisions * recalls) / (precisions + recalls)
optimal_threshold = thresholds[np.argmax(f1_scores)]

print(f"Optimal Threshold: {optimal_threshold}")

# 根據最佳閾值進行預測
y_pred_new = (y_scores >= optimal_threshold).astype(int)

# 顯示新的分類報告
print(classification_report(y_test, y_pred_new))


通過調整閾值來改進模型對少數類別的預測

  • 調整決策閾值優點
    • 能夠靈活調整模型的預測行為,找到最佳的精確率和召回率平衡點。
    • 只需要調整模型的預測輸出,不需要重新訓練模型,因此操作簡單且高效。
  • 調整決策閾值缺點
    • 需要仔細選擇和測試最佳閾值,這可能需要大量實驗來確定最佳值。
    • 調整閾值可能會在提高一個指標的同時犧牲另一個指標(如提高召回率可能會降低精確率)。


6. 使用集成方法

  • 不平衡數據集的集成學習:通過使用集成方法,如隨機森林、提升方法(如 XGBoost),可以提高模型在不平衡數據集上的性能。這些方法通過集成多個基模型來提高少數類別的檢出率。
from xgboost import XGBClassifier

# 訓練 XGBoost 模型並設置類別權重
model = XGBClassifier(scale_pos_weight=len(y_train[y_train == 0]) / len(y_train[y_train == 1]), random_state=42)
model.fit(X_train, y_train)

# 在測試集上進行預測
y_pred = model.predict(X_test)

# 顯示分類報告
print(classification_report(y_test, y_pred))


使用隨機森林或 XGBoost 等集成學習方法

  • 用集成方法優點
    • 集成方法能夠有效地提高模型在不平衡數據集上的性能,因為它們通過多個基模型的投票或加權來做出預測,減少單一模型的偏差。
    • 特別適合於處理複雜和不平衡的數據集,並能夠捕捉更多樣的數據特徵。
  • 用集成方法缺點
    • 集成方法通常計算成本較高,訓練時間較長。
    • 模型的解釋性較差,難以理解具體決策過程。
分享至
成為作者繼續創作的動力吧!
從 Google News 追蹤更多 vocus 的最新精選內容從 Google News 追蹤更多 vocus 的最新精選內容

JayRay 的沙龍 的其他內容

你可能也想看

發表回應

成為會員 後即可發表留言
© 2024 vocus All rights reserved.