数据预处理与特征工程:数据清洗、归一化与标准化、特征选择、PCA降维

说实话,做决策算法这些年,我踩过最大的坑往往不是模型选错了,而是数据没处理好。你想想看,垃圾数据喂进去,再牛的算法也白搭。这一章咱们就聊聊数据预处理和特征工程,我把这些年积累的实战经验都抖出来。

数据清洗——别让脏数据毁了你的模型

我记得刚入行那会儿,接手一个信贷风控项目。数据量挺大,几十万条样本。我兴冲冲地跑了个逻辑回归,结果AUC只有0.52,跟抛硬币差不多。排查了两天,发现是某个字段有大量空值,程序默认填了-1,直接把模型带偏了。嗯,从那以后,数据清洗成了我第一个检查项。

缺失值处理

缺失值怎么搞?我一般分三步走:

  1. 先看缺失比例——超过70%的字段,我通常直接扔掉。信息量太少,补了也是噪声。
  2. 再看缺失模式——是随机缺失还是有规律?比如用户收入字段,高收入人群往往不愿意填,这就不是随机缺失。
  3. 最后选填充策略——数值型用中位数或均值,分类型用众数。我个人习惯用中位数,因为它对异常值不敏感。

核心原则:缺失值处理没有银弹。我在项目中试过用模型预测缺失值,效果反而不好,因为预测本身就有误差,误差会层层传递。简单方法往往更稳健。

异常值检测

异常值这东西,说白了就是数据里的「刺头」。我常用的方法有两种:

  • 3σ原则——数据服从正态分布时,超过均值±3倍标准差的值视为异常。简单粗暴,但好用。
  • 箱线图法——用四分位数来界定。Q1-1.5IQR和Q3+1.5IQR之外的都是异常。这个方法不要求数据分布,适用范围更广。

注意:异常值不一定要删除。我曾经处理过一个电商数据,发现「购买金额」字段有个100万的记录,以为是异常,结果一查是公司大客户采购。所以,先搞清楚异常值是怎么来的,再决定怎么处理。

归一化与标准化——让特征站在同一起跑线

为什么需要归一化?你想想看,一个特征取值范围是0-1,另一个是0-10000,模型会天然认为后者更重要。这显然不合理。

Min-Max归一化

公式很简单:(x - min) / (max - min)。把数据压缩到[0,1]区间。我一般在神经网络里用这个,因为激活函数对输入范围有要求。

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
X_normalized = scaler.fit_transform(X)

Z-score标准化

公式:(x - mean) / std。处理后数据均值为0,标准差为1。这个更适合有异常值的情况,因为它不依赖最大值最小值。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)

我的经验:如果你用树模型(随机森林、XGBoost),归一化其实没啥用。树模型是基于分裂点的,不受特征尺度影响。但如果你用SVM、KNN、神经网络,归一化是必须的。我有个项目,KNN没做归一化,准确率只有65%,做完直接飙到82%。

特征选择——去芜存菁的艺术

特征不是越多越好。我见过有人搞了200个特征,模型训练要跑一整天,效果还不如20个关键特征。特征选择就是帮你找到那20个「关键先生」。

过滤式(Filter)

先算特征和目标的相关性,再选特征。速度快,适合高维数据。

方法 适用场景 我的评价
方差选择法 特征值变化很小的场景 简单但粗糙,我一般用它做第一道筛选
卡方检验 分类问题,特征和标签都是离散的 文本分类里特别好用
互信息法 能捕捉非线性关系 我最喜欢的方法,就是计算量稍大

包裹式(Wrapper)

把特征选择当成搜索问题。每次选一个特征子集,训练模型看效果。效果最好,但计算量最大。

  • 递归特征消除(RFE)——每次去掉最不重要的特征,递归直到达到目标特征数。我有个项目用RFE从50个特征选到15个,AUC反而提升了0.03。
  • 前向/后向搜索——前向是逐步加特征,后向是逐步减特征。数据量小的时候可以试试。

避坑指南:我曾经在100维的数据上跑包裹式选择,跑了整整两天没出结果。后来改用过滤式+嵌入式组合,半小时搞定。高维数据慎用包裹式。

嵌入式(Embedded)

特征选择和模型训练同时进行。最典型的就是L1正则化(Lasso)。

from sklearn.linear_model import Lasso

lasso = Lasso(alpha=0.01)
lasso.fit(X_train, y_train)
# 系数为0的特征就是被剔除的
selected_features = X.columns[lasso.coef_ != 0]

树模型的特征重要性也是嵌入式方法。我常用XGBoost的feature_importances_来快速筛选特征,效果不错。

PCA降维——化繁为简的利器

PCA说白了就是找数据变化最大的方向,把高维数据投影到低维空间。我刚开始学的时候觉得这玩意儿很玄乎,后来用多了才发现,它就是线性代数里的特征值分解。

核心思想

PCA做三件事:

  1. 去中心化——每个特征减去均值
  2. 找主成分——计算协方差矩阵的特征向量,特征值越大,这个方向越重要
  3. 降维——选前k个特征向量,把数据投影过去

实战代码

from sklearn.decomposition import PCA
import numpy as np

# 假设X是1000个样本,50个特征
pca = PCA(n_components=0.95)  # 保留95%的方差
X_pca = pca.fit_transform(X)

print(f"原始维度: {X.shape[1]}")
print(f"降维后维度: {X_pca.shape[1]}")
print(f"各主成分方差占比: {pca.explained_variance_ratio_}")

我的习惯:我不会硬性指定降维到多少维,而是设置一个方差保留比例,比如95%。这样既能压缩数据,又不会丢失太多信息。另外,PCA之前一定要做标准化,否则量纲大的特征会主导主成分方向。

什么时候用PCA?

  • 可视化——降到2维或3维,画个散点图看看数据分布
  • 去噪——PCA能过滤掉方差小的噪声成分
  • 加速训练——特征太多时,降维能大幅提升训练速度

注意:PCA后的特征失去了可解释性。每个主成分都是原始特征的线性组合,你没法说「这个主成分代表年龄」。如果业务方要求解释模型,PCA可能不是好选择。

知识体系总览

下面这张图是我梳理的本章知识结构,方便你快速回顾:

数据预处理与特征工程知识体系 数据预处理与特征工程 数据清洗 缺失值处理 异常值检测 归一化与标准化 Min-Max归一化 Z-score标准化 特征选择 过滤式(Filter) 包裹式(Wrapper) 嵌入式(Embedded) PCA降维 去中心化 找主成分 投影降维 核心原则:数据质量决定模型上限 先清洗 → 再变换 → 后选择 → 最后降维

数据预处理这块,说白了就是「磨刀不误砍柴工」。我见过太多人急着调模型参数,结果数据里一堆问题,白白浪费时间。先把数据收拾利索了,后面的事情就顺了。

可可精品资料库