机器学习:基于scikit-learn进行特征工程

2024-07-22 09:18:58 浏览数 (3)

公众号:尤而小屋 编辑:Peter 作者:Peter

大家好,我是Peter~

今天给大家分享如何基于机器学习建模全能包scikit-learn进行特征工程feature-engineering。

特征工程

机器学习的特征工程(Feature Engineering)是机器学习项目中一个至关重要的步骤,它涉及从原始数据中提取、选择和转换特征,以便更好地训练机器学习模型。特征工程直接影响到模型的性能,因为机器学习算法的性能很大程度上依赖于输入数据的表示(即特征)。

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。

基于scikit-learn做特征工程

scikit-learn中主要用于特征的工具包:

  • 数据预处理sklearn-Processing-data: https://scikit-learn.org/stable/modules/preprocessing.html#non-linear-transformation
  • 特征选择sklearn-feature-selection:https://scikit-learn.org/stable/modules/feature_selection.html
  • 降维sklearn-Dimensionality-reduction:https://scikit-learn.org/stable/modules/decomposition.html#decompositions
代码语言:python代码运行次数:0复制
import numpy as np
import pandas as pd

import warnings
warnings.filterwarnings('ignore')

导入数据

使用鸢尾花数据集iris

代码语言:python代码运行次数:0复制
from sklearn.datasets import load_iris
代码语言:python代码运行次数:0复制
iris = load_iris()

# 特征数据X
X = iris.data
# 目标变量
y = iris.target
代码语言:python代码运行次数:0复制
X[:5]
代码语言:python代码运行次数:0复制
array([[5.1, 3.5, 1.4, 0.2],
     [4.9, 3. , 1.4, 0.2],
     [4.7, 3.2, 1.3, 0.2],
     [4.6, 3.1, 1.5, 0.2],
     [5. , 3.6, 1.4, 0.2]])
代码语言:python代码运行次数:0复制
y[:5]
代码语言:python代码运行次数:0复制
array([0, 0, 0, 0, 0])

数据预处理processing-data

数据标准化

标准化是将数据缩放到均值为0,标准差为1的过程。使用preproccessing库的StandardScaler类对数据进行标准化的代码如下:

$$x_{new} = frac{x-overline x}{S}$$

  • $overline x$:x的均值
  • S:x的标准差
代码语言:python代码运行次数:0复制
from sklearn.preprocessing import StandardScaler
 
# 标准化后的数据
ss_data = StandardScaler().fit_transform(X)
ss_data[:5]
代码语言:python代码运行次数:0复制
    array([[-0.90068117,  1.01900435, -1.34022653, -1.3154443 ],
           [-1.14301691, -0.13197948, -1.34022653, -1.3154443 ],
           [-1.38535265,  0.32841405, -1.39706395, -1.3154443 ],
           [-1.50652052,  0.09821729, -1.2833891 , -1.3154443 ],
           [-1.02184904,  1.24920112, -1.34022653, -1.3154443 ]])

用于稀疏数据(比如文本数据)的标准化MaxAbsScaler(最大值缩放到1):

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import MaxAbsScaler  
  
scaler = MaxAbsScaler()  
X_scaled = scaler.fit_transform(X)

数据归一化

方式1:基于最大值最小值的归一化

$$x_{new} = frac{x-Min}{Max-Min}$$

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import MinMaxScaler 
mm_data = MinMaxScaler().fit_transform(X)
mm_data[:5] 
代码语言:python代码运行次数:0复制
    array([[0.22222222, 0.625     , 0.06779661, 0.04166667],
           [0.16666667, 0.41666667, 0.06779661, 0.04166667],
           [0.11111111, 0.5       , 0.05084746, 0.04166667],
           [0.08333333, 0.45833333, 0.08474576, 0.04166667],
           [0.19444444, 0.66666667, 0.06779661, 0.04166667]])

方式2:基于规则l2的归一化处理

$$x{new} = frac{x}{sqrt{sum^m{j}}xj^2}$$

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import Normalizer

#归一化,返回值为归一化后的数据
normal_data = Normalizer().fit_transform(X)
normal_data[:5]
代码语言:python代码运行次数:0复制
array([[0.80377277, 0.55160877, 0.22064351, 0.0315205 ],
    [0.82813287, 0.50702013, 0.23660939, 0.03380134], 
    [0.80533308, 0.54831188, 0.2227517 , 0.03426949], 
    [0.80003025, 0.53915082, 0.26087943, 0.03478392],
    [0.790965  , 0.5694948 , 0.2214702 , 0.0316386 ]])

数据二值化处理Binarizer

连续型特征的二值化处理方法:大于设置阈值的赋值为1,其他为0:

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import Binarizer

#二值化处理:阈值设置为3
bin_data = Binarizer(threshold=3).fit_transform(X)
bin_data[:5]
代码语言:python代码运行次数:0复制
array([[1., 1., 0., 0.],
       [1., 0., 0., 0.],
       [1., 1., 0., 0.],
       [1., 1., 0., 0.],
       [1., 1., 0., 0.]])

独热码Onehot

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import OneHotEncoder
# 哑编码:对IRIS数据集的目标值进行独热码

OneHotEncoder().fit_transform(y.reshape((-1,1)))
代码语言:python代码运行次数:0复制
    <150x3 sparse matrix of type '<class 'numpy.float64'>'
    	with 150 stored elements in Compressed Sparse Row format>

scikit-learn中的OneHotEncoder通常与ColumnTransformer一起使用,特别是在处理混合类型数据时:

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import OneHotEncoder  
from sklearn.compose import ColumnTransformer  
  
# 假设 X_categorical 是包含分类变量的DataFrame  
categorical_features = ['feature1', 'feature2']  
onehot = OneHotEncoder(handle_unknown='ignore')  
col_trans = ColumnTransformer([("onehot", onehot, categorical_features)], remainder='passthrough')  
X_transformed = col_trans.fit_transform(X_categorical)  
  
# 注意:X_transformed 是一个稀疏矩阵,用toarray() 转换为NumPy数组  
X_transformed_array = X_transformed.toarray()

缺失指填充Imputer

模拟存在缺失值的数据

代码语言:python代码运行次数:0复制
import pandas as pd
import numpy as np

df = pd.DataFrame({
    "chinese":[100,np.nan,98,90,np.nan],
    "math":[100,np.nan,98,80,94],
})
代码语言:python代码运行次数:0复制
impute_data = imputer.transform(df) 
impute_data 
代码语言:python代码运行次数:0复制
array([[100., 100.],
       [ 96.,  93.],
       [ 98.,  98.],
       [ 90.,  80.],
       [ 96.,  94.]])
代码语言:python代码运行次数:0复制
(100 98 90) / 3  # chinese列 

96.0
代码语言:python代码运行次数:0复制
(100 98 80 94) / 4  # math列

93.0

手动计算的结果和自动填充的结果是吻合的。

数据变换

基于多项式、指数、对数、平方根等进行变换;

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import PolynomialFeatures

# 参数degree为度,默认值为2
poly_data = PolynomialFeatures(degree=2).fit_transform(X)  # X = iris.data

可以自定义变换函数:

代码语言:python代码运行次数:0复制
from sklearn.preprocessing import FunctionTransformer  
  
# 自定义变换函数  
def custom_transform(X):    
    return X * 2  
  
transformer = FunctionTransformer(custom_transform)  
X_transformed = transformer.fit_transform(X)

还有其他的变换,比如:Box-Cox变换等

代码语言:python代码运行次数:0复制
import matplotlib.pyplot as plt
%matplotlib inline

import numpy as np  
from scipy import stats  
  
# 生成一组不符合正态分布的数据(例如,指数分布数据)  
data = np.random.exponential(size=100)  
# 进行Box-Cox变换  
transformed_data, lambda_value = stats.boxcox(data)  

# ----------
plt.scatter(x=range(len(data)),y=data)
plt.scatter(x=range(len(data)),y=transformed_data)
plt.show()

特征选择

根据特征选择的形式又可以将特征选择方法分为3种:

  • Filter:过滤法,不用考虑后续学习器,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。
  • Wrapper:包装法,需考虑后续学习器,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
  • Embedded:嵌入法,是Filter与Wrapper方法的结合。先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。 我们使用sklearn中的feature_selection库来进行特征选择。

Filter方法

基于方差

使用方差选择法,先要计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征

代码语言:python代码运行次数:0复制
from sklearn.feature_selection import VarianceThreshold

# 方差选择法:threshold为方差的阈值
var_data = VarianceThreshold(threshold=3).fit_transform(X)
var_data[:5]
代码语言:python代码运行次数:0复制
array([[1.4],
       [1.4],
       [1.3],
       [1.5],
       [1.4]])
基于卡方检验
代码语言:python代码运行次数:0复制
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
代码语言:python代码运行次数:0复制
chi_data = SelectKBest(chi2,k=3).fit_transform(X,y)

Wrapper方法

递归特征消除(Recursive Feature Elimination,RFE)

递归特征消除(Recursive Feature Elimination,RFE)是一种在机器学习中广泛使用的特征选择方法。它首先使用所有特征训练一个模型,通过迭代地训练模型并剔除不重要的特征,直到达到预设的特征数量或满足其他停止条件为止。

代码语言:python代码运行次数:0复制
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

# estimator基模型; n_features_to_select 选择的特征数
rfe_data = RFE(estimator=LogisticRegression(), n_features_to_select=3).fit_transform(iris.data, iris.target)
rfe_data[:5]
代码语言:python代码运行次数:0复制
array([[3.5, 1.4, 0.2],
       [3. , 1.4, 0.2],
       [3.2, 1.3, 0.2],
       [3.1, 1.5, 0.2],
       [3.6, 1.4, 0.2]])

Embedded方法

带有惩罚项的特征选择
代码语言:python代码运行次数:0复制
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression

# 基模型:带L2惩罚项的逻辑回归
sfm_data1 = SelectFromModel(LogisticRegression(penalty="l2", C=0.1)).fit_transform(X, y)
sfm_data1[:5]
代码语言:python代码运行次数:0复制
array([[1.4, 0.2],
       [1.4, 0.2],
       [1.3, 0.2],
       [1.5, 0.2],
       [1.4, 0.2]])
基于树模型的特征选择

树模型比如GBDT可用来作为基模型进行特征选择

代码语言:python代码运行次数:0复制
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
 
# GBDT作为基模型的特征选择
sfm_data2 = SelectFromModel(GradientBoostingClassifier()).fit_transform(X, y)
sfm_data2[:5]
代码语言:python代码运行次数:0复制
array([[1.4, 0.2],
       [1.4, 0.2],
       [1.3, 0.2],
       [1.5, 0.2],
       [1.4, 0.2]])

数据降维

机器学习建模过程中,当特征数量非常大时,模型的训练时间、预测时间以及所需的计算资源(如内存和CPU/GPU)都会显著增加。通过降维,可以减少特征的数量,从而降低计算成本,使模型更加高效。

基于主成分分析PCA

PCA算法,全称为主成分分析(Principal Component Analysis),是一种无监督学习算法,主要用于数据降维和特征提取。PCA通过线性变换将原始数据映射到一个新的低维空间,以保留数据中的最大方差,即保留数据的主要信息。

代码语言:python代码运行次数:0复制
from sklearn.decomposition import PCA
 
# PCA:n_components为主成分数目
pca_data = PCA(n_components=2).fit_transform(X)
pca_data[:5]
代码语言:python代码运行次数:0复制
array([[-2.68412563,  0.31939725],
       [-2.71414169, -0.17700123],
       [-2.88899057, -0.14494943],
       [-2.74534286, -0.31829898],
       [-2.72871654,  0.32675451]])

基于线性判别分析(LDA)

代码语言:python代码运行次数:0复制
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

#线性判别分析法LDA: n_components为降维后的维数
lda_data = LDA(n_components=2).fit_transform(X, y)
lda_data[:5]
代码语言:python代码运行次数:0复制
array([[ 8.06179978, -0.30042062],
       [ 7.12868772,  0.78666043],
       [ 7.48982797,  0.26538449],
       [ 6.81320057,  0.67063107],
       [ 8.13230933, -0.51446253]])

1 人点赞