3、数据预处理优化:特征工程、数据清洗、归一化与标准化、降维技术(PCA)
大家好,我是你们的老朋友。今天咱们来聊聊数据预处理。说实话,我见过太多人一上来就调模型,结果跑出来的结果惨不忍睹。为什么?因为数据没洗干净,特征没选好。你想想看,垃圾进,垃圾出,这是铁律。
我个人习惯,拿到数据的第一件事,不是急着建模,而是先花 70% 的时间做预处理。这听起来有点夸张,但实际项目中,这一步往往决定了最终效果的 80%。
3.1 特征工程:从原始数据中挖金子
特征工程,说白了就是把原始数据变成模型能听懂的语言。我遇到过最典型的例子:一个电商数据集里,用户注册时间是个时间戳,模型根本看不懂。怎么办?拆!拆成年、月、日、星期几、是否节假日。模型一下子就开窍了。
常用的特征工程方法,我列几个:
- 特征提取:从文本里提取 TF-IDF,从图片里提取像素值。
- 特征构造:比如把「购买次数」和「总金额」组合成「客单价」。
- 特征选择:去掉那些跟目标变量八竿子打不着的特征。
3.2 数据清洗:别让脏数据毁了你的模型
数据清洗,听着简单,做起来全是坑。我刚开始做项目时,就吃过一次大亏。一个回归任务,数据里有个字段是「年龄」,结果有人填了 200 岁。模型训练完,预测结果直接飘了。嗯,从那以后,我每次都会先做数据清洗。
常见的脏数据问题:
- 缺失值:直接删掉?还是用均值/中位数填充?我建议先看看缺失比例。如果超过 50%,这列基本可以扔了。如果不多,用中位数填充更稳健。
- 异常值:比如收入字段出现负数。我习惯用 3σ 原则或者 IQR 方法检测,然后视情况截断或剔除。
- 重复数据:这个简单,直接去重。但要注意,有些重复是业务上合理的,别一刀切。
3.3 归一化与标准化:让特征站在同一起跑线
为什么需要归一化和标准化?你想想看,如果特征 A 的取值范围是 0~1,特征 B 是 0~10000,模型会天然觉得 B 更重要。这显然不合理。
我常用的两种方法:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| 归一化 (Min-Max Scaling) | (x - min) / (max - min) | 数据有明确边界,比如像素值 0~255 |
| 标准化 (Z-score Normalization) | (x - μ) / σ | 数据分布近似正态,或者有异常值 |
我个人习惯,如果数据里没有明显的异常值,优先用标准化。因为归一化对异常值太敏感了——一个 10000 的异常值,能把其他所有数据压缩到 0.0001 附近,模型直接废了。
代码实现也很简单:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 归一化
scaler = MinMaxScaler()
X_normalized = scaler.fit_transform(X)
3.4 降维技术(PCA):化繁为简的艺术
降维,说白了就是用更少的特征,表达尽可能多的信息。PCA(主成分分析)是我最常用的方法。它的核心思想很简单:找到数据方差最大的方向,把数据投影上去。
为什么用 PCA?我遇到过这样一个项目:特征有 1000 多个,模型训练一次要 3 小时。用 PCA 降到 50 维后,训练时间缩短到 10 分钟,效果只掉了 1%。这买卖,划算。
下面这张图,展示了 PCA 的核心逻辑:
使用 PCA 时,有几个关键点:
- 先标准化:PCA 对特征的尺度敏感。如果特征 A 是 0~1,特征 B 是 0~10000,PCA 会优先抓住 B 的方差。所以,跑 PCA 之前,一定要先做标准化。
- 选择主成分数量:我一般看累计方差贡献率。保留 95% 的方差,通常就够了。代码里用
pca.explained_variance_ratio_就能看到。 - 可解释性:降维后的特征,往往失去了物理含义。如果你需要跟业务方解释「为什么这个特征重要」,PCA 可能不太合适。这时候可以考虑 t-SNE 或者 UMAP。
代码示例:
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 先标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# PCA 降维,保留 95% 方差
pca = PCA(n_components=0.95)
X_pca = pca.fit_transform(X_scaled)
print(f"原始特征数: {X.shape[1]}")
print(f"降维后特征数: {X_pca.shape[1]}")
print(f"各主成分方差占比: {pca.explained_variance_ratio_}")
好了,数据预处理这块,核心就是这些。特征工程、数据清洗、归一化标准化、PCA 降维,每一步都值得你花时间打磨。记住,模型的好坏,90% 取决于数据质量。把数据收拾利索了,模型自然就听话了。