利用多项式特征生成与递归特征消除解决特征组合与特征选择问题

本文探讨了在机器学习中使用多项式特征生成和自动特征选择(RFECV)来解决特征与标签关系复杂及特征选择问题。通过实例展示了如何在红酒质量数据集上应用这些技术,以及它们如何影响模型的预测性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目背景

无论是对于什么数据都存在两个非常经典的问题:问题一是,数据与标签之间,数据与数据之间的一些实际关系很难搞清楚。有些时候特征A,特征B可能都与标签存在正向关系。然而实际上的关系却可能是标签与特征A,B的乘积存在实际关系;问题二,在不同机器学习的模型中,特征的最佳选择往往并不一致。比如当模型选择为模型model1的时候,特征可能为特征ABC,而当模型变为model2的时候,最佳特征可能就变为了ACD。

为了解决这两个问题,有一个比较成熟的自动化方案可供我们使用。那就是多项式特征生成与自动特征选择。

这里我们借助sklearn中的多项式特征生成(sklearn.preprocessing.PolynomialFeatures)与RFECV(sklearn.feature_selection.RFECV,递归式特征消除)来解决这个问题。前者的作用是自动生成多项式特征,如,x1,x2,生成特征为x1**x1,x1*x2,x2**x2等。而递归式特征消除,则是一种利用模型进行特征消除的方法,需要模型本身带有特征的重要程度这一项,之后则不断地递归调用自身,将不重要的特征去除,直到去除某个特征后,模型的预测效果下降为止。

技术栈

  • Python3
  • scikit-learn
  • pandas
  • numpy
  • matplotlib

实现

数据

特征的自由组合有时会带来性能提升,但并不一定一定是有效的。更多的时候我们需要要考虑的是实际业务的需要。这里我们选择UCI的红酒质量数据集进行处理,从实际业务上来说,红酒质量数据集中的特征都是单项的红酒指标,但是实际上红酒的评分本就并非直接与单项数据成正比,有些则是与特征之间的组合或者特征的几次方成有效关系。因此我们这里就是用多项式特征生成与递归特征消除来自动获取符合实际业务的模型。

该数据的下载可以前往:http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv

代码

首先加载有关类库

import numpy as np
from sklearn.feature_selection import RFECV
from sklearn.linear_model import LassoCV
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

之后创建数据加载的方法,并调用数据;要注意的是我们这里使用的train_test_split方法进行数据的分割,其中test_size=0.30,表示分割出百分之三十的数据作为测试数据集,随机数种子为random_state=531,为随机数种子赋值后我们将

def GetDataByPandas():
    import pandas as pd
    wine = pd.read_csv("/home/fonttian/Data/dataset/wine/wine.csv")
    y = np.array(wine.quality)
    X = np.array(wine.drop("quality", axis=1))
    columns = np.array(wine.columns)

    return X, y, columns

X, y, wineNames = GetDataByPandas()
scalar = StandardScaler()
X = scalar.fit_transform(X)

train_data, test_data, train_labels, test_labels = train_test_split(X, y, test_size=0.30, random_state=531)

之后首先使用多项式特征生成方法进行特征的自动生成,具体代码如下:

from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(2)
print("原始数据的形状:")
print(train_data.shape)
train_data_new = poly.fit_transform(train_data)
test_data_new = poly.fit_transform(test_data)
print("生成多项式特征之后的数据形状:")
print(train_data_new.shape)
原始数据的形状:
(1119, 11)
生成多项式特征之后的数据形状:
(1119, 78)

此处参数2表示,特征生成的程度,如果需要生成3程度(也就是三次方和三个特征自由组合),只需要设置参数为3即可。另外还有一个参数interaction_only,表示是否只生成交互特征,如果为True,将不会生成特征与自身交互产生的特征(也就是几次方之类的),该参数默认为False。
之后我们需要选择一个模型进行数据的预测,同时为了方便观察以及避免超参数带来的偶然性。我们这里选择LassoCV方法进行建模,该方法会使用交叉验证自动选择Lasso的最佳超参数alpha,这样可以很大程度避免默认超参数对实际结果的影响。具体代码如下:

%matplotlib inline
def LassoCV_plot(model):
    import matplotlib.pyplot as plot
    plot.figure()
    plot.plot(model.alphas_, model.mse_path_, ':')
    plot.plot(model.alphas_, model.mse_path_.mean(axis=-1),
              label='Average MSE Across Folds', linewidth=2)
    plot.axvline(model.alpha_, linestyle='--',
                 label='CV Estimate of Best alpha')
    plot.semilogx()
    plot.legend()
    ax = plot.gca()
    ax.invert_xaxis()
    plot.xlabel('alpha')
    plot.ylabel('Mean Square Error')
    plot.axis('tight')
    plot.show()

    # print out the value of alpha that minimizes the Cv-error
    print("alpha Value that Minimizes CV Error  ", model.alpha_)
    print("Minimum MSE  ", min(model.mse_path_.mean(axis=-1)))


# Call LassoCV from sklearn.linear_model
lcv_1 = LassoCV(cv=10,n_jobs=-1)
wineModel = lcv_1.fit(train_data, train_labels)
LassoCV_plot(wineModel)
lcv_2 = LassoCV(cv=10,n_jobs=-1)
wineModel_new = lcv_2.fit(train_data_new, train_labels)
LassoCV_plot(wineModel_new)

estimator = LassoCV(cv=10,n_jobs=-1)
selector = RFECV(estimator, step=1, cv=5,n_jobs=-1)
selector = selector.fit(X, y)

selector_train_data = selector.fit_transform(train_data, train_labels)
test_data_selector = selector.transform(test_data)

lassocv可视化

alpha Value that Minimizes CV Error   0.005057237342969403
Minimum MSE   0.42849753501285

lassocv 可视化

alpha Value that Minimizes CV Error   0.0061927974491236
Minimum MSE   0.4236178162163108

从最终结果来看,我们直接使用生成的67种特征+原11种特征进行建模的效果并不好于直接使用原11种特征,这是必然是因为产生了大量的无用特征的缘故。下一步我们就需要借助递归式特征消除进行特征选择,将真正有效的特征选择出来。

print("使用特征选择,并进行效果对比:")

estimator = LassoCV(cv=10,n_jobs=-1)
selector = RFECV(estimator, step=1, cv=5,n_jobs=-1)
selector = selector.fit(X, y)

selector_train_data = selector.fit_transform(train_data, train_labels)
test_data_selector = selector.transform(test_data)

print("特征选择之后数据的shape:",selector_train_data.shape)
wineModel = lcv_1.fit(selector_train_data, train_labels)
print("alpha Value that Minimizes CV Error  ", wineModel.alpha_)
print("Minimum MSE  ", min(wineModel.mse_path_.mean(axis=-1)))

selector_train_data_new = selector.fit_transform(train_data_new, train_labels)
test_data_new_selector = selector.transform(test_data_new)

print("特征选择之后数据的shape:",selector_train_data_new.shape)
wineModel_new = lcv_2.fit(selector_train_data_new, train_labels)
print("alpha Value that Minimizes CV Error  ", wineModel_new.alpha_)
print("Minimum MSE  ", min(wineModel_new.mse_path_.mean(axis=-1)))
使用特征选择,并进行效果对比:
特征选择之后数据的shape: (1119, 7)
alpha Value that Minimizes CV Error   0.0008837665882418426
Minimum MSE   0.427181140352486
特征选择之后数据的shape: (1119, 38)
alpha Value that Minimizes CV Error   0.00038256145886961614
Minimum MSE   0.4002180554706169

上面即是进行特征选择后的实际结果,可以很明显的看到,如果仅仅对原始数据进行特征选择,那么大概能够降低0.00413的平均误差以及0.001的最小MSE;但是在对生成的多项式特征进行特征选择之后,其结果则得到的极大的下降(0.00588,0.234)。而且各位重要的是进行特征选择后的多项式数据集的拟合结果已经明显高于原有数据集的拟合结果。但是除了拟合结果之外更好地应该是预测结果的变化,下面的代码则是预测结果的变化:

# 输出预测值
def show_prediction(model, X, y):
    prediction = model.predict(X)

    print("RMSE", np.sqrt(mean_squared_error(y, prediction)))
    print("MSE", mean_squared_error(y, prediction))


show_prediction(lcv_1, test_data_selector, test_labels)
show_prediction(lcv_2, test_data_new_selector, test_labels)
RMSE 0.6440234501860966
MSE 0.4147662043896037
RMSE 0.6390612669439588
MSE 0.40839930290801785

总结

从预测结果看,很明显经过多项式特征生成与递归特征消除的模型效果依旧要好于原有模型很多。同时更重要的地方在于,目前对于模型效果具有正面效果的数据很有可能是有意义的特殊特征组合。利用该方法我们也可以快速的获得一个可能有用特殊意义的特征组合的集合,并引导我们发现这些特殊特征组合的现实意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tian Fengshou

写的很好,请给我钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值