机器学习数据预处理:数据编码(超通俗完整版)
数据编码就是把文字、类别、标签,转换成计算机能看懂的数字,是处理分类特征必做步骤,不管是本科作业、研究生论文、工业项目都高频使用。
一、什么是数据编码?为什么必须做?
1. 一句话理解
机器只认识数字,不认识文字。
“男/女、红/绿/蓝、北京/上海、低/中/高”这类特征,必须转成数字才能建模,这个过程就是数据编码。
2. 不编码会怎样?
- 模型直接报错,无法训练
- 文字类别无法参与计算
- 无法做距离计算、梯度下降、树分裂
二、4 种最常用编码方法(通俗易懂版)
1. 标签编码 Label Encoding
把每个类别直接映射成一个整数。
- 男→0,女→1
- 红→0,绿→1,蓝→2
优点:简单、不升维度
缺点:会引入虚假顺序
模型可能误以为:蓝(2) > 绿(1) > 红(0)
适合:有序类别(低<中<高、小<中<大)
2. 独热编码 One-Hot Encoding(最常用)
每个类别单独一列,用 0/1 表示是否属于该类。
- 红 → [1,0,0]
- 绿 → [0,1,0]
- 蓝 → [0,0,1]
优点:无顺序误解,最安全
缺点:类别多会维度爆炸
适合:无序、类别少的特征(性别、颜色、品种)
3. 目标编码 Target Encoding(高级上分技巧)
用该类别对应的目标均值来编码。
例如:颜色→购买率
- 红色类别购买率 0.7 → 红色=0.7
- 蓝色类别购买率 0.3 → 蓝色=0.3
优点:不降信息、不升维度
缺点:容易信息泄露/过拟合
适合:树模型(XGBoost、LightGBM、RF)
4. 二进制编码 Binary Encoding
先标签编码 → 再转二进制 → 按位展开
既保留信息,又不会维度爆炸。
适合:类别非常多的特征(城市、商品ID)
三、一张表看懂怎么选编码
| 编码方法 | 无序类别 | 有序类别 | 类别很多 | 优点 | 缺点 |
|---|---|---|---|---|---|
| 标签编码 | ❌不适合 | ✅适合 | ✅ | 简单、快 | 引入顺序 |
| 独热编码 | ✅最适合 | ❌不适合 | ❌爆炸 | 安全、通用 | 维度爆炸 |
| 目标编码 | ✅适合 | ✅适合 | ✅适合 | 强表达力 | 易过拟合 |
| 二进制编码 | ✅适合 | ✅适合 | ✅极适合 | 低维、高效 | 可解释性差 |
四、最简单选择口诀
- 有序类别(低中高)→ 标签编码
- 无序、类别少 → 独热编码
- 树模型、类别多 → 目标编码
- 超多类别(ID类)→ 二进制/Embedding
五、完整可运行代码(含3种编码+对比+可视化)
直接复制运行,包含:数据集、标签编码、独热编码、目标编码、模型对比、PCA可视化。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# ======================
# 1. 构造数据集
# ======================
np.random.seed(42)
n = 500
df = pd.DataFrame({
"Color": np.random.choice(["Red","Green","Blue","Yellow"], n),
"City": np.random.choice(["Beijing","Shanghai","Guangzhou","Shenzhen"], n),
"Rating": np.random.choice(["Low","Medium","High"], n),
"Age": np.random.randint(18,60,n),
"Income": np.random.randint(3000,15000,n),
})
# 构造标签
df["Purchased"] = (
((df["Color"]=="Red") & (df["Rating"]=="High")) |
((df["City"].isin(["Beijing","Shanghai"])) & (df["Age"]<30))
).astype(int)
print("原始数据:")
print(df.head())
# ======================
# 2. 标签编码
# ======================
df["Color_LE"] = LabelEncoder().fit_transform(df["Color"])
df["City_LE"] = LabelEncoder().fit_transform(df["City"])
df["Rating_LE"] = df["Rating"].map({"Low":0,"Medium":1,"High":2})
# ======================
# 3. 独热编码
# ======================
df_onehot = pd.get_dummies(df[["Color","City","Rating"]])
# ======================
# 4. 目标编码
# ======================
color_mean = df.groupby("Color")["Purchased"].mean()
df["Color_TE"] = df["Color"].map(color_mean)
# ======================
# 5. 编码分布可视化
# ======================
plt.figure(figsize=(16,10))
plt.subplot(331)
sns.countplot(x=df["Color"])
plt.title("原始颜色分布")
plt.subplot(332)
sns.histplot(x=df["Color_LE"])
plt.title("标签编码")
plt.subplot(333)
sns.histplot(x=df["Color_TE"])
plt.title("目标编码")
plt.show()
# ======================
# 6. 模型效果对比
# ======================
X1 = df[["Color_LE","City_LE","Rating_LE","Age","Income"]]
X2 = pd.concat([df_onehot, df[["Age","Income"]]], axis=1)
X3 = df[["Color_TE","City_LE","Rating_LE","Age","Income"]]
y = df["Purchased"]
def test_acc(X):
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=42)
m = RandomForestClassifier(random_state=42)
m.fit(X_train,y_train)
return accuracy_score(y_test,m.predict(X_test))
print("标签编码准确率:", test_acc(X1))
print("独热编码准确率:", test_acc(X2))
print("目标编码准确率:", test_acc(X3))
# ======================
# 7. PCA 空间分布对比
# ======================
def pca_plot(X, title):
pca = PCA(2)
x_pca = pca.fit_transform(X)
plt.scatter(x_pca[:,0],x_pca[:,1],c=y,cmap="coolwarm")
plt.title(title)
plt.show()
pca_plot(X1, "Label Encoding")
pca_plot(X2, "One-Hot Encoding")
pca_plot(X3, "Target Encoding")
六、编码常见误区(面试/作业必看)
- 对无序特征用标签编码 → 模型学错规律
- 类别太多还用独热 → 维度爆炸、训练变慢
- 目标编码不做平滑 → 严重过拟合
- 先编码再划分数据集 → 信息泄露
- 树模型用独热 → 效果不如目标编码
七、总结(背诵版)
- 数据编码 = 文字类别 → 数字
- 有序 → 标签编码
- 无序少类 → 独热编码
- 树模型多类 → 目标编码
- 编码选对,模型效果直接起飞

1954

被折叠的 条评论
为什么被折叠?



