Python如何获取相关系数绝对值之和最小的特征子集
优化实现方案
你当前的场景是4个变量选3个,本质等价于排除1个变量,可以利用相关矩阵的对称性实现无显式循环的高效计算,比原嵌套循环的实现效率高数十倍,且代码更简洁:
步骤1:预处理相关矩阵
首先将你的DataFrame转为行列均为变量名的标准相关矩阵格式,避免后续频繁查询取值:
import pandas as pd import numpy as np # 你的示例数据 foo = pd.DataFrame({'vars': ['col_a', 'col_b', 'col_c', 'col_d'], 'col_a': [1, 0.9, 0.04, 0.03], 'col_b': [0.9,1,0.05,0.03], 'col_c': [0.04, 0.05, 1, -0.04], 'col_d': [0.03, 0.03, -0.04,1]}) # 转为标准相关矩阵(索引和列都是变量名) corr_mat = foo.set_index('vars') # 取相关系数绝对值,对角线置0(自相关不需要计算) abs_corr = corr_mat.abs() np.fill_diagonal(abs_corr.values, 0)
步骤2:用排除法计算最优三元组
4个变量的所有两两相关绝对值总和是固定值,排除1个变量后,剩余3个变量的两两相关绝对值总和 = 总总和 - 被排除变量和其他3个变量的相关绝对值总和。要让剩余总和最小,只需要找被排除变量的相关和最大即可:
# 计算所有两两相关绝对值的总总和(因为矩阵对称,每个对算两次,除以2去重) total_sum = abs_corr.sum().sum() / 2 # 每个变量和其他所有变量的相关绝对值之和 var_corr_sum = abs_corr.sum(axis=1) # 找要排除的变量(和最大的那个) exclude_col = var_corr_sum.idxmax() # 得到最优三元组 best_triple = tuple(col for col in corr_mat.columns if col != exclude_col) # 对应的最小和 min_sum = total_sum - var_corr_sum[exclude_col] print(f"最优三元组:{best_triple},对应两两相关绝对值和:{min_sum}")
通用场景(n个变量选k个)实现
如果后续需要扩展到任意n选k的场景,也可以用向量化操作代替嵌套for循环,性能远高于原实现:
import itertools k = 3 cols = corr_mat.columns.to_list() # 生成所有k元组合 combs = list(itertools.combinations(cols, k)) # 批量计算每个组合的两两和 comb_sums = [abs_corr.loc[list(c), list(c)].sum().sum()/2 for c in combs] # 找最小值对应的组合 best_comb = combs[np.argmin(comb_sums)]
优化点说明
- 原实现中每次调用
query取值的开销非常大,转为索引直接取值后性能提升明显 - 利用相关矩阵的对称性避免重复计算,不需要嵌套遍历两两组合
- 特殊场景下用排除法完全不需要遍历组合,时间复杂度从O(C(n,k)*k²)降到O(n²)
内容的提问来源于stack exchange,提问作者quant
相关产品推荐
相关产品推荐

