数据预处理后,我们生成了大量的新变量(比如独热编码生成了大量仅包含0或1的变量)。但实际上,部分新生成的变量可能是多余:一方面它们本身不一定包含有用的信息,故无法提高模型性能;另一方面过这些多余变量在构建模型时会消耗大量内存和计算能力。因此,我们应该进行特征选择并选择特征子集进行建模。
项目地址:
本文将介绍特征工程中的 Embedded Methods 嵌入方法。
目录:
过滤法的特征选择过程与后续的机器学习模型无关,因此过滤法可能导致较差的模型性能。
封装方法利用预定义的有监督的机器学习模型来选择最佳功能。但是,由于它们需要在大量可能的特征子集上多次训练模型,因此尽管它们通常会导致更好的性能,但它们同时也需要较长的处理时间。
嵌入式方法将特征选择过程嵌入到机器学习模型中,即利用机器学习来为每一个特征打分。嵌入式方法在创建模型时即完成了对特征子集的选择。因此,与过滤法相比,它们往往具有更好的性能。与封装方法相比,它们节省了大量的处理时间和计算能力。
三种方法的一个简单对比.
1.3.1 基于正则化模型的方法
许多机器学习模型在其损失函数中引入了正则项(L1正则或L2正则),以防止过拟合问题。线性模型(例如线性向量支持机,逻辑回归,线性回归)中的L1正则项能够有效地将某些特征的特征系数缩小为零,从而实现解的稀疏。因此,基于带正则项线性模型的特征系数,我们可以为特征打分。系数越高,往往该特征在线性模型中越重要。
我们可以使用sklearn SelectFromModel函数删除特征系数低或为零的特征。
1.3.1.1 Lasso Regression (Linear Regression with L1 Norm) 套索回归
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)
array([ 0.346, 0.003, -0. , -0. , -0. , -0. , -0.033, 0. ])
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) 逻辑回归
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)
array([[ 0. , 1. , -3.452, -0.159],
[ 0. , -1.201, 0.053, 0. ],
[ 0. , 0. , 1.331, 3.27 ]])
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 线性向量支持机
# 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)
array([ 0.254, 0.026, 0.026, -0.017, 0.032, -0.01 , -0.1 , -0.037])
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
这些非参的树状模型在建立的过程中记录了每一个变量如何在树节点的分叉中逐步降低模型损失,并可以根据上述记录分析每个特征的特征重要性。而我们可以基于这特征重要性删去一些不重要的变量。
# 我们以随机森林为例 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)
array([0.52 , 0.045, 0.031, 0.026, 0.027, 0.139, 0.106, 0.107])
# 可视化特征重要性 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('特征相对重要性');
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]])
基于 Jupyter 的特征工程手册 - 特征选择系列历史文章:
专栏 | 基于 Jupyter 的特征工程手册:特征选择(一)
专栏 | 基于 Jupyter 的特征工程手册:特征选择(二)
专栏 | 基于 Jupyter 的特征工程手册:特征选择(三)
专栏 | 基于 Jupyter 的特征工程手册:特征选择(四)
中文版 Jupyter 地址: