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

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

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


项目地址:

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


本文将介绍特征工程中的 Wrapper Methods 封装方法。


目录:


image.png


封装方法将特征选择问题视作搜索问题,即其目标为从特征子集集合中搜索出一个最佳的子集,而这一子集在模型中表现最佳。在每一步中,其在特征子集上训练模型,然后对其进行评估,并在下一步继续调整特征子集,重新训练评估,直到找到最佳子集或达到最大迭代次数为止。穷尽搜索在封装方法中为NP-Hard,故人们提出了一些方法来降低封装方法所需要的迭代次数,以便可以在有限的时间内达到一个较好的效果。


image.png


1.2.1 Deterministic Algorithms 确定性算法


在不考虑模型随机性的情况下,给定相同的数据输入,确定性算法将始终输出相同的最优特征子集。


顺序向前选择(SFS),顺序向后选择(SBS)均为确定性算法。顺序向前选择(SFS)方法将从最优单变量模型开始,然后在迭代中,其会在上一步变量子集的基础上,以穷举的方法在现有变量子集中增加一个新变量,使得新增一个变量后的变量子集可以获得最大的模型表现提升。迭代将持续直到所选变量的数量满足要求为止。


顺序向后选择(SBS)则从适合一个包含所有变量的模型开始,然后在迭代中,其会在上一步变量子集的基础上,以穷举的方法在现有变量子集中删除一个对模型负影响最低的变量,直到所选特征的数量满足要求为止。


但是顺序向前选择(SFS)方法和顺序向后选择(SBS)均为逐步(step-wise)的方法,都可能会陷入局部最优状态。


1.2.1.1 Recursive Feature Elimination (SBS) 递归式特征消除


在sklearn中,它仅实现递归特征消除(SBS)方法。其提供了两个函数来实现这一方法,一个是RFE,另一个是RFECV。与RFE函数相比,REFCV使用交叉验证的结果来选择最优的特征数量,而在RFE中,要选择的特征数量由用户预定义。

# RFE函数 演示
import numpy as np
from sklearn.feature_selection import RFE
# 直接载入数据集
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.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作为示范
clf = ExtraTreesRegressor(n_estimators=25)
selector = RFE(estimator = clf, n_features_to_select = 4, step = 1) 
# 与RFECV不同,此处RFE函数需要用户定义选择的变量数量,此处设置为选择4个最好的变量,每一步我们仅删除一个变量
selector = selector.fit(train_set, train_y) # 在训练集上训练
transformed_train = train_set[:,selector.support_]  # 转换训练集
assert np.array_equal(transformed_train, train_set[:,[0,5,6,7]]) # 选择了第一个,第六个,第七个及第八个变量
transformed_test = test_set[:,selector.support_] # 转换训练集
assert np.array_equal(transformed_test, test_set[:,[0,5,6,7]]) # 选择了第一个,第六个,第七个及第八个变量
# RFECV 函数 演示
import numpy as np
from sklearn.feature_selection import RFECV
# 直接载入数据集
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.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作为示范
clf = ExtraTreesRegressor(n_estimators=25)
selector = RFECV(estimator = clf, step = 1, cv = 5) # 使用5折交叉验证
# 每一步我们仅删除一个变量
selector = selector.fit(train_set, train_y)
transformed_train = train_set[:,selector.support_]  # 转换训练集
assert np.array_equal(transformed_train, train_set) # 选择了所有的变量
transformed_test = test_set[:,selector.support_] # 转换训练集
assert np.array_equal(transformed_test, test_set) # 选择了所有的变量


1.2.2 Randomized Algorithms 随机方法


与确定性算法相比,随机方法在搜索最佳特征子集时引入了一定程度的随机性。因此,在相同数据输入的情形下,它可能会输出不同的最优特征子集结果,但此方法中的随机性将有助于避免模型陷入局部最优结果。


1.2.2.1 Simulated Annealing (SA) 基于模拟退火特征选择


模拟退火是一种随机最优化方法,近年来被引入到特征选择领域。在每一步中,我们将根据当前的最优特征子集随机选择一个特征子集。若新的特征子集效果更好,那么我们将采用它并更新当前最优特征子集。若新特征子集的表现不佳,我们仍会以一定的概率接受它,这个接受概率取决于当前的状态(温度)。


以一定的概率接受变现不佳的特征子集对于模拟退火算法至关重要,因为这有助于算法避免陷入局部最优状态。随着迭代的进行,模拟退火算法可收敛为良好且稳定的最终结果。


由于未发现能较好实现SA算法的函数,因此我编写了一个python脚本来实现SA算法,以供您参考。其能够很好地兼容sklearn中的模型,支持分类及回归问题。它还提供了内置交叉验证方法。


公式:


在每一步中,接受表现不佳的特征子集的概率为:


image.png


Prob为接受表现不佳的特征子集的概率, 𝑙𝑜𝑠𝑠𝑛 为新特征子集的损失(loss), 𝑙𝑜𝑠𝑠𝑜 为新特征子集创建前的最优(最低)损失(loss), 𝐶𝑢𝑟_𝑇𝑒𝑚𝑝𝑒𝑟𝑎𝑡𝑢𝑟𝑒 为当前的温度。模拟退火的伪代码为:


image.png


回归问题演示

import sys 
sys.path.append("..") 
from SA import Simulated_Annealing # 导入我们撰写的模块
# 直接载入数据集
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.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作为示范
# 选择模拟退火中评价特征子集的的损失函数
from sklearn.metrics import mean_squared_error # 回归问题我们使用MSE
clf = ExtraTreesRegressor(n_estimators=25)
selector = Simulated_Annealing(loss_func = mean_squared_error, estimator = clf, 
                               init_temp = 0.2, min_temp = 0.005, iteration = 10, alpha = 0.9)
# 在训练集中训练
# SA.py中有具体每个参数的含义,此处不赘述
selector.fit(X_train = train_set, y_train = train_y, cv = 5) # 使用5折交叉验证
transformed_train = selector.transform(train_set) # 转换训练集
transformed_test = selector.transform(test_set)  # 转换测试集

image.png

import sys 
sys.path.append("..") 
import numpy as np
import random
from SA import Simulated_Annealing # 导入我们撰写的模块
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个观测点作为训练集
# 剩下的前20个观测点作为验证集,剩下的30个观测作为测试集
train_set = X[0:100,:]
val_set = X[100:120,:]
test_set = X[120:,:]
train_y = y[0:100]
val_y = y[100:120]
test_y = y[120:]
# 重制随机种子 
# 随机方法需要随机性的存在
random.seed()
np.random.seed()
# 选择用于衡量子集表现的有监督的机器学习模型
from sklearn.ensemble import ExtraTreesClassifier # we use extratree as predictive model
# 选择模拟退火中评价特征子集的的损失函数
from sklearn.metrics import log_loss # 回归问题中,我们使用交叉熵损失函数
clf = ExtraTreesClassifier(n_estimators=25)
selector = Simulated_Annealing(loss_func = log_loss, estimator = clf, 
                               init_temp = 0.2, min_temp = 0.005, iteration = 10, 
                               alpha = 0.9, predict_type = 'predict_proba')
# 在训练集中训练
# SA.py中有具体每个参数的含义,此处不赘述
selector.fit(X_train = train_set, y_train = train_y, X_val = val_set, 
             y_val = val_y, stop_point = 15) 
# 此函数允许用户导入自己定义的验证集,此处尝试一下
transformed_train = selector.transform(train_set)  # 转换训练集
transformed_test = selector.transform(test_set)  # 转换测试集
selector.best_sol # 返回最优特征的索引
selector.best_loss; # 返回最优特征子集对应的损失

1.2.2.2 Genetic Algorithm (GA) 基于基因算法特征选择


遗传算法是一种基于进化生物学概念的最优化搜索算法。它借鉴了自然界中的进化过程,并通过允许个体候选解通过“交叉”和“变异”来进化得到更优的候选解及种群。其还结合了自然界中的竞争理念,即仅允许最合适或最优的几个候选解“生存”下来并“繁殖”其后代。经过种群及个体候选解的持续迭代,基因算法(GA)会收敛到优化解决方案。


与模拟退火类似,我也编写了一个python脚本来实现GA算法,以供您参考。它提供了两种算法,包括“one-max”和“ NSGA2”。“one-max”为传统的单目标GA算法,“NSGA2”则为一个多目标GA算法。在特征选择中,“one-max”的目标是减少模拟在验证集上的损失,而“NSGA2”的目标一是减少损失,二是同时要最小化特征子集中特征的数量。


此python脚本能够很好地兼容sklearn中的模型,支持分类及回归问题。它还提供了内置交叉验证方法。


基因算法的伪代码如下:


image.png


回归问题演示

import sys 
sys.path.append("..") 
from GA import Genetic_Algorithm # 导入我们撰写的模块
# 直接载入数据集
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.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作为示范
# 选择模拟退火中评价特征子集的的损失函数
from sklearn.metrics import mean_squared_error # 回归问题我们使用MSE
clf = ExtraTreesRegressor(n_estimators=25)
selector = Genetic_Algorithm(loss_func = mean_squared_error, estimator = clf, 
                             n_gen = 10, n_pop = 20, algorithm = 'NSGA2')
# 在训练集中训练
# GA.py中有具体每个参数的含义,此处不赘述
selector.fit(X_train = train_set, y_train = train_y, cv = 5) # 使用5折交叉验证
transformed_train = selector.transform(train_set) # 转换训练集
transformed_test = selector.transform(test_set)  # 转换测试集

image.png

import sys 
sys.path.append("..") 
import numpy as np
import random
from GA import Genetic_Algorithm # 导入我们撰写的模块
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个观测点作为训练集
# 剩下的前20个观测点作为验证集,剩下的30个观测作为测试集
train_set = X[0:100,:]
val_set = X[100:120,:]
test_set = X[120:,:]
train_y = y[0:100]
val_y = y[100:120]
test_y = y[120:]
# 重制随机种子 
# 随机方法需要随机性的存在
random.seed()
np.random.seed()
# 选择用于衡量子集表现的有监督的机器学习模型
from sklearn.ensemble import ExtraTreesClassifier # we use extratree as predictive model
# 选择模拟退火中评价特征子集的的损失函数
from sklearn.metrics import log_loss # 回归问题中,我们使用交叉熵损失函数
clf = ExtraTreesClassifier(n_estimators=25)
selector = Genetic_Algorithm(loss_func = log_loss, estimator = clf, 
                             n_gen = 15, n_pop = 10, predict_type = 'predict_proba')
# 在训练集中训练
# GA.py中有具体每个参数的含义,此处不赘述
selector.fit(X_train = train_set, y_train = train_y, X_val = val_set, 
             y_val = val_y, stop_point = 15) 
# 此函数允许用户导入自己定义的验证集,此处尝试一下
transformed_train = selector.transform(train_set)  # 转换训练集
transformed_test = selector.transform(test_set)  # 转换测试集
selector.best_sol # 返回最优特征的索引
selector.best_loss; # 返回最优特征子集对应的损失


基于 Jupyter 的特征工程手册:特征选择:


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

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

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


中文版 Jupyter 地址:

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

相关文章
|
机器学习/深度学习 数据采集 自然语言处理
【机器学习实战】10分钟学会Python怎么用LASSO回归进行正则化(十二)
【机器学习实战】10分钟学会Python怎么用LASSO回归进行正则化(十二)
2940 0
|
10月前
|
机器学习/深度学习 算法 前端开发
【Python机器学习专栏】集成学习算法的原理与应用
【4月更文挑战第30天】集成学习通过组合多个基学习器提升预测准确性,广泛应用于分类、回归等问题。主要步骤包括生成基学习器、训练和结合预测结果。算法类型有Bagging(如随机森林)、Boosting(如AdaBoost)和Stacking。Python中可使用scikit-learn实现,如示例代码展示的随机森林分类。集成学习能降低模型方差,缓解过拟合,提高预测性能。
154 3
|
10月前
|
机器学习/深度学习 算法 数据可视化
【Python机器学习专栏】决策树算法的实现与解释
【4月更文挑战第30天】本文探讨了决策树算法,一种流行的监督学习方法,用于分类和回归。文章阐述了决策树的基本原理,其中内部节点代表特征判断,分支表示判断结果,叶节点代表类别。信息增益等标准用于衡量特征重要性。通过Python的scikit-learn库展示了构建鸢尾花数据集分类器的示例,包括训练、预测、评估和可视化决策树。最后,讨论了模型解释和特征重要性评估在优化中的作用。
162 1
|
10月前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】关联规则学习:Apriori算法详解
【4月更文挑战第30天】Apriori算法是一种用于关联规则学习的经典算法,尤其适用于购物篮分析,以发现商品间的购买关联。该算法基于支持度和置信度指标,通过迭代生成频繁项集并提取满足阈值的规则。Python中可借助mlxtend库实现Apriori,例如处理购物篮数据,设置支持度和置信度阈值,找出相关规则。
354 2
|
10月前
|
机器学习/深度学习 算法 Python
【Python机器学习专栏】逻辑回归在分类问题中的应用
【4月更文挑战第30天】逻辑回归是用于二分类的统计方法,通过Sigmoid函数将线性输出映射到[0,1],以预测概率。优点包括易于理解、不需要线性关系、鲁棒且能输出概率。缺点是假设观测独立、易过拟合及需大样本量。在Python中,可使用`sklearn`的`LogisticRegression`实现模型。尽管有局限,但在适用场景下,逻辑回归是强大且有价值的分类工具。
118 0
|
10月前
|
机器学习/深度学习 Python
【Python机器学习专栏】时间序列数据的特征工程
【4月更文挑战第30天】本文探讨了时间序列数据的特征工程,强调其在捕捉季节性、揭示趋势、处理异常值和提升模型性能中的重要性。介绍了滞后特征、移动窗口统计特征、时间戳特征、频域特征和波动率特征等方法,并提供了Python实现示例。通过有效特征工程,可提高时间序列分析的准确性和预测可靠性。
441 0
|
10月前
|
机器学习/深度学习 算法 Python
【Python机器学习专栏】数据特征选择与降维技术
【4月更文挑战第30天】本文探讨了Python中数据特征选择与降维技术在机器学习和数据分析中的应用。特征选择包括单变量选择、递归特征消除(RFE)、树模型的特征重要性和相关性分析,有助于去除冗余和无关特征。降维技术涵盖PCA、LDA以及非线性方法如KPCA和ISOMAP,用于在低维空间保留信息。这些技术能简化数据、提升模型性能及可解释性。
163 0
|
机器学习/深度学习 自然语言处理 算法
【机器学习实战项目】10分钟学会Python怎么用支持向量机SVM进行分类预测(三)
【机器学习实战项目】10分钟学会Python怎么用支持向量机SVM进行分类预测(三)
315 0
|
机器学习/深度学习 自然语言处理 算法
【机器学习实战项目】10分钟学会Python怎么用Logistic回归进行分类预测(一)
【机器学习实战项目】10分钟学会Python怎么用Logistic回归进行分类预测(一)
400 0
|
机器学习/深度学习 算法 搜索推荐
【机器学习实战项目】10分钟学会Python怎么用朴素贝叶斯Bayes进行分类预测(二)
【机器学习实战项目】10分钟学会Python怎么用朴素贝叶斯Bayes进行分类预测(二)
558 0