【feature selection】特征选择学习笔记

1. 什么是特征选择

  • 特征选择是特征工程的内容, 其目标是寻找最优特征子集。剔除不相关或冗余特征, 减小特征数量

    在这里插入图片描述

  • 特征选择的作用

    • (1) 过拟合的表现是模型太贴合训练数据而在测试集上表现不好, 特征选择能通过减少不相关或冗余特征降低过拟合的风险
    • (2) 在数据预处理阶段, 能够帮助识别缺失值过多, 异常值过多, 特征高度相关的特征
    • (3) 对大型数据集或实时应用来说, 能够减少计算量, 提高计算效率
    • (4) 能够提高模型的可解释性。特征选择能够帮助识别哪些特征对模型预测有影响, 从而提高模型的可解释性
    • (5) 特征选择还能降低数据维度, 同样的, 特征提取也可以降低维度

2. 特征选择与特征提取的区别

  • 如上图所示, 用数学的话来解释:

    • 特征选择后的特征是原来特征的一个子集
    • 特征提取后的新特征是原来特征的一个映射
  • 比如, 有长、宽两个特征,特征选择是根据模型的目标来选择这个特征或者选择这个特征,而特征提取是把长和宽两个特征提取成面积这个"新特征"

3. 特征选择的方法

  • 特征选择主要从两个方面考虑: 方差和相关性
    • 方差:特征是否发散。如果一个特征不发散,比如方差接近0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用
    • 相关性:特征与目标的相关性。与目标相关性高的特征,应当优选选择
3.1 Filtering过滤法
  • 基本思想:分别对每个特征 x i x_i xi,计算 x i x_i xi相对于类别标签 y y y的信息量 S ( i ) S(i) S(i),得到 n n n个结果。然后将 n n n S ( i ) S(i) S(i)按照从大到小排序,输出前前k个特征,完成特征选择。问题的关键在于如何计算信息量 S ( i ) S(i) S(i)

  • 过滤法方法如下:

    • 方差选择法
      • 先计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征
      • 不需要计算特征与标签的信息量
      • 基于各特征分布方式较为接近的时候,才能以方差的逻辑来衡量信息量,连续变量不适合用方差选择法
      • 可以使用sklearn.feature_selection库的VarianceThreshold类来选择k个最好的特征
    • 相关系数法
      • 计算各个特征对目标值的相关系数以及相关系数的P值,选择k个最好的特征
      • 相关系数是一种最简单的,能帮助理解特征和相应变量之间关系的方法。衡量的是变量之间的线性相关性,结果的取值区间为[-1, 1],-1表示表示完全负相关,+1表示完全正相关,0表示没有线性相关性
      • 速度快,易于计算,数据清洗第一阶段可执行
      • 明显缺陷是只对线性关系敏感,非线性关系即使一一对应,P相关系数也可能为0
      • 可以用sklearn.feature_selection库的SelectKBest类结合相关系数来选择k个最好的特征
    • 卡方验证
      • 构建卡方分布统计量,检验自变量n个取值因变量m个取值的相关性
      • 可以用sklearn.feature_selection库的SelectKBest类结合卡方检验来选择k个最好的特征
    • 互信息法和最大信息系数法
      • 采用互信息评价定性自变量对定性因变量的相关性
      • 互信息直接用于特征选择不方便,不方便归一化且不方便计算连续数据,需要对连续数据进行离散化
      • 最大信息系数法统计定量数据
      • 可以用sklearn.feature_selection库的SelectKBest类结合最大信息系数法来选择k个最好的特征
3.2 Wrapper包装法
  • 基本思想:基于留出法hold-out,对每一个待选的特征子集,都在训练集上训练一遍模型,然后在测试集上根据误差大小选择出特征子集。需要先选定特定算法,通常选用普遍效果较好的算法(想训练什么算法就选择什么算法进行评估),例如RF、SVM、KNN等

  • 包装法方法如下:

    • 前向搜索:每次增量从剩余未选特征中选出一个加入特征集,待达到阈值或n时,从所有的特征集中选出错误率最小的特征集。 O ( n 2 ) O(n^{2} ) O(n2)的时间复杂度
    • 后向搜索:增量减,开始特征集包含{1,2,…,n},每次删除一个特征,直到达到阈值或为空。选择最佳的特征集。 O ( n 2 ) O(n^{2} ) O(n2)的时间复杂度
    • 递归特征消除法:使用基模型进行多轮训练,每轮根据学习器返回的coeff和feature_importance来消除若干权重较低的特征,再根据新的特征集进行下一轮训练
3.3 Embedding嵌入法
  • 基本思想:先使用某些机器学习的模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征,类似于Filtering,只不过系数是通过训练得到的
  • 嵌入法的方法:
    • 基于惩罚项的特征选择法:使用sklearn.feature_selection库的SelectFromModel类结合带L1以及L2惩罚项的基本模型如LR/SVM模型,来选择特征
    • 基于树模型的特征选择法:树模型中选择GBT决策树作为基模型选择特征。使用sklearn.feature_selection库的SelectFromModel类结合GBDT模型,来选择特征

4. 特征选择示例

4.1 方差选择法示例
  • 不使用基模型

  • 不计算特征与目标相关性

  • 设置过滤阈值

    import numpy as np
    from sklearn.feature_selection import VarianceThreshold
    from sklearn.datasets import make_regression
    
    # 创建一个模拟的回归数据集,但是添加一些方差很低的特征
    X, y = make_regression(n_samples=1000, n_features=20, noise=0.1)
    
    # 添加一些几乎恒定的特征
    constant_value = 10  # 设定一个几乎恒定的值
    X = np.hstack((X, np.ones((X.shape[0], 5)) * constant_value))
    
    print("X的shape: ", X.shape) # [1000, 25]
    
    # 查看原始特征的数量
    print(f"原始特征数量: {X.shape[1]}")
    
    # 初始化方差选择法,设定阈值为某个较小的值(例如,我们期望移除方差接近于0的特征)
    selector = VarianceThreshold(threshold=(.8 * (1 - .8)))  # 假设我们设定阈值为方差的20%
    
    # 在数据上拟合方差选择法
    X_new = selector.fit_transform(X)
    
    # 查看选择后的特征数量
    print(f"选择后的特征数量: {X_new.shape[1]}")
    
    # 输出被移除的特征的索引
    print(f"被移除的特征索引: {np.setdiff1d(np.arange(X.shape[1]), selector.get_support(indices=True))}")
    
    # 如果你想要查看每个特征的方差,可以使用numpy的var函数
    variances = np.var(X, axis=0)
    print(f"各特征的方差: {variances}") # 可以看到,那些方差接近0的特征(即我们添加的恒定值特征)现在已经被移除了,如下图
    
  • 被过滤掉的特征的方差:

4.2 递归特征消除法示例
  • 可以使用LR、SVM等基模型,使用的模型最好是训练任务要用的模型

  • 设置要保留的特征个数

    import numpy as np
    from sklearn.datasets import make_classification
    from sklearn.linear_model import LogisticRegression
    from sklearn.feature_selection import RFE
    from sklearn.model_selection import train_test_split
    
    # 创建一个模拟的二分类数据集,具有一些非线性关系
    # 数据集有1000个样本, 特征数20, 其中10个是与输出相关的特征, 5个冗余特征
    X, y = make_classification(n_samples=1000, n_features=20, n_informative=10, n_redundant=5, random_state=42)
    
    # 划分数据集为训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    
    # 初始化逻辑回归模型
    lr = LogisticRegression(solver='lbfgs', max_iter=1000, random_state=42)
    
    # 初始化递归特征消除对象,并设置要选择的特征数量(或者传递一个step参数来控制每次迭代中移除的特征数量)
    # 在这个例子中,我们让RFE自动决定保留的特征数量; 返回特征选择后的数
    # 参数estimator为基模型; n_features_to_select为要选择的特征数量
    rfe = RFE(estimator=lr, n_features_to_select=10, step=1, verbose=1)
    
    # 在训练数据上拟合RFE模型
    rfe.fit(X_train, y_train)
    
    # 输出被选择的特征的索引: true表示特征被选择, false表示特征被排除
    # print("Selected features indices:", rfe.support_(indices=True))
    selected_feature_indices = np.where(rfe.support_)[0]
    print("Selected feature indices:", selected_feature_indices)
    
    # 输出被选择的特征数量
    print("Number of selected features: %d" % rfe.n_features_)
    
    # 可以通过transform方法获取训练集和测试集上的所选特征
    X_train_selected = rfe.transform(X_train)
    X_test_selected = rfe.transform(X_test)
    
    # print("所选择的训练特征: ", X_train_selected)
    # print("所选择的测试特征: ", X_test_selected)
    
    # 现在可以使用X_train_selected和X_test_selected在新的逻辑回归模型上进行训练和评估
    lr_selected = LogisticRegression(solver='lbfgs', max_iter=1000, random_state=42)
    lr_selected.fit(X_train_selected, y_train)
    score = lr_selected.score(X_test_selected, y_test)
    print("Test accuracy with selected features:", score)
    
  • 被选择特征的索引:

 


 
创作不易,如有帮助,请 点赞 收藏 支持
 


 

[参考文章]

[1]. 特征选择vs特征提取
[2]. 特征工程和特征选择
[3]. 特征选择方法汇总
[4]. 百度文心一言大模型

created by shuaixio, 2024.05.24

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值