前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >专栏 | 基于 Jupyter 的特征工程手册:特征选择(五)

专栏 | 基于 Jupyter 的特征工程手册:特征选择(五)

作者头像
红色石头
发布2022-01-16 10:06:50
4250
发布2022-01-16 10:06:50
举报
文章被收录于专栏:红色石头的机器学习之路

作者:陈颖祥、杨子晗

编译:AI有道

数据预处理后,我们生成了大量的新变量(比如独热编码生成了大量仅包含0或1的变量)。但实际上,部分新生成的变量可能是多余:一方面它们本身不一定包含有用的信息,故无法提高模型性能;另一方面过这些多余变量在构建模型时会消耗大量内存和计算能力。因此,我们应该进行特征选择并选择特征子集进行建模。

项目地址:

https://github.com/YC-Coder-Chen/feature-engineering-handbook/blob/master/%E4%B8%AD%E6%96%87%E7%89%88.md

本文将介绍特征工程中的 Embedded Methods 嵌入方法。

目录:

过滤法的特征选择过程与后续的机器学习模型无关,因此过滤法可能导致较差的模型性能。

封装方法利用预定义的有监督的机器学习模型来选择最佳功能。但是,由于它们需要在大量可能的特征子集上多次训练模型,因此尽管它们通常会导致更好的性能,但它们同时也需要较长的处理时间。

嵌入式方法将特征选择过程嵌入到机器学习模型中,即利用机器学习来为每一个特征打分。嵌入式方法在创建模型时即完成了对特征子集的选择。因此,与过滤法相比,它们往往具有更好的性能。与封装方法相比,它们节省了大量的处理时间和计算能力。

三种方法的一个简单对比.

1.3.1 基于正则化模型的方法

许多机器学习模型在其损失函数中引入了正则项(L1正则或L2正则),以防止过拟合问题。线性模型(例如线性向量支持机,逻辑回归,线性回归)中的L1正则项能够有效地将某些特征的特征系数缩小为零,从而实现解的稀疏。因此,基于带正则项线性模型的特征系数,我们可以为特征打分。系数越高,往往该特征在线性模型中越重要。

我们可以使用sklearn SelectFromModel函数删除特征系数低或为零的特征。

1.3.1.1 Lasso Regression (Linear Regression with L1 Norm) 套索回归

代码语言:javascript
复制
import numpy as np
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import Lasso # 我们也可以使用带L2正则项的岭回归


# 直接载入数据集
from sklearn.datasets import fetch_california_housing
dataset = fetch_california_housing()
X, y = dataset.data, dataset.target # 利用 california_housing 数据集来演示


# 选择前15000个观测点作为训练集
# 剩下的作为测试集
train_set = X[0:15000,:]
test_set = X[15000:,]
train_y = y[0:15000]


clf = Lasso(normalize=True, alpha = 0.001)  
# 在进行线性回归前,我们需要先对变量进行缩放操作,否则回归系数大小无法比较
# alpha控制正则效果的大小,alpha越大,正则效果越强


clf.fit(train_set, train_y) # 在训练集上训练
np.round(clf.coef_ ,3)
代码语言:javascript
复制
array([ 0.346,  0.003, -0.   , -0.   , -0.   , -0.   , -0.033,  0.   ])
代码语言:javascript
复制
selector = SelectFromModel(clf, prefit=True, threshold=1e-5)
# 阈值被设置为1e-5,因此绝对系数低于1e-5的特征将被删除
# 我们还可以设置max_features参数以选择最重要的前几个特征


transformed_train = selector.transform(train_set) # 转换训练集
transformed_test = selector.transform(test_set) #转换测试集


assert np.array_equal(transformed_train, train_set[:,[0,1,6]]) 
# 选择第一个,第二个及第七个变量
assert np.array_equal(transformed_test, test_set[:,[0,1,6]])

1.3.1.2 Logistic Regression (with L1 Norm) 逻辑回归

代码语言:javascript
复制
import numpy as np
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris  # 利用iris数据作为演示数据集


# 载入数据集
iris = load_iris()
X, y = iris.data, iris.target


# iris 数据集使用前需要被打乱顺序
np.random.seed(1234)
idx = np.random.permutation(len(X))
X = X[idx]
y = y[idx]


# 选择前100个观测点作为训练集
# 剩下的50个观测点作为测试集
train_set = X[0:100,:]
test_set = X[100:,]
train_y = y[0:100]


# 在进行逻辑回归前,我们需要先对变量进行缩放操作,否则回归系数大小无法比较
from sklearn.preprocessing import StandardScaler
model = StandardScaler()
model.fit(train_set) 
standardized_train = model.transform(train_set)
standardized_test = model.transform(test_set)


clf = LogisticRegression(penalty='l1', C = 0.7, 
                         random_state=1234, solver='liblinear') 
# 我们也可以将正则项设置为 'l2'
# C控制正则效果的大小,C越大,正则效果越弱


clf.fit(standardized_train, train_y)
np.round(clf.coef_,3)
代码语言:javascript
复制
array([[ 0.   ,  1.   , -3.452, -0.159],
       [ 0.   , -1.201,  0.053,  0.   ],
       [ 0.   ,  0.   ,  1.331,  3.27 ]])
代码语言:javascript
复制
selector = SelectFromModel(clf, prefit=True, threshold=1e-5)
# 阈值被设置为1e-5,因此绝对系数低于1e-5的特征将被删除
# 我们还可以设置max_features参数以选择最重要的前几个特征


transformed_train = selector.transform(train_set) # 转换训练集
transformed_test = selector.transform(test_set) #转换测试集


assert np.array_equal(transformed_train, train_set[:,[1,2,3]]) 
# 选择第2个, 第3个及第4个变量
assert np.array_equal(transformed_test, test_set[:,[1,2,3]])

1.3.1.3 LinearSVR/ LinearSVC 线性向量支持机

代码语言:javascript
复制
# LinearSVC 用于分类问题
# LinearSVR 用于回归问题
# 这里以LinearSVR为例


import numpy as np
from sklearn.feature_selection import SelectFromModel
from sklearn.svm import LinearSVR


# 直接载入数据集
from sklearn.datasets import fetch_california_housing
dataset = fetch_california_housing()
X, y = dataset.data, dataset.target # 利用 california_housing 数据集来演示


# 选择前15000个观测点作为训练集
# 剩下的作为测试集
train_set = X[0:15000,:]
test_set = X[15000:,]
train_y = y[0:15000]


# 在进行逻辑回归前,我们需要先对变量进行缩放操作,否则回归系数大小无法比较
from sklearn.preprocessing import StandardScaler
model = StandardScaler()
model.fit(train_set) 
standardized_train = model.transform(train_set)
standardized_test = model.transform(test_set)


clf = LinearSVR(C = 0.0001, random_state = 123) 
# C控制正则效果的大小,C越大,正则效果越弱


clf.fit(standardized_train, train_y)
np.round(clf.coef_,3)
代码语言:javascript
复制
array([ 0.254,  0.026,  0.026, -0.017,  0.032, -0.01 , -0.1  , -0.037])
代码语言:javascript
复制
selector = SelectFromModel(clf, prefit=True, threshold=1e-2)
# 阈值被设置为1e-2,因此绝对系数低于1e-2的特征将被删除
# 我们还可以设置max_features参数以选择最重要的前几个特征


transformed_train = selector.transform(train_set) # 转换训练集
transformed_test = selector.transform(test_set) #转换测试集


assert np.array_equal(transformed_train, train_set[:,[0,1,2,3,4,6,7]]) 
# 仅第6个变量被删去
assert np.array_equal(transformed_test, test_set[:,[0,1,2,3,4,6,7]])

1.3.2 Tree Based Methods 基于树模型的方法

机器学习的一大分支便是基于树的机器学习模型,例如随机森林,AdaBoost,Xgboost等。您可以在我的朋友和我撰写的一系列博客中找到有关这些基于树的机器学习模型的更多介绍此处:

https://github.com/YC-Coder-Chen/Tree-Math

这些非参的树状模型在建立的过程中记录了每一个变量如何在树节点的分叉中逐步降低模型损失,并可以根据上述记录分析每个特征的特征重要性。而我们可以基于这特征重要性删去一些不重要的变量。

代码语言:javascript
复制
# 我们以随机森林为例
import numpy as np
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestRegressor


# 直接载入数据集
from sklearn.datasets import fetch_california_housing
dataset = fetch_california_housing()
X, y = dataset.data, dataset.target # 利用 california_housing 数据集来演示


# 选择前15000个观测点作为训练集
# 剩下的作为测试集
train_set = X[0:15000,:]
test_set = X[15000:,]
train_y = y[0:15000]


# 在树类机器学习模型中,我们无需缩放变量操作


clf = RandomForestRegressor(n_estimators = 50, random_state = 123)


clf.fit(train_set, train_y)
np.round(clf.feature_importances_, 3)
代码语言:javascript
复制
array([0.52 , 0.045, 0.031, 0.026, 0.027, 0.139, 0.106, 0.107])
代码语言:javascript
复制
# 可视化特征重要性
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
%matplotlib inline
importances = clf.feature_importances_
indices = np.argsort(importances)
plt.figure(figsize=(12,12))
plt.title('特征重要性')
plt.barh(range(len(indices)), importances[indices], color='seagreen', align='center')
plt.yticks(range(len(indices)),np.array(dataset.feature_names)[indices])
plt.xlabel('特征相对重要性');
代码语言:javascript
复制
selector = SelectFromModel(clf, prefit=True, threshold='median')
# 阈值被设定为'median', 即以特征重要性的中位数作为阈值,大约为0.076
# 我们还可以设置max_features参数以选择最重要的前几个特征


transformed_train = selector.transform(train_set)
transformed_test = selector.transform(test_set)
assert np.array_equal(transformed_train, train_set[:,[0,5,6,7]]) 
# 选择来第1个,第6个, 第7个及第8个特征
assert np.array_equal(transformed_test, test_set[:,[0,5,6,7]])
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档