特征工程之相关性筛选

相关性筛选 ,指的是通过计算特征之间(或特征与标签之间)的相关性 ,筛选出最有用的特征 ,剔除冗余或无关的特征。

它属于你之前看的组件列表里(特征工程组件 -> Python特征工程组件 -> 相关性筛选)的核心功能。下面我从概念、常见方法、代码实现、典型场景几个方面来讲。


一、为什么需要相关性筛选?

现实数据中,特征往往存在以下问题:

  1. 特征之间高度相关(冗余):比如"身高(cm)"和"身高(m)",信息几乎重复。

  2. 特征与标签无关:比如"用户ID"对"是否流失"没有预测力。

  3. 维度太高:几百上千个特征,训练慢、容易过拟合。

相关性筛选的目的:

  • 剔除冗余特征,减少维度。

  • 保留与标签最相关的特征。

  • 提升模型效果和训练速度。


二、相关性的两种类型

类型 衡量什么 用途
特征-特征相关性 特征之间的冗余程度 剔除冗余特征
特征-标签相关性 特征对标签的预测能力 筛选有用特征

三、常见的相关性度量方法

方法 适用数据类型 取值范围 特点
皮尔逊相关系数 连续 vs 连续 -1, 1 衡量线性关系
斯皮尔曼相关系数 连续/有序 -1, 1 衡量单调关系,抗异常值
肯德尔相关系数 有序 -1, 1 衡量一致性
卡方检验 类别 vs 类别 p值 衡量独立性
互信息 任意 vs 任意 [0, ∞) 衡量任意关系
方差膨胀因子(VIF) 连续 vs 连续 [1, ∞) 衡量多重共线性
距离相关系数 任意 vs 任意 0, 1 衡量任意关系

四、代码实现

1. 皮尔逊相关系数(pandas .corr())

复制代码
import pandas as pd
import numpy as np

# 构造数据
np.random.seed(42)
df = pd.DataFrame({
    'height_cm': [170, 175, 180, 165, 185],
    'height_m':  [1.70, 1.75, 1.80, 1.65, 1.85],  # 与 height_cm 高度相关
    'weight':    [65, 70, 75, 60, 80],
    'age':       [25, 30, 35, 40, 45],
    'label':     [0, 1, 1, 0, 1]
})

# 计算相关系数矩阵
corr_matrix = df.corr()
print(corr_matrix)

输出:

复制代码
           height_cm  height_m   weight      age     label
height_cm   1.000000  1.000000  0.998...  1.000...  0.316...
height_m    1.000000  1.000000  0.998...  1.000...  0.316...
weight      0.998...  0.998...  1.000000  0.998...  0.316...
age         1.000...  1.000...  0.998...  1.000000  0.316...
label       0.316...  0.316...  0.316...  0.316...  1.000000

2. 剔除高度相关的特征(特征-特征)

复制代码
# 找出相关性大于 0.95 的特征对
threshold = 0.95
corr_matrix_abs = corr_matrix.abs()

# 只看上三角(避免重复)
upper = corr_matrix_abs.where(np.triu(np.ones(corr_matrix_abs.shape), k=1).astype(bool))

# 找出需要删除的列
to_drop = [column for column in upper.columns if any(upper[column] > threshold)]
print("需要删除的列:", to_drop)

# 删除
df_reduced = df.drop(columns=to_drop)
print(df_reduced)

输出:

复制代码
需要删除的列: ['height_m', 'weight', 'age']
   height_cm  label
0        170      0
1        175      1
2        180      1
3        165      0
4        185      1

3. 特征-标签相关性筛选

复制代码
# 计算每个特征与 label 的相关性
corr_with_label = df.corr()['label'].drop('label')
print(corr_with_label)

# 筛选相关性绝对值大于 0.1 的特征
selected = corr_with_label[corr_with_label.abs() > 0.1].index.tolist()
print("筛选后的特征:", selected)

4. 斯皮尔曼相关系数

复制代码
# method='spearman' 或 'kendall'
corr_spearman = df.corr(method='spearman')
print(corr_spearman)

5. 卡方检验(类别 vs 类别)

复制代码
from sklearn.feature_selection import chi2
from sklearn.preprocessing import LabelEncoder

# 构造类别数据
X = np.array([
    ['男', '北京'],
    ['女', '上海'],
    ['男', '北京'],
    ['女', '广州'],
    ['男', '上海']
])
y = np.array([0, 1, 0, 1, 1])

# 先做 OneHot 或 Label 编码
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse_output=False)
X_encoded = encoder.fit_transform(X)

# 卡方检验
chi2_scores, p_values = chi2(X_encoded, y)
print("卡方值:", chi2_scores)
print("p值:", p_values)

6. 互信息(mutual_info_classif / mutual_info_regression)

复制代码
from sklearn.feature_selection import mutual_info_classif, mutual_info_regression

# 分类问题
mi_scores = mutual_info_classif(X_encoded, y, random_state=42)
print("互信息(分类):", mi_scores)

# 回归问题
# mi_scores = mutual_info_regression(X_encoded, y)
复制代码

互信息能捕捉非线性关系,比皮尔逊更通用。

7. 方差膨胀因子(VIF)------ 检测多重共线性

复制代码
from statsmodels.stats.outliers_influence import variance_inflation_factor

# VIF 需要数值型数据
X_vif = df[['height_cm', 'weight', 'age']].values

vif_data = pd.DataFrame()
vif_data['feature'] = ['height_cm', 'weight', 'age']
vif_data['VIF'] = [variance_inflation_factor(X_vif, i) for i in range(X_vif.shape[1])]
print(vif_data)

输出示例:

复制代码
     feature        VIF
0  height_cm  1234.56
1     weight   987.65
2        age  2345.67

VIF 判断标准:

  • VIF < 5:无多重共线性

  • 5 ≤ VIF < 10:中度共线性

  • VIF ≥ 10:严重共线性,建议删除

8. sklearn 的 SelectKBest + 相关性

复制代码
from sklearn.feature_selection import SelectKBest, f_classif

# 用 F 检验选前 k 个特征
selector = SelectKBest(score_func=f_classif, k=2)
X_selected = selector.fit_transform(X_encoded, y)
print("选中的特征索引:", selector.get_support(indices=True))
print("特征得分:", selector.scores_)
复制代码

9. VarianceThreshold ------ 剔除低方差特征

复制代码
from sklearn.feature_selection import VarianceThreshold

# 剔除方差小于 0.1 的特征
selector = VarianceThreshold(threshold=0.1)
X_selected = selector.fit_transform(X_encoded)
print("选中的特征索引:", selector.get_support(indices=True))
复制代码

10. 在 Pipeline 中使用

复制代码
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_encoded, y, test_size=0.3, random_state=42)

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('select', SelectKBest(score_func=f_classif, k=2)),  # 选前2个特征
    ('clf', LogisticRegression())
])

pipe.fit(X_train, y_train)
print("测试集准确率:", pipe.score(X_test, y_test))
复制代码

五、相关性筛选的常用阈值

场景 阈值建议
特征-特征相关性(剔除冗余) 0.9 或 0.95
特征-标签相关性(保留有用) 0.1 或 0.05(p值)
VIF(多重共线性) 5 或 10
互信息 看排序,选前 k 个
方差阈值 0.01 或 0.1

注意:阈值不是绝对的,要结合业务和数据特点调整。


六、典型应用场景

场景 方法
剔除冗余特征 特征-特征相关性 > 0.95
筛选有用特征 特征-标签相关性
检测多重共线性 VIF
类别特征筛选 卡方检验、互信息
非线性关系筛选 互信息、距离相关
高维数据降维 SelectKBest + 相关性
回归问题 mutual_info_regression、f_regression

七、相关性筛选的优缺点

优点

  1. 简单快速:计算成本低,容易理解。

  2. 减少维度:剔除冗余特征,加快训练。

  3. 提升可解释性:保留的特征更有业务意义。

  4. 减少过拟合:维度降低,模型更简单。

缺点

  1. 只看线性关系:皮尔逊只能捕捉线性关系,非线性要用互信息。

  2. 忽略特征组合:两个特征单独与标签不相关,组合起来可能很相关。

  3. 可能误删:相关性高不代表冗余,有时两个特征都重要。

  4. 阈值难定:0.95 还是 0.9?需要实验。

  5. 不适用于所有模型:树模型对冗余特征不敏感,筛选收益有限。


八、关键提醒

  1. 相关性 ≠ 因果性:两个特征相关,不代表一个导致另一个。

  2. 筛选参数从训练集学:相关性计算、阈值选择,只用训练集,避免数据泄露。

  3. 结合业务判断:统计上相关,业务上可能无意义,要综合判断。

  4. 互信息能捕捉非线性:线性关系用皮尔逊,非线性用互信息。

  5. 特征组合可能有用:两个单独不相关的特征,组合起来可能很强,筛选时要注意。

  6. 树模型不需要:XGBoost、LightGBM 对冗余特征不敏感,筛选收益有限。

  7. 筛选后要重新评估:筛选可能丢信息,要检查模型效果是否真的提升。


九、相关性筛选 vs 其他特征选择方法

方法 类型 特点
相关性筛选 Filter(过滤式) 快,独立于模型
卡方检验 Filter 类别特征
互信息 Filter 任意关系
RFE(递归特征消除) Wrapper(包裹式) 用模型选,慢但效果好
Lasso / L1 正则 Embedded(嵌入式) 模型自带特征选择
树模型特征重要性 Embedded 随机森林、XGBoost 自带

十、总结

相关性筛选 = 通过计算特征之间或特征与标签之间的相关性,筛选出最有用的特征。

  • 两种类型:特征-特征相关性(剔冗余)、特征-标签相关性(选有用)。

  • 常用方法:皮尔逊、斯皮尔曼、卡方、互信息、VIF。

  • sklearn 实现 :SelectKBest、VarianceThreshold、mutual_info_classif。

  • 核心价值:降维、去冗余、提升模型效果和可解释性。

  • 主要代价:只看线性、忽略组合、可能误删。

  • 关键原则:参数从训练集学;结合业务判断;树模型收益有限。

相关推荐
看-是灰机2 小时前
Milvus向量数据库
linux·运维·人工智能·机器学习·milvus
znx9392 小时前
量化交易:用理性穿越市场混沌的修行之路
人工智能·python·机器学习·期魔方
论文复现现场5 小时前
自动驾驶 BEV 模型训练,2 张 A100 80GB 够不够?显存、双卡训练与租赁成本
人工智能·深度学习·机器学习·自动驾驶·分布式训练·a100·bevformer
在所不辞兄5 小时前
为什么物理嵌入神经网络的收敛性和泛化误差缺乏统一的理论保证?
人工智能·深度学习·神经网络·机器学习·有限元
沐风___6 小时前
REA AI 逆向工程:没有源码,怎样查清软件的一个功能?
人工智能·机器学习
码爸15 小时前
支持向量机介绍与示例
算法·机器学习·支持向量机
别动我齐刘海17 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
szxinmai主板定制专家19 小时前
储能EMS + 协调控制器实战:RK3568/3576/3588+FPGA+AI 故障录波与诊断
人工智能·深度学习·机器学习·fpga开发·rk3588·rk3576·协调控制器
努力努力再努力wz20 小时前
【机器学习入门系列】从随机事件到正态分布:一文梳理概率论的核心知识
人工智能·机器学习·概率论