category_encoders是一個Python庫,專門用於將分類變量(如文字、標籤)轉換為機器學習模型可以處理的數值形式。它是 scikit-learn-contrib 項目的一部分,完全兼容Scikit-learn的API,可以無縫集成到機器學習流程中。本文將圍繞該庫的核心用法展開詳細講解。
category_encoders的github官方倉庫見:category_encoders,category_encoders介紹文檔見:category_encoders-docs。
安裝方式如下:
pip install category_encoders
# 查看category_encoders版本
import category_encoders as ce
ce.__version__
'2.8.1'
1 基礎介紹
1.1 使用概覽
category_encoders庫的核心價值在於它集成了超過20種不同的編碼方法,遠超Scikit-learn自帶的少數幾種。其主要特點包括:
- 統一的Scikit-learn API:所有編碼器都遵循
fit、transform等方法,可以輕鬆用於管道(Pipeline)和交叉驗證。 - 豐富的編碼方法:提供了從經典到前沿的各種編碼技術,滿足不同數據和模型的需求。
- 便捷的列處理:可以指定需要編碼的列,或自動識別數據框中的非數值列進行編碼。
- 處理未見類別:部分編碼器(如
TargetEncoder)能夠以合理的方式處理在訓練集中未出現過的新類別。
那麼為什麼需要這麼多編碼,這是因為機器學習模型只能看懂數字看不懂文字,所以得把顏色、城市這些文字類的特徵轉換成數字,這就是編碼;獨熱編碼雖然常用,但只適合類別少、沒有順序的特徵,要是遇到幾百個城市這種類別多的情況,用獨熱編碼會生成超多列數據,模型計算起來又慢又容易出錯,遇到低中高這種有順序的特徵,用獨熱編碼還會丟掉高低順序的關鍵信息。所以才需要序數編碼、目標編碼這些其他方法,它們能壓縮數據列數或者保留順序,讓模型算得快還預測得準。
此外,對於深度學習模型,雖然其可以通過嵌入層自動學習類別特徵的表示,但在某些場景下,預先使用編碼方法將類別特徵轉換為數值形式,可以簡化網絡結構並提升訓練效率。
所有category_encoders的編碼器使用方式如下:
import category_encoders as ce
import pandas as pd
import numpy as np
# 創建更簡單的數據集 - 使用顏色代替城市
np.random.seed(42)
data = pd.DataFrame({
'color': ['紅', '藍', '綠', '紅', '藍', '綠', '紅', '藍'],
'feature1': np.random.randn(8),
'target': [1, 0, 1, 0, 1, 0, 1, 0]
})
# 手動劃分訓練集和測試集(前6個訓練,後2個測試)
X_train = data[['color', 'feature1']].iloc[:6]
y_train = data['target'].iloc[:6]
X_test = data[['color', 'feature1']].iloc[6:]
y_test = data['target'].iloc[6:]
print("原始訓練數據:")
print(X_train)
print("\n訓練目標:")
print(y_train)
# 使用OneHot編碼(這是類別編碼的一種,更直觀)
encoder = ce.OneHotEncoder(cols=['color'])
X_train_encoded = encoder.fit_transform(X_train) # 有監督編碼需傳入y,無監督可省略y
X_test_encoded = encoder.transform(X_test)
print("\n編碼後的訓練數據:")
print(X_train_encoded)
print("\n編碼後的測試數據:")
print(X_test_encoded)
# 查看編碼器學習到的映射關係
print("\n編碼器學習到的映射:")
print(encoder.mapping)
原始訓練數據:
color feature1
0 紅 0.496714
1 藍 -0.138264
2 綠 0.647689
3 紅 1.523030
4 藍 -0.234153
5 綠 -0.234137
訓練目標:
0 1
1 0
2 1
3 0
4 1
5 0
Name: target, dtype: int64
編碼後的訓練數據:
color_1 color_2 color_3 feature1
0 1 0 0 0.496714
1 0 1 0 -0.138264
2 0 0 1 0.647689
3 1 0 0 1.523030
4 0 1 0 -0.234153
5 0 0 1 -0.234137
編碼後的測試數據:
color_1 color_2 color_3 feature1
6 1 0 0 1.579213
7 0 1 0 0.767435
編碼器學習到的映射:
[{'col': 'color', 'mapping': color_1 color_2 color_3
1 1 0 0
2 0 1 0
3 0 0 1
-1 0 0 0
-2 0 0 0}]
1.2 編碼方法介紹
category_encoders庫中的編碼器大致可分為兩類,可以根據數據是否有目標變量來確定。
無監督編碼方法
這類方法不依賴於目標變量(預測值),僅根據特徵自身的分佈或屬性進行轉換。
-
Backward Difference Contrast
- 編碼方法:將有序分類變量的每個級別(除第一個外)與其前一個級別的均值進行比較和編碼。
- 核心特點:適用於分析相鄰級別間的變化趨勢,常見於方差分析等統計模型。
-
BaseN
- 編碼方法:將整數類別ID轉換為自定義進制(如二進制、三進制)的數值表示。
- 核心特點:提供靈活的數值轉換,但通常不是特徵工程的首選,效率有限。
-
Binary
- 編碼方法:先將類別轉換為有序整數,再將該整數轉換為二進制數,並將每一位作為獨立的二元特徵。
- 核心特點:能高效壓縮維度,在類別數量極多時,比獨熱編碼節省大量特徵空間。
-
Gray
- 編碼方法:與二進制編碼類似,但使用格雷碼(循環碼)進行轉換,保證相鄰數值間僅一位不同。
- 核心特點:編碼後的相鄰類別具有最小的特徵差異,對某些算法可能更穩定。
-
Count
- 編碼方法:使用該類別在數據集中出現的次數(頻數)作為其編碼值。
- 核心特點:簡單快速,能反映類別的普遍性或常見度,但會丟失類別本身的區分信息。
-
Hashing
- 編碼方法:應用哈希函數將類別字符串映射到一個固定大小的、低維度的特徵向量中。
- 核心特點:內存消耗恆定,非常適合在線學習或超高基數特徵,但存在哈希衝突導致信息損失的風險。
-
Helmert Contrast
- 編碼方法:將有序分類變量的某個級別,與其之後所有級別的均值進行比較和編碼。
- 核心特點:用於統計模型,分析特定水平與後續整體平均水平之間的差異。
-
Ordinal
- 編碼方法:根據明確的順序(如大小、等級),為有序分類變量分配連續的整數。
- 核心特點:簡單且保留了順序信息,但隱含了“類別間隔相等”的假設,可能引入誤導。
-
One-Hot
- 編碼方法:為每一個類別創建一個新的二元特徵(列),樣本屬於該類別則標記為1,否則為0。
- 核心特點:徹底消除類別間的虛假順序關係,但類別多時會導致特徵稀疏和維度災難。
-
Rank Hot
- 編碼方法:先為有序分類變量按明確順序分配排名,再對排名執行獨熱編碼(對應排名標1,其餘為0),可優化為Top-K策略(僅編碼核心排名)。
- 核心特點:兼具順序保留與無虛假間隔優勢,靈活控維度;適用於中等類別數有序變量,類別過多易稀疏。
-
Polynomial Contrast
- 編碼方法:將有序分類變量的級別轉換為正交多項式(如線性、二次、三次)的係數。
- 核心特點:用於檢測和擬合目標變量與有序分類變量之間可能存在的多項式趨勢(如曲線關係)。
-
Sum Contrast
- 編碼方法:將每個類別的效應編碼為與所有類別整體均值的偏差。
- 核心特點:在迴歸模型中,使得截距項代表全局響應均值,係數易於解釋為與全局均值的偏離。
有監督編碼方法
這類方法在編碼過程中利用了目標變量的信息,旨在將類別信息與預測目標更緊密地聯繫起來。
-
CatBoost Encoding
- 編碼方法:一種基於目標變量統計(如均值)的編碼,通過引入樣本的隨機排列順序,並在計算中排除當前樣本的值來防止目標泄露。
- 核心特點:專為CatBoost設計,能有效防止過擬合,且可直接應用於其他樹模型,無需額外驗證策略。
-
Generalized Linear Mixed Model
- 編碼方法:將類別變量視為隨機效應,使用廣義線性混合模型估計其對目標的效應值,以此作為編碼。
- 核心特點:特別適用於具有層次結構、重複測量或存在組內相關性的數據。
-
James-Stein Estimator
- 編碼方法:將每個類別的目標統計量(如均值)向整體均值進行收縮,收縮強度取決於該類別的樣本量。
- 核心特點:通過方差縮減來優化估計,尤其能提升小樣本類別編碼值的穩健性和可靠性。
-
LeaveOneOut
- 編碼方法:對於當前樣本,計算其所屬類別中所有其他樣本的目標統計量(如均值)作為編碼值。
- 核心特點:最直接的防止目標泄露方法之一,但計算量較大,且對相同類別樣本的編碼值不完全相同。
-
M-estimator
- 編碼方法:計算目標均值與一個先驗值(如全局均值)的加權平均。權重由類別樣本量決定,樣本量大的類別更依賴自身均值。
- 核心特點:對簡單的目標均值編碼進行平滑,有效減少因小類別樣本量不足而引入的噪聲和過擬合。
-
Target Encoding / Mean Encoding
- 編碼方法:使用該類別的目標變量均值(迴歸)或正類比例(分類)來替換類別標籤。
- 核心特點:將類別信息與預測目標強關聯,效果顯著,但必須配合嚴格的交叉驗證或平滑使用,否則極易導致數據泄露和過擬合。
-
Weight of Evidence
- 編碼方法:主要用於二分類,計算
ln((好樣本比例) / (壞樣本比例))作為編碼值。 - 核心特點:直接衡量該類別對區分“好”、“壞”事件的預測能力,在金融風控等領域應用廣泛,解釋性強。
- 編碼方法:主要用於二分類,計算
-
Quantile Encoder
- 編碼方法:不使用目標均值,而是使用目標變量在該類別下的特定分位數(如中位數、第25分位數)進行編碼。
- 核心特點:對異常值不敏感,能捕捉類別內目標值的分佈位置信息,比單一均值提供更穩健的編碼。
-
Summary Encoder
- 編碼方法:為目標變量在每個類別下的分佈計算多個統計量(如均值、標準差、分位數、偏度等),生成一組特徵。
- 核心特點:提供關於類別與目標關係的全景視圖,能更豐富地描述數據分佈形態,但特徵維度會增加。
重要提示:本文僅介紹category_encoders庫中各種編碼方法的基本使用和適用場景,關於每種編碼方法的詳細數學原理和統計理論,需要進一步自行查閲相關學術資料和官方文檔進行深入學習。
1.3 編碼器選擇建議
-
無監督編碼:無目標變量時使用
- 標準首選:
One-Hot(類別少,<10),Ordinal(變量有明確順序)。 - 類別極多(高基數):用
Binary、Hashing壓縮維度。 - 探索類別頻率:用
Count。 - 有序變量分析:
Backward Difference、Helmert、Polynomial(用於統計模型趨勢分析)。 - 特定需求:
BaseN、Gray(一般很少用)。
- 標準首選:
-
有監督編碼:有目標變量時優先考慮
- 通用穩健選擇:
CatBoost(防過擬合好)、M-estimator(平滑小類別)。 - 二分類問題(如風控):首選
Weight of Evidence (WOE),解釋性強。 - 避免泄露:使用
LeaveOneOut或嚴格在訓練集內做Target Encoding並配合交叉驗證。 - 數據有層次/組結構:考慮
Generalized Linear Mixed Model (GLMM)。 - 提升小類別估計:用
James-Stein(收縮至整體均值)。 - 關注分佈而非僅均值:用
Quantile Encoder(抗異常值)、Summary Encoder(描述完整分佈)。
- 通用穩健選擇:
-
簡明決策路徑
- 是否有目標變量?
- 無 → 選 無監督編碼,根據類別數量、順序選擇。
- 有 → 選 有監督編碼,尤其推薦
CatBoost、M-estimator或WOE。
- 關鍵注意:
- 防過擬合:有監督編碼必須使用交叉驗證或在訓練集內擬合,避免數據泄露。
- 在線學習:
Hashing是唯一內存固定的編碼器。 - 樹模型:可放心使用
CatBoost、Ordinal。 - 線性/統計模型:慎用
Ordinal(可能引入虛假順序),多用One-Hot或統計對比編碼(Helmert等)。
- 是否有目標變量?
核心原則:根據數據特點(順序、基數)和任務目標(預測、解釋)選擇,有監督編碼通常預測能力更強,但務必小心處理避免目標泄露。
2 代碼示例
以下數據集作為後續所有示例的基礎數據:
import pandas as pd
# 構造示例數據
df = pd.DataFrame({
"color": ["紅", "藍", "綠", "紅", "綠"],
"size": ["S", "M", "L", "M", "L"],
"target": [25.3, 30.1, 28.5, 26.7, 29.3] # 有監督編碼需要目標變量
})
2.1 無監督編碼方法(Unsupervised)
Backward Difference Contrast(後向差分對比編碼)
- 核心邏輯:將有序類別轉換為相鄰類別均值的差值,適用於有序類別特徵(如S<M<L);
- 輸出形式:k個類別生成k-1列,每列表示當前類別與前一類別均值的差分;
- 適用場景:有序分類特徵(如評分、等級、年齡段),需體現類別間的順序差值。
# 針對有序特徵size(S<M<L)
encoder = ce.BackwardDifferenceEncoder(cols=["size"], drop_invariant=True)
df_encoded = encoder.fit_transform(df)
print("後向差分編碼結果:")
print(df_encoded[["size_0", "size_1"]]) # 3個類別生成2列,每一列代表當前列和上一列的一次比較
後向差分編碼結果:
size_0 size_1
0 -0.666667 -0.333333
1 0.333333 -0.333333
2 0.333333 0.666667
3 0.333333 -0.333333
4 0.333333 0.666667
BaseN(BaseN編碼)
- 核心邏輯:把類別變成N進制數字,用更少的列裝下更多的類,是Binary編碼的通用版;
- 關鍵參數:
base(進制數,默認2,即Binary編碼); - 輸出形式:k個類別生成[log_base(k)個⌉列,base為進制數,k為類別數;
- 適用場景:類別特別多,不想生成太多列的情況。
# 對color特徵用3進制編碼
encoder = ce.BaseNEncoder(cols=["color"], base=3)
df_encoded = encoder.fit_transform(df)
print("BaseN(3進制)編碼結果:")
print(df_encoded.filter(like="color"))
BaseN(3進制)編碼結果:
color_0 color_1
0 0 1
1 0 2
2 1 0
3 0 1
4 1 0
Binary(二進制編碼)
- 核心邏輯:BaseN編碼的特例(base=2),先將類別映射為整數,再轉換為二進制,每一位作為一列;
- 輸出形式:k個類別生成⌈log2(k)⌉列,列數遠少於One-Hot;
- 適用場景:類別特別多,極限壓縮編碼維度的情況。
encoder = ce.BinaryEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df)
print("二進制編碼結果:")
print(df_encoded.filter(like="color"))
二進制編碼結果:
color_0 color_1
0 0 1
1 1 0
2 1 1
3 0 1
4 1 1
Gray(格雷編碼)
- 核心邏輯:基於格雷碼(相鄰整數僅有1位不同的二進制編碼),減少編碼列間的相關性;
- 輸出形式:與Binary編碼列數相同,但數值分佈更平滑;
- 適用場景:需降低編碼後特徵間相關性的高維度類別特徵。
encoder = ce.GrayEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df)
print("格雷編碼結果:")
print(df_encoded.filter(like="color"))
格雷編碼結果:
color_0 color_1
0 0 1
1 1 0
2 1 1
3 0 1
4 1 1
Count(計數編碼)
- 核心邏輯:用每個類別在數據集中的出現次數(頻數)替換該類別;
- 輸出形式:每個類別特徵生成1列,值為對應類別的計數;
- 適用場景:需體現類別“出現頻率”的場景,如高頻類別更重要的特徵。
encoder = ce.CountEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df)
print("計數編碼結果:")
print(df_encoded[["color"]]) # color列值為該顏色出現的次數
計數編碼結果:
color
0 2
1 1
2 2
3 2
4 2
Hashing(哈希編碼)
- 核心邏輯:通過哈希函數將類別映射到固定數量的列(桶),無需擬合(可處理未知類別);
- 關鍵參數:
n_components(哈希桶數,默認8)、hash_method(哈希方法,如'md5'/'sha1'); - 輸出形式:固定n_components列,可能存在哈希衝突;
- 適用場景:超大規模數量特徵(如用户ID、商品ID),無需存儲類別映射表。
encoder = ce.HashingEncoder(cols=["color"], n_components=4, hash_method='sha1')
df_encoded = encoder.fit_transform(df)
print("哈希編碼結果:")
print(df_encoded.filter(like="col")) # 輸出4列哈希值
哈希編碼結果:
col_0 col_1 col_2 col_3
0 0 1 0 0
1 0 1 0 0
2 0 1 0 0
3 0 1 0 0
4 0 1 0 0
Helmert Contrast(赫爾默特對比編碼)
- 核心邏輯:將每個類別與後續所有類別的均值對比,適用於有序類別;
- 輸出形式:k個類別生成k-1列,每列表示當前類別與後續類別均值的差值;
- 適用場景:適用於有序類別特徵,常用於統計建模與迴歸分析,以考察當前類別 vs 後續所有類別的差異。
encoder = ce.HelmertEncoder(cols=["size"])
df_encoded = encoder.fit_transform(df)
print("赫爾默特對比編碼結果:")
print(df_encoded.filter(like="size"))
赫爾默特對比編碼結果:
size_0 size_1
0 -1.0 -1.0
1 1.0 -1.0
2 0.0 2.0
3 1.0 -1.0
4 0.0 2.0
Ordinal(序數編碼)
- 核心邏輯:將有序類別映射為連續整數(如S→1, M→2, L→3),最基礎的有序編碼;
- 關鍵參數:
mapping(自定義類別-整數映射,默認按字母順序); - 輸出形式:每個類別特徵生成1列,值為整數;
- 適用場景:明確有序的類別特徵(如學歷、評分),需保留順序關係。
# 自定義size的映射(S<M<L)
mapping = [{"col": "size", "mapping": {"S": 1, "M": 2, "L": 3, None: 0}}]
encoder = ce.OrdinalEncoder(cols=["size"], mapping=mapping)
df_encoded = encoder.fit_transform(df)
print("序數編碼結果:")
print(df_encoded[["size"]])
序數編碼結果:
size
0 1
1 2
2 3
3 2
4 3
One-Hot(獨熱編碼)
- 核心邏輯:將每個類別映射為獨立列,列值為0/1(當前樣本是否屬於該類別);
- 關鍵參數:
drop_invariant(刪除全0/全1列)、use_cat_names(用類別名作為列名); - 輸出形式:k個類別生成k列(或k-1列,避免多重共線性);
- 適用場景:低基數無序類別特徵(如性別、顏色),是最常用的無監督編碼。
encoder = ce.OneHotEncoder(cols=["color"], use_cat_names=True)
df_encoded = encoder.fit_transform(df)
print("獨熱編碼結果:")
print(df_encoded[["color_紅", "color_藍", "color_綠"]])
獨熱編碼結果:
color_紅 color_藍 color_綠
0 1 0 0
1 0 1 0
2 0 0 1
3 1 0 0
4 0 0 1
Rank Hot(秩熱編碼)
- 核心邏輯:先對類別按出現頻率排序(秩),再對秩進行獨熱編碼;
- 輸出形式:k個類別生成k列,列值為0/1,基於秩的分佈;
- 適用場景:需結合類別頻率和獨熱編碼的場景,突出高頻類別。
encoder = ce.RankHotEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df)
print("秩熱編碼結果:")
print(df_encoded.filter(like="color"))
秩熱編碼結果:
color_1 color_2 color_3
0 1 0 0
1 1 1 1
2 1 1 0
3 1 0 0
4 1 1 0
Polynomial Contrast(多項式對比編碼)
- 核心邏輯:將有序類別轉換為多項式(線性、二次、三次等)形式,捕捉類別間的非線性關係;
- 輸出形式:k個類別生成k-1列,對應不同階數的多項式;
- 適用場景:有序類別特徵,需捕捉類別與目標間的非線性關係(無監督場景下僅體現類別自身的非線性)。
encoder = ce.PolynomialEncoder(cols=["size"])
df_encoded = encoder.fit_transform(df)
print("多項式對比編碼結果:")
print(df_encoded.filter(like="size"))
多項式對比編碼結果:
size_0 size_1
0 -7.071068e-01 0.408248
1 -4.433780e-17 -0.816497
2 7.071068e-01 0.408248
3 -4.433780e-17 -0.816497
4 7.071068e-01 0.408248
Sum Contrast(和對比編碼)
- 核心邏輯:將每個類別與總體均值對比,列值和為0,避免多重共線性;
- 輸出形式:k個類別生成k-1列,每列值表示當前類別與總體均值的偏差;
- 適用場景:有序/無序類別特徵,需避免獨熱編碼的多重共線性問題。
encoder = ce.SumEncoder(cols=["size"])
df_encoded = encoder.fit_transform(df)
print("和對比編碼結果:")
print(df_encoded.filter(like="size"))
和對比編碼結果:
size_0 size_1
0 1.0 0.0
1 0.0 1.0
2 -1.0 -1.0
3 0.0 1.0
4 -1.0 -1.0
2.2 有監督編碼方法(Supervised)
CatBoost(CatBoost編碼)
- 核心邏輯:基於目標變量的統計值,按樣本順序逐步編碼(避免過擬合),對每個類別計算目標均值並加入隨機噪聲;
- 關鍵參數:
sigma(噪聲係數,默認0.05,防止過擬合); - 輸出形式:每個類別特徵生成1列,值為結合目標均值的編碼值;
- 適用場景:分類/迴歸任務,尤其是梯度提升樹(CatBoost/XGBoost)模型,抗過擬合能力強。
encoder = ce.CatBoostEncoder(cols=["color"],sigma=0.01)
df_encoded = encoder.fit_transform(df, y=df["target"])
print("CatBoost編碼結果:")
print(df_encoded[["color"]])
CatBoost編碼結果:
color
0 27.848641
1 28.131808
2 27.850336
3 26.515930
4 28.308330
Generalized Linear Mixed Model(GLMM編碼)
- 核心邏輯:基於廣義線性混合模型,將類別作為隨機效應,計算每個類別的後驗均值;
- 輸出形式:每個類別特徵生成1列,值為模型估計的後驗均值;
- 適用場景:需結合統計模型的編碼場景,適合小樣本數據(正則化效果好)。
encoder = ce.GLMMEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df, y=df["target"])
print("GLMM編碼結果:")
print(df_encoded[["color"]])
GLMM編碼結果:
color
0 -2.119044
1 1.555984
2 0.563060
3 -2.119044
4 0.563060
James-Stein Estimator(詹姆斯-斯坦因估計編碼)
- 核心邏輯:用詹姆斯-斯坦因估計量收縮類別均值,平衡全局均值和類別自身均值,減少方差;
- 輸出形式:每個類別特徵生成1列,值為收縮後的目標均值;
- 適用場景:類別樣本分佈不均衡(部分類別樣本少),需收縮均值減少偏差。
encoder = ce.JamesSteinEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df, y=df["target"])
print("James-Stein編碼結果:")
print(df_encoded[["color"]])
James-Stein編碼結果:
color
0 26.0
1 30.1
2 28.9
3 26.0
4 28.9
LeaveOneOut(留一法編碼)
- 核心邏輯:對每個樣本,用除自身外同類別樣本的目標均值作為編碼值,避免自身信息泄露;
- 輸出形式:每個類別特徵生成1列,值為留一法計算的目標均值;
- 適用場景:小樣本數據,防止過擬合(無信息泄露),適合分類/迴歸任務。
encoder = ce.LeaveOneOutEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df, y=df["target"])
print("留一法編碼結果:")
print(df_encoded[["color"]])
留一法編碼結果:
color
0 26.70
1 27.98
2 29.30
3 25.30
4 28.50
M-estimator(M估計量編碼)
- 核心邏輯:基於穩健統計的M估計量,降低異常值對類別均值的影響;
- 關鍵參數:
sigma(穩健性係數); - 輸出形式:每個類別特徵生成1列,值為穩健的目標均值估計;
- 適用場景:目標變量存在異常值的迴歸/分類任務,需穩健的均值估計。
encoder = ce.MEstimateEncoder(cols=["color"], sigma=0.01)
df_encoded = encoder.fit_transform(df, y=df["target"])
print("M-estimator編碼結果:")
print(df_encoded[["color"]])
M-estimator編碼結果:
color
0 26.660000
1 29.040000
2 28.593333
3 26.660000
4 28.593333
Target Encoding(目標編碼)
- 核心邏輯:用每個類別的目標變量均值替換該類別(分類任務:概率;迴歸任務:均值);
- 關鍵參數:
smoothing(平滑係數,平衡全局均值和類別均值,避免過擬合); - 輸出形式:每個類別特徵生成1列,值為目標均值;
- 適用場景:分類/迴歸任務的核心編碼方法,簡單高效,但需注意平滑/交叉驗證防止過擬合。
# 加入平滑避免小類別過擬合
encoder = ce.TargetEncoder(cols=["color"], smoothing=10)
df_encoded = encoder.fit_transform(df, y=df["target"])
print("目標編碼結果:")
print(df_encoded[["color"]])
目標編碼結果:
color
0 27.699135
1 28.255830
2 28.110503
3 27.699135
4 28.110503
Weight of Evidence(證據權重編碼,WOE)
- 核心邏輯:專為二分類任務設計,計算每個類別對正/負樣本的區分度: $$WOE = ln(\frac{正樣本佔比}{負樣本佔比})$$
- 輸出形式:每個類別特徵生成1列,值為WOE值;
- 適用場景:二分類任務(如風控、違約預測),WOE值可直接體現類別對目標的區分能力。
import pandas as pd
import category_encoders as ce
# 1. 構建示例數據
data = {
"color": ["紅", "藍", "紅", "綠", "藍", "綠", "紅"],
"target": [1, 0, 1, 0, 0, 1, 1,] # 二分類標籤:0/1
}
df_temp = pd.DataFrame(data)
# 2. 查看原始數據(變量名同步修改)
print("原始數據:")
print(df_temp)
print("-" * 50)
# 3. 執行WOE編碼(變量名同步修改)
encoder = ce.WOEEncoder(cols=["color"])
df_encoded = encoder.fit_transform(df_temp, y=df_temp["target"])
# 4. 輸出編碼結果
print("證據權重(WOE)編碼結果:")
print(df_encoded[["color"]])
原始數據:
color target
0 紅 1
1 藍 0
2 紅 1
3 綠 0
4 藍 0
5 綠 1
6 紅 1
--------------------------------------------------
證據權重(WOE)編碼結果:
color
0 1.203973
1 -1.280934
2 1.203973
3 -0.182322
4 -1.280934
5 -0.182322
6 1.203973
Quantile Encoder(分位數編碼)
- 核心邏輯:用類別對應的目標變量分位數(如中位數、四分位數)替換類別,而非均值,抗異常值更強;
- 關鍵參數:
quantile(分位數,默認0.5即中位數); - 輸出形式:每個類別特徵生成1列,值為目標變量的分位數;
- 適用場景:目標變量有異常值的迴歸任務,需穩健的統計量替代均值。
# 用75分位數編碼
encoder = ce.QuantileEncoder(cols=["color"], quantile=0.75)
df_encoded = encoder.fit_transform(df, y=df["target"])
print("分位數編碼結果:")
print(df_encoded[["color"]])
分位數編碼結果:
color
0 27.333333
1 29.700000
2 29.166667
3 27.333333
4 29.166667
Summary Encoder(分位數摘要編碼)
- 核心邏輯:對每個類別計算目標變量的指定分位數(如25%分位數、中位數、75%分位數等),生成多列編碼;
- 關鍵參數:
quantiles(分位數列表,默認(0.25, 0.75))、m(貝葉斯平滑係數,默認1.0,緩解稀有類別分位數估計偏差); - 輸出形式:每個類別特徵生成
len(quantiles)列,列名格式為「原列名_分位數值」(如 color_0.25、color_0.5); - 適用場景:高基數類別特徵編碼(如用户ID、商品SKU),分位數對異常值魯棒,相比均值編碼更穩定,但列數隨分位數數量增加。
encoder = ce.SummaryEncoder(
cols=["color"], # 僅編碼color列
quantiles=[0.25, 0.5, 0.75], # 計算25%分位數、中位數(0.5)、75%分位數
m=1.0, # 平滑係數,緩解過擬合
handle_unknown="value", # 未知類別用全局分位數填充
handle_missing="value" # 缺失值用全局分位數填充
)
df_encoded = encoder.fit_transform(df, y=df["target"])
print("彙總編碼結果:")
print(df_encoded.filter(like="color"))
彙總編碼結果:
color_25 color_50 color_75
0 26.000000 26.833333 27.333333
1 28.400000 29.300000 29.700000
2 28.033333 28.766667 29.166667
3 26.000000 26.833333 27.333333
4 28.033333 28.766667 29.166667
3 參考
- category_encoders
- category_encoders-docs