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

情感   2024-07-22 10:00   湖北  

公众号:尤而小屋
编辑: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
import numpy as np
import pandas as pd

import warnings
warnings.filterwarnings('ignore')

导入数据

使用鸢尾花数据集iris

from sklearn.datasets import load_iris
iris = load_iris()

# 特征数据X
X = iris.data
# 目标变量
y = iris.target
X[:5]
array([[5.13.51.40.2],
     [4.93. , 1.40.2],
     [4.73.21.30.2],
     [4.63.11.50.2],
     [5. , 3.61.40.2]])
y[:5]
array([00000])

数据预处理processing-data

数据标准化

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

  • :x的均值
  • S:x的标准差
from sklearn.preprocessing import StandardScaler
 
# 标准化后的数据
ss_data = StandardScaler().fit_transform(X)
ss_data[:5]
    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):

from sklearn.preprocessing import MaxAbsScaler  
  
scaler = MaxAbsScaler()  
X_scaled = scaler.fit_transform(X)

数据归一化

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

from sklearn.preprocessing import MinMaxScaler 
mm_data = MinMaxScaler().fit_transform(X)
mm_data[:5
    array([[0.222222220.625     , 0.067796610.04166667],
           [0.166666670.416666670.067796610.04166667],
           [0.111111110.5       , 0.050847460.04166667],
           [0.083333330.458333330.084745760.04166667],
           [0.194444440.666666670.067796610.04166667]])

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

from sklearn.preprocessing import Normalizer

#归一化,返回值为归一化后的数据
normal_data = Normalizer().fit_transform(X)
normal_data[:5]
array([[0.803772770.551608770.220643510.0315205 ],
    [0.828132870.507020130.236609390.03380134], 
    [0.805333080.548311880.2227517 , 0.03426949], 
    [0.800030250.539150820.260879430.03478392],
    [0.790965  , 0.5694948 , 0.2214702 , 0.0316386 ]])

数据二值化处理Binarizer

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

from sklearn.preprocessing import Binarizer

#二值化处理:阈值设置为3
bin_data = Binarizer(threshold=3).fit_transform(X)
bin_data[:5]
array([[1.1.0.0.],
       [1.0.0.0.],
       [1.1.0.0.],
       [1.1.0.0.],
       [1.1.0.0.]])

独热码Onehot

from sklearn.preprocessing import OneHotEncoder
# 哑编码:对IRIS数据集的目标值进行独热码

OneHotEncoder().fit_transform(y.reshape((-1,1)))
    <150x3 sparse matrix of type '<class 'numpy.float64'>'
     with 150 stored elements in Compressed Sparse Row format>

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

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

模拟存在缺失值的数据

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],
})
df

chinesemath
0100.0100.0
1NaNNaN
298.098.0
390.080.0
4NaN94.0
from sklearn.impute import SimpleImputer  

# 列方向:使用现有值的均值填充
imputer = SimpleImputer(missing_values=np.nan, strategy="mean")  
imputer.fit(df)

官网地址:https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html

sklearn.impute.SimpleImputer(
    missing_values=nan, 
    strategy='mean'
    fill_value=None,
    copy=True
    add_indicator=False,
    keep_empty_features=False
)
impute_data = imputer.transform(df) 
impute_data 
array([[100.100.],
       [ 96.,  93.],
       [ 98.,  98.],
       [ 90.,  80.],
       [ 96.,  94.]])
(100+98+90) / 3  # chinese列 

96.0

(100+98+80+94) / 4  # math列

93.0

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

数据变换

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

from sklearn.preprocessing import PolynomialFeatures

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

可以自定义变换函数:

from sklearn.preprocessing import FunctionTransformer  
  
# 自定义变换函数  
def custom_transform(X):    
    return X * 2  
  
transformer = FunctionTransformer(custom_transform)  
X_transformed = transformer.fit_transform(X)

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

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方法

基于方差

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

from sklearn.feature_selection import VarianceThreshold

# 方差选择法:threshold为方差的阈值
var_data = VarianceThreshold(threshold=3).fit_transform(X)
var_data[:5]
array([[1.4],
       [1.4],
       [1.3],
       [1.5],
       [1.4]])

基于卡方检验

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
chi_data = SelectKBest(chi2,k=3).fit_transform(X,y)

Wrapper方法

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

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

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]
array([[3.51.40.2],
       [3. , 1.40.2],
       [3.21.30.2],
       [3.11.50.2],
       [3.61.40.2]])

Embedded方法

带有惩罚项的特征选择

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]
array([[1.40.2],
       [1.40.2],
       [1.30.2],
       [1.50.2],
       [1.40.2]])

基于树模型的特征选择

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

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
 
# GBDT作为基模型的特征选择
sfm_data2 = SelectFromModel(GradientBoostingClassifier()).fit_transform(X, y)
sfm_data2[:5]
array([[1.40.2],
       [1.40.2],
       [1.30.2],
       [1.50.2],
       [1.40.2]])

数据降维

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

基于主成分分析PCA

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

from sklearn.decomposition import PCA
 
# PCA:n_components为主成分数目
pca_data = PCA(n_components=2).fit_transform(X)
pca_data[:5]
array([[-2.68412563,  0.31939725],
       [-2.71414169-0.17700123],
       [-2.88899057-0.14494943],
       [-2.74534286-0.31829898],
       [-2.72871654,  0.32675451]])

基于线性判别分析(LDA)

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

#线性判别分析法LDA: n_components为降维后的维数
lda_data = LDA(n_components=2).fit_transform(X, y)
lda_data[:5]
array([[ 8.06179978-0.30042062],
       [ 7.12868772,  0.78666043],
       [ 7.48982797,  0.26538449],
       [ 6.81320057,  0.67063107],
       [ 8.13230933-0.51446253]])

尤而小屋
尤而小屋,一个温馨且有爱的小屋🏡 小屋主人,一手代码谋求生存,一手掌勺享受生活,欢迎你的光临~
 最新文章