特征工程
特征工程
特征工程是机器学习中将原始数据转换为更能代表潜在问题的特征的过程。好的特征工程能够显著提升模型性能,是数据科学家的核心技能之一。
特征构造
特征构造是根据领域知识从原始数据创建新特征的过程。
import pandas as pd
import numpy as np
from sklearn.preprocessing import PolynomialFeatures
# 创建示例数据
data = {
'长度': [10, 20, 30, 40, 50],
'宽度': [5, 10, 15, 20, 25],
'高度': [2, 4, 6, 8, 10]
}
df = pd.DataFrame(data)
# 手动构造特征
df['体积'] = df['长度'] * df['宽度'] * df['高度']
df['表面积'] = 2 * (df['长度'] * df['宽度'] + df['长度'] * df['高度'] + df['宽度'] * df['高度'])
df['长宽比'] = df['长度'] / df['宽度']
print("构造的新特征:")
print(df['体积', '表面积', '长宽比'](/notes/--))
多项式特征
多项式特征通过创建特征的交互项和高次项来增强模型的表达能力。
# 创建多项式特征
poly = PolynomialFeatures(degree=2, include_bias=False)
X = df['长度', '宽度', '高度'](/notes/--).values
X_poly = poly.fit_transform(X)
print("多项式特征名称:")
print(poly.get_feature_names_out())
print(f"\n原始特征数: {X.shape[1]}")
print(f"多项式特征数: {X_poly.shape[1]}")
print("\n多项式特征示例:")
print(X_poly[:3])
对数变换和Box-Cox变换
对于偏态分布的数据,可以使用变换使其更接近正态分布。
from sklearn.preprocessing import PowerTransformer
import matplotlib.pyplot as plt
# 创建偏态数据
np.random.seed(42)
skewed_data = np.random.exponential(scale=2, size=1000).reshape(-1, 1)
# 对数变换
log_transformed = np.log1p(skewed_data)
# Box-Cox变换
boxcox_transformer = PowerTransformer(method='box-cox')
boxcox_transformed = boxcox_transformer.fit_transform(skewed_data)
# Yeo-Johnson变换
yeojohnson_transformer = PowerTransformer(method='yeo-johnson')
yeojohnson_transformed = yeojohnson_transformer.fit_transform(skewed_data)
# 可视化变换效果
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes[0, 0].hist(skewed_data, bins=30, edgecolor='black')
axes[0, 0].set_title('原始数据')
axes[0, 1].hist(log_transformed, bins=30, edgecolor='black')
axes[0, 1].set_title('对数变换')
axes[1, 0].hist(boxcox_transformed, bins=30, edgecolor='black')
axes[1, 0].set_title('Box-Cox变换')
axes[1, 1].hist(yeojohnson_transformed, bins=30, edgecolor='black')
axes[1, 1].set_title('Yeo-Johnson变换')
plt.tight_layout()
plt.show()
分箱(Binning)
分箱是将连续变量离散化的过程,可以处理异常值并捕捉非线性关系。
# 等宽分箱
df['长度_等宽'] = pd.cut(df['长度'], bins=3, labels=['短', '中', '长'])
# 等频分箱
df['长度_等频'] = pd.qcut(df['长度'], q=3, labels=['低', '中', '高'])
# 自定义分箱
bins = [0, 15, 35, 60]
labels = ['小', '中', '大']
df['长度_自定义'] = pd.cut(df['长度'], bins=bins, labels=labels)
print("分箱结果:")
print(df['长度', '长度_等宽', '长度_等频', '长度_自定义'](/notes/-_-_-_))
特征缩放
特征缩放确保不同尺度的特征对模型的影响是均衡的。
from sklearn.preprocessing import StandardScaler, RobustScaler, MaxAbsScaler
X = df['长度', '宽度', '高度'](/notes/--).values
# StandardScaler: 标准化
standard_scaler = StandardScaler()
X_standard = standard_scaler.fit_transform(X)
# RobustScaler: 对异常值鲁棒的缩放
robust_scaler = RobustScaler()
X_robust = robust_scaler.fit_transform(X)
# MaxAbsScaler: 保持稀疏性
maxabs_scaler = MaxAbsScaler()
X_maxabs = maxabs_scaler.fit_transform(X)
print("StandardScaler结果:")
print(X_standard)
print("\nRobustScaler结果:")
print(X_robust)
特征选择
特征选择是从大量特征中选择最相关特征的过程。
from sklearn.feature_selection import SelectKBest, f_classif, RFE
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
# 创建分类数据
X, y = make_classification(n_samples=1000, n_features=20, n_informative=10,
n_redundant=5, random_state=42)
# 方法1: 基于方差的特征选择
from sklearn.feature_selection import VarianceThreshold
var_selector = VarianceThreshold(threshold=0.5)
X_var = var_selector.fit_transform(X)
print(f"方差选择后特征数: {X_var.shape[1]}")
# 方法2: 单变量特征选择
selector = SelectKBest(score_func=f_classif, k=10)
X_selected = selector.fit_transform(X, y)
print(f"单变量选择后特征数: {X_selected.shape[1]}")
# 查看特征得分
feature_scores = pd.DataFrame({
'特征': range(X.shape[1]),
'得分': selector.scores_
})
print("\n特征得分:")
print(feature_scores.sort_values('得分', ascending=False))
使用随机森林进行特征重要性评估
# 训练随机森林模型
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)
# 获取特征重要性
feature_importance = pd.DataFrame({
'特征': range(X.shape[1]),
'重要性': rf.feature_importances_
}).sort_values('重要性', ascending=False)
print("随机森林特征重要性:")
print(feature_importance.head(10))
# 递归特征消除(RFE)
rfe = RFE(estimator=rf, n_features_to_select=10)
X_rfe = rfe.fit_transform(X, y)
print(f"\nRFE选择的特征数: {X_rfe.shape[1]}")
print(f"被选择的特征: {np.where(rfe.support_)[0]}")
特征工程实践建议
- 理解业务背景:特征构造需要结合领域知识
- 可视化探索:通过可视化发现数据的分布和关系
- 迭代优化:特征工程是一个迭代过程
- 注意数据泄露:特征选择应在训练集上进行
- 自动化工具:使用Featuretools等工具加速特征工程
特征工程是机器学习项目中最耗时但最有价值的环节。掌握特征工程技术,能够帮助我们构建更强大、更准确的机器学习模型。