特征工程基础:提取、选择、降维

做数据项目这些年,我最大的感触就是——数据和特征决定了上限,模型只是逼近这个上限。说白了,你拿一堆原始日志直接塞进XGBoost,效果往往还不如人家精心构造几个比率特征后拿线性回归。今天我们就来聊聊特征工程的三个核心动作:提取、选择、降维。

一句话总结三者的分工:

  • 特征提取:从原始数据里“变”出新特征(文本→词频、时间→星期)
  • 特征选择:从现有特征堆里“挑”出有用的(过滤、包裹、嵌入)
  • 特征降维:把高维特征“压缩”到低维空间(PCA、t-SNE)

1. 特征提取 – 从原始数据中创造信息

特征提取,说白了就是把非结构化或半结构化的数据,转化成数值向量。举个最典型的例子:文本数据。你拿到一堆客户评论,计算机不认识汉字,你必须把它变成数字。我个人最喜欢的入门方式就是 TF-IDF。

from sklearn.feature_extraction.text import TfidfVectorizer

corpus = [
    "这个产品性价比很高",
    "质量太差,用了三天就坏了",
    "物流很快,包装也不错"
]
vectorizer = TfidfVectorizer(max_features=100)
X = vectorizer.fit_transform(corpus)
print(X.shape)  # (3, 100)

你可能会问:为什么不用简单的词袋(CountVectorizer)?我在一个用户满意度预测项目里踩过坑——直接用词频,结果“的”、“了”这些高频停用词把重要信号淹没了。换成TF-IDF后,模型AUC直接提升了4个点。

除了文本,时间序列特征提取也很常见。比如计算滑动窗口均值、标准差、差分、傅里叶变换。我记得有一次做电商购买间隔预测,我把原始时间戳转成了“距上次购买天数”、“最近7天购买频次”等特征,效果比直接扔时间戳好太多。

经验之谈:特征提取时,尽量保持业务可解释性。不要为了提特征而提特征,比如瞎拼凑高阶多项式。我在信贷风控项目中见过有人把“收入”和“年龄”相乘得到一个新特征,结果模型过拟合得一塌糊涂。

2. 特征选择 – 去芜存菁

特征多了未必是好事。我遇到过几十万维度的特征,全放进去模型训练慢不说,还容易过拟合。特征选择帮你砍掉冗余和无关的特征,提升泛化能力。

常用的三类方法:

类别 原理 典型方法 适用场景
过滤法 统计指标打分,与模型无关 卡方检验、互信息、方差阈值 特征量极大,快速筛选
包裹法 用目标模型评估特征子集 递归特征消除(RFE) 特征较少,精度要求高
嵌入法 模型自身输出特征重要性 L1正则(Lasso)、树模型 feature_importances_ 特征较多,训练可接受

我个人的习惯:先拿过滤法快速砍掉明显低相关的特征,比如方差接近0的列。然后再用嵌入法(比如LightGBM的feature importance)选出Top-K。最后如果时间允许,再用包裹法微调。这样做下来,项目节奏又快效果又稳。

# 过滤法示例:方差阈值
from sklearn.feature_selection import VarianceThreshold

selector = VarianceThreshold(threshold=0.01)
X_selected = selector.fit_transform(X)
print(f"原始维度: {X.shape[1]}, 保留维度: {X_selected.shape[1]}")

注意一点:过滤法和包裹法的组合使用,我曾经在一个电商CTR预估项目里吃过亏——先用卡方过滤到2000维,再用递归特征消除,结果卡方把一些虽然方差小但对埋点事件很敏感的特征给干掉了。建议你过滤法留的阈值宽一点,别太狠。

避坑指南:千万不要在特征选择前看一眼模型性能就拍脑袋定阈值。要结合交叉验证,否则容易陷入“假信号”陷阱。

3. 特征降维 – 压缩不丢失结构

降维和特征选择不同。选择是“挑”,降维是“变”。PCA将原始特征线性组合成新特征,t-SNE更关注高维空间中的局部邻居关系。

我常用的三个工具:

  • PCA:线性降维,适合数据可视化、去噪。我在做基因表达数据时,几万个基因用PCA降到50维,分类效果反而更好,因为去掉了噪声。
  • LDA:有监督降维,最大化类间距离。适合分类问题。
  • t-SNE / UMAP:非线性降维,主要用来可视化,不适合作为建模输入。
from sklearn.decomposition import PCA

pca = PCA(n_components=0.95)  # 保留95%方差
X_pca = pca.fit_transform(X_scaled)
print(f"降维后维度: {X_pca.shape[1]}")

这里有个容易翻车的细节:PCA是基于方差的,所以特征必须标准化。否则一个数值范围大的特征就会主导主成分。我曾有一次忘了标准化,结果PCA的前两个主成分几乎全被“年龄”这个变量决定了,完全不表达数据结构。嗯,从那以后再也不敢跳过 preprocessing。

技巧:遇到稀疏高维数据,比如文本TF-IDF特征,PCA效果往往不好。可以试试截断SVD(TruncatedSVD),它不需要先稠密化。

4. 三者的关系与选择策略

很多同学会把这三个步骤搞混,甚至串在一起用。其实它们各有侧重,可以组合,但顺序有讲究。我画了一张我日常用的决策流程图:

特征工程核心三步骤 · 决策流程 原始数据 特征提取 特征选择 特征降维 建模 说明:特征提取是必须先做的;然后根据数据量和业务需求,二选一或组合使用特征选择与降维。

我一般遵循两条原则:

  • 特征数量百万级以上 → 先特征选择(过滤法快速砍),再考虑是否降维。
  • 特征少但噪声大 → 直接上PCA或LDA去噪,降维后再建模。

如果你既做选择又做降维,记得先选择再降维。否则降维后的新特征很难解释,选择也失去了意义。

曾经踩过的坑:有一次我在文本分类项目中,先做了PCA降到100维,再用递归特征消除。结果RFE把所有主成分都保留了,等于白干。顺序错了,耗费大量算力还毫无收益。

好了,特征工程的基础三件套就聊到这儿。不管是用深度学习还是传统模型,这三步都是绕不开的硬功夫。你可以在自己的项目里多试试不同组合,慢慢就会形成自己的套路。