特征工程

第23课:特征构造

数值特征变换、时间特征、文本特征、交叉特征、自动特征工程

1. 特征构造原则

"数据和特征决定上限,模型只是逼近上限。"

2. 数值变换

对数变换(右偏数据)、Box-Cox(最优λ)、分位数变换(映射到正态)、分箱(连续→离散)

3. 时间特征

基础(年月日时分秒、星期几、是否周末)、周期编码(sin/cos保持23点和0点相邻)、滑动窗口

4. 文本特征

文本长度、词数、TF-IDF、N-gram(捕捉词序)、主题特征(LDA/NMF)

5. 交叉与自动特征工程

类别交叉(城市×职业)、多项式特征。Featuretools(DFS)、OpenFE(自动排序)

Python代码实现与验证

💡 代码说明:以下代码使用 Python / Scikit-learn 实现,已实机运行验证。

完整代码


import numpy as np
import pandas as pd
from sklearn.preprocessing import QuantileTransformer, KBinsDiscretizer, PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import make_regression
np.random.seed(42)

income = np.random.exponential(50000, 1000)
print("收入偏度: {:.2f}".format(pd.Series(income).skew()))
log_inc = np.log1p(income)
print("对数后偏度: {:.2f}".format(pd.Series(log_inc).skew()))
sqrt_inc = np.sqrt(income)
print("平方根后偏度: {:.2f}".format(pd.Series(sqrt_inc).skew()))

qt = QuantileTransformer(output_distribution='normal', random_state=42)
qt_inc = qt.fit_transform(income.reshape(-1,1)).ravel()
print("分位数变换后偏度: {:.2f}".format(pd.Series(qt_inc).skew()))

print("\n=== 分箱 ===")
X = np.random.uniform(0,100,500).reshape(-1,1)
for strategy in ['uniform','quantile','kmeans']:
    kb = KBinsDiscretizer(n_bins=5, strategy=strategy, encode='ordinal')
    Xb = kb.fit_transform(X)
    print("{}: 每箱{}".format(strategy, np.bincount(Xb.ravel().astype(int))))

print("\n=== 多项式特征 ===")
Xr,yr = make_regression(n_samples=200, n_features=2, noise=10, random_state=42)
for d in [1,2,3]:
    Xp = PolynomialFeatures(d, include_bias=False).fit_transform(Xr)
    s = cross_val_score(LinearRegression(), Xp, yr, cv=5, scoring='r2')
    print("degree={}: 特征数={} R2={:.4f}".format(d, Xp.shape[1], s.mean()))

dates = pd.date_range('2024-01-01', periods=100, freq='h')
df = pd.DataFrame({'ts':dates})
df['hour']=df['ts'].dt.hour; df['dow']=df['ts'].dt.dayofweek
df['is_wknd']=(df['dow']>=5).astype(int)
df['h_sin']=np.sin(2*np.pi*df['hour']/24); df['h_cos']=np.cos(2*np.pi*df['hour']/24)
print("\n时间特征:\n{}".format(df.head(3).to_string()))

运行结果

收入偏度: 1.87 对数后偏度: -0.83 平方根后偏度: 0.60 分位数变换后偏度: 0.00 === 分箱 === uniform: 每箱[101 88 86 113 112] quantile: 每箱[100 100 100 100 100] kmeans: 每箱[ 96 82 88 116 118] === 多项式特征 === degree=1: 特征数=2 R2=0.9527 degree=2: 特征数=5 R2=0.9520 degree=3: 特征数=9 R2=0.9455 时间特征: ts hour dow is_wknd h_sin h_cos 0 2024-01-01 00:00:00 0 0 0 0.000000 1.000000 1 2024-01-01 01:00:00 1 0 0 0.258819 0.965926 2 2024-01-01 02:00:00 2 0 0 0.500000 0.866025
✅ 验证通过

深入理解:特征工程的精髓

"特征工程是决定模型上限的关键"

业界共识:好的特征工程比好的模型更重要。一个线性模型配上优秀特征可以超越复杂模型配普通特征。

特征工程流程

  1. 理解业务:领域知识是最好的特征来源
  2. EDA发现:从数据中发现模式→构造特征
  3. 变换:对数/Box-Cox处理偏态,分箱处理非线性
  4. 编码:类别→数值,选择合适编码方式
  5. 缩放:数值特征标准化/归一化
  6. 选择:删除无关/冗余特征
  7. 验证:交叉验证评估特征贡献

Kaggle竞赛中的特征工程技巧

常见特征工程错误

  1. 数据泄露:在特征构造中使用了未来信息
  2. 目标泄露:特征中包含了目标变量的信息
  3. 过拟合特征:在训练集上有效但测试集失效
  4. 忽略缺失模式:缺失本身可能是有价值的特征
  5. 不验证:没有用交叉验证确认特征的实际贡献

进阶特征工程技巧

Kaggle竞赛中的特征工程

在Kaggle竞赛中,特征工程是区分Top 1%和Top 10%的关键。以下是从顶级选手那里学到的技巧:

聚合特征:对时序数据,按实体ID聚合历史行为的统计量——均值、标准差、最小最大、趋势斜率、最近N次的均值变化。这些"在用户层面的历史摘要"往往是最强特征。
目标编码:高基数类别特征(如城市名2000+类)的杀手锏。关键:必须在5折CV内计算,使用平滑参数防止小样本类别不稳定。公式:enc = (count*mean + m*global_mean)/(count+m),m通常取10-100。
比率特征:两个相关特征的比值常常比原始特征更有信息量。贷款金额/年收入、月供/月收入、信用额度使用率等。这些比率捕捉了"相对"而非"绝对"信息。

数据泄露防范完整清单

  1. 目标泄露:特征包含目标信息——检查每个特征与目标的互信息
  2. 时间泄露:用了未来数据——特征构造时只用截止时间前的数据
  3. 组泄露:同组数据分布在训练和测试集——使用GroupKFold
  4. 预处理泄露:全数据fit scaler——用Pipeline自动处理
  5. 特征选择泄露:在CV外选特征——特征选择必须在CV内

缺失值处理策略决策树

交叉验证的常见错误

错误的交叉验证比没有交叉验证更危险——它给你虚假的信心。

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

📝 课后练习

  1. 实现本课核心算法并用Scikit-learn验证
  2. 调优关键超参数并记录性能变化
  3. 用交叉验证评估模型稳定性
  4. 与之前学过的方法对比分析
  5. 分析本课方法的失效条件
🔧
特征工匠
掌握特征构造的核心技巧