前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Feature Engineering 特征工程 4. Feature Selection

Feature Engineering 特征工程 4. Feature Selection

作者头像
Michael阿明
发布2020-07-13 14:40:18
6610
发布2020-07-13 14:40:18
举报

经过各种编码和特征生成后,通常会拥有成百上千个特征。这可能导致两个问题:

  • 首先,拥有的特征越多,就越有可能过拟合
  • 其次,拥有的特征越多,训练模型和优化超参数所需的时间就越长。使用较少的特征可以加快预测速度,但会降低预测准确率

为了解决这些问题,使用特征选择技术来为模型保留最丰富的特征

1. Univariate Feature Selection 单变量特征选择

最简单,最快的方法是基于单变量统计检验

  • 统计label对每个单一特征的依赖程度
  • scikit-learn特征选择模块中,feature_selection.SelectKBest返回 K 个最佳特征
  • F-value测量特征变量和目标之间的线性相关性。这意味着如果是非线性关系,得分可能会低估特征与目标之间的关系
  • mutual information score是非参数的,可以捕获非线性关系
代码语言:javascript
复制
from sklearn.feature_selection import SelectKBest, f_classif

feature_cols = baseline_data.columns.drop('outcome')

# Keep 5 features 保留5个最好的特征
selector = SelectKBest(f_classif, k=5)
					# 评价函数, 保留特征数量
X_new = selector.fit_transform(baseline_data[feature_cols],
								 baseline_data['outcome'])
								 # 特征, 标签
X_new
代码语言:javascript
复制
array([[2015.,    5.,    9.,   18., 1409.],
       [2017.,   13.,   22.,   31.,  957.],
       [2013.,   13.,   22.,   31.,  739.],
       ...,
       [2010.,   13.,   22.,   31.,  238.],
       [2016.,   13.,   22.,   31., 1100.],
       [2011.,   13.,   22.,   31.,  542.]])

但是,上面犯了严重的错误,特征选择时fit,把所有数据用进去了,会造成数据泄露 我们应该只用训练集来进行fit,选择特征

代码语言:javascript
复制
feature_cols = baseline_data.columns.drop('outcome')
train, valid, _ = get_data_splits(baseline_data)

# Keep 5 features
selector = SelectKBest(f_classif, k=5)

X_new = selector.fit_transform(train[feature_cols], train['outcome'])
							#  区别,仅用 训练集
X_new
代码语言:javascript
复制
array([[2.015e+03, 5.000e+00, 9.000e+00, 1.800e+01, 1.409e+03],
       [2.017e+03, 1.300e+01, 2.200e+01, 3.100e+01, 9.570e+02],
       [2.013e+03, 1.300e+01, 2.200e+01, 3.100e+01, 7.390e+02],
       ...,
       [2.011e+03, 1.300e+01, 2.200e+01, 3.100e+01, 5.150e+02],
       [2.015e+03, 1.000e+00, 3.000e+00, 2.000e+00, 1.306e+03],
       [2.013e+03, 1.300e+01, 2.200e+01, 3.100e+01, 1.084e+03]])
  • 可以看见,两种情况下,选择了不同的特征
  • 现在,我们需要把得到的特征数值,转换回去,并丢弃其他未选择的特征
代码语言:javascript
复制
# Get back the features we've kept, zero out all other features
selected_features = pd.DataFrame(selector.inverse_transform(X_new), 
                                 index=train.index, 
                                 columns=feature_cols)
selected_features.head()

goal

hour

day

month

year

category

currency

country

category_currency

category_country

currency_country

count_7_days

time_since_last_project

0

0.0

0.0

0.0

0.0

2015.0

0.0

5.0

9.0

0.0

0.0

18.0

1409.0

0.0

1

0.0

0.0

0.0

0.0

2017.0

0.0

13.0

22.0

0.0

0.0

31.0

957.0

0.0

2

0.0

0.0

0.0

0.0

2013.0

0.0

13.0

22.0

0.0

0.0

31.0

739.0

0.0

3

0.0

0.0

0.0

0.0

2012.0

0.0

13.0

22.0

0.0

0.0

31.0

907.0

0.0

4

0.0

0.0

0.0

0.0

2015.0

0.0

13.0

22.0

0.0

0.0

31.0

1429.0

0.0

  • 我们发现逆转换回去后,未被选择的特征都是0.0,需要丢弃它们
代码语言:javascript
复制
# Dropped columns have values of all 0s, so var is 0, drop them
# 保留方差不为0的
selected_columns = selected_features.columns[selected_features.var() != 0]

# Get the valid dataset with the selected features.
valid[selected_columns].head()

year

currency

country

currency_country

count_7_days

302896

2015

13

22

31

1534.0

302897

2013

13

22

31

625.0

302898

2014

5

9

18

851.0

302899

2014

13

22

31

1973.0

302900

2014

5

9

18

2163.0

2. L1 regularization L1正则

单变量方法在做出选择决定时一次只考虑一个特征

相反,我们可以通过将所有特征包括在具有L1正则化的线性模型中来使用所有特征进行特征筛选

与惩罚系数平方的 L2(Ridge)回归相比,这种类型的正则化(有时称为Lasso)会惩罚系数的绝对大小

随着L1正则化强度的提高,对于预测目标而言次要的特征将设置为0

对于回归问题,可以使用sklearn.linear_model.Lasso 分类问题,可以使用sklearn.linear_model.LogisticRegression 这些都可以跟sklearn.feature_selection.SelectFromModel一起使用,来选择非零系数

代码语言:javascript
复制
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModel

train, valid, _ = get_data_splits(baseline_data)

X, y = train[train.columns.drop("outcome")], train['outcome']

# Set the regularization parameter C=1
logistic = LogisticRegression(C=1, penalty="l1", random_state=7).fit(X, y)
model = SelectFromModel(logistic, prefit=True)

X_new = model.transform(X)
X_new
代码语言:javascript
复制
array([[1.000e+03, 1.200e+01, 1.100e+01, ..., 1.900e+03, 1.800e+01,
        1.409e+03],
       [3.000e+04, 4.000e+00, 2.000e+00, ..., 1.630e+03, 3.100e+01,
        9.570e+02],
       [4.500e+04, 0.000e+00, 1.200e+01, ..., 1.630e+03, 3.100e+01,
        7.390e+02],
       ...,
       [2.500e+03, 0.000e+00, 3.000e+00, ..., 1.830e+03, 3.100e+01,
        5.150e+02],
       [2.600e+03, 2.100e+01, 2.300e+01, ..., 1.036e+03, 2.000e+00,
        1.306e+03],
       [2.000e+04, 1.600e+01, 4.000e+00, ..., 9.200e+02, 3.100e+01,
        1.084e+03]])

类似于单变量测试,返回具有选定特征的数组。我们要将它们转换为DataFrame,以便获得选定的特征列

代码语言:javascript
复制
# Get back the kept features as a DataFrame with dropped columns as all 0s
selected_features = pd.DataFrame(model.inverse_transform(X_new), 
                                 index=X.index,
                                 columns=X.columns)

# Dropped columns have values of all 0s, keep other columns 
selected_columns = selected_features.columns[selected_features.var() != 0]
  • 通常,使用L1正则化进行特征选择比单变量测试更强大
  • 但是在具有大量数据和大量特征的情况下,L1正则化的特征选择速度也会很慢
  • 在大型数据集上,单变量测试将更快,但预测性能可能会更差
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. Univariate Feature Selection 单变量特征选择
  • 2. L1 regularization L1正则
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档