文章目录
- 1. Univariate Feature Selection 单变量特征选择
- 2. L1 regularization L1正则
learn from https://www.kaggle.com/learn/feature-engineering
上一篇:Feature Engineering 特征工程 3. Feature Generation
经过各种编码和特征生成后,通常会拥有成百上千个特征。这可能导致两个问题:
- 首先,拥有的特征越多,就越有可能过拟合
- 其次,拥有的特征越多,训练模型和优化超参数所需的时间就越长。使用较少的特征可以加快预测速度,但会降低预测准确率
为了解决这些问题,使用特征选择技术来为模型保留最丰富的特征
1. Univariate Feature Selection 单变量特征选择
最简单,最快的方法是基于单变量
统计检验
- 统计
label
对每个单一特征的依赖程度 - 在
scikit-learn
特征选择模块中,feature_selection.SelectKBest
返回 K 个最佳特征 - 对于分类问题,该模块提供了三种不同的评分功能:χ2\chi^2χ2,
ANOVA F-value
和mutual information score
F-value
测量特征变量和目标之间的线性相关性。这意味着如果是非线性关系,得分可能会低估特征与目标之间的关系mutual information score
是非参数的,可以捕获非线性关系
from sklearn.feature_selection import SelectKBest, f_classiffeature_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
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
,选择特征
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
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]])
- 可以看见,两种情况下,选择了不同的特征
- 现在,我们需要把得到的特征数值,转换回去,并丢弃其他未选择的特征
# 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
,需要丢弃它们
# 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
一起使用,来选择非零系数
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModeltrain, 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
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,以便获得选定的特征列
# 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正则化的特征选择速度也会很慢
- 在大型数据集上,单变量测试将更快,但预测性能可能会更差
完成课程和练习,获得证书一张,继续加油!🚀🚀🚀
上一篇:Feature Engineering 特征工程 3. Feature Generation