特征工程

特征工程

特征工程的目的

良好的数据要能够提取出良好的特征才能真正发挥效力。特征预处理、数据清洗是很关键的步骤,往往能够使得算法的效果和性能得到显著提高。归一化、离散化、因子化、缺失值处理、去除共线性等,数据挖掘过程中很多时间就花在它们上面。这些工作简单可复制,收益稳定可预期,是机器学习的基础必备步骤。
筛选出显著特征、摒弃非显著特征,这对很多结果有决定性的影响。特征选择好了,非常简单的算法也能得出良好、稳定的结果。这需要运用特征有效性分析的相关技术,如相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。

主要内容

常见的特征工程包括:

  1. 异常处理:

    • 通过箱线图(或 3-Sigma)分析删除异常值;
    • BOX-COX 转换(处理有偏分布);
    • 长尾截断;
  2. 特征归一化/标准化:

    • 标准化(转换为标准正态分布);
    • 归一化(抓换到 [0,1] 区间);
    • 针对幂律分布,可以采用公式: l o g ( ( 1 + x 1 ) / ( 1 + m e d i a n ) ) log((1+x1)/(1+median)) log((1+x1)/(1+median))
  3. 数据分桶:

    • 等频分桶;
    • 等距分桶;
    • Best-KS 分桶(类似利用基尼指数进行二分类);
    • 卡方分桶;
  4. 缺失值处理:

    • 不处理(针对类似 XGBoost 等树模型);
    • 删除(缺失数据太多);
    • 插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等;
    • 分箱,缺失值一个箱;
  5. 特征构造:

    • 构造统计量特征,报告计数、求和、比例、标准差等;
    • 时间特征,包括相对时间和绝对时间,节假日,双休日等;
    • 地理信息,包括分箱,分布编码等方法;
    • 非线性变换,包括 log/ 平方/ 根号等;
    • 特征组合,特征交叉;
    • 仁者见仁,智者见智。
  6. 特征筛选

    • 过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系数法/卡方检验法/互信息法;
    • 包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有 LVM(Las Vegas Wrapper) ;
    • 嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有 lasso 回归;
  7. 降维

    • PCA/ LDA/ ICA;
    • 特征选择也是一种降维。

导入基础包、数据及查看信息

# 导入基础包
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

# 修改图例中文及坐标轴显示问题
mpl.rcParams['font.sans-serif'] = 'SimHei'
mpl.rcParams['axes.unicode_minus'] = False

# 魔法函数
%matplotlib inline 

# 设置最大行列显示
pd.set_option('display.max_columns',None)
pd.set_option('display.max_rows',20)
# 数据读取
# sep分隔符,默认以','分割,本文件以' '分割
Train_data = pd.read_csv('used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv('used_car_testA_20200313.csv', sep=' ')
# 显示数据
Train_data.head()
SaleIDnameregDatemodelbrandbodyTypefuelTypegearboxpowerkilometernotRepairedDamageregionCodesellerofferTypecreatDatepricev_0v_1v_2v_3v_4v_5v_6v_7v_8v_9v_10v_11v_12v_13v_14
007362004040230.061.00.00.06012.50.010460020160404185043.3577963.9663440.0502572.1597441.1437860.2356760.1019880.1295490.0228160.097462-2.8818032.804097-2.4208210.7952920.914762
1122622003030140.012.00.00.0015.0-43660020160309360045.3052735.2361120.1379251.380657-1.4221650.2647770.1210040.1357310.0265970.020582-4.9004822.096338-1.030483-1.7226740.245522
221487420040403115.0151.00.00.016312.50.028060020160402622245.9783594.8237921.319524-0.998467-0.9969110.2514100.1149120.1651470.0621730.027075-4.8467491.8035591.565330-0.832687-0.229963
337186519960908109.0100.00.01.019315.00.04340020160312240045.6874784.492574-0.0506160.883600-2.2280790.2742930.1103000.1219640.0333950.000000-4.5095991.285940-0.501868-2.438353-0.478699
4411108020120103110.051.00.00.0685.00.069770020160313520044.3835112.0314330.572169-1.5712392.2460880.2280360.0732050.0918800.0788190.121534-1.8962400.9107830.9311102.8345181.923482
Train_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 31 columns):
SaleID               150000 non-null int64
name                 150000 non-null int64
regDate              150000 non-null int64
model                149999 non-null float64
brand                150000 non-null int64
bodyType             145494 non-null float64
fuelType             141320 non-null float64
gearbox              144019 non-null float64
power                150000 non-null int64
kilometer            150000 non-null float64
notRepairedDamage    150000 non-null object
regionCode           150000 non-null int64
seller               150000 non-null int64
offerType            150000 non-null int64
creatDate            150000 non-null int64
price                150000 non-null int64
v_0                  150000 non-null float64
v_1                  150000 non-null float64
v_2                  150000 non-null float64
v_3                  150000 non-null float64
v_4                  150000 non-null float64
v_5                  150000 non-null float64
v_6                  150000 non-null float64
v_7                  150000 non-null float64
v_8                  150000 non-null float64
v_9                  150000 non-null float64
v_10                 150000 non-null float64
v_11                 150000 non-null float64
v_12                 150000 non-null float64
v_13                 150000 non-null float64
v_14                 150000 non-null float64
dtypes: float64(20), int64(10), object(1)
memory usage: 35.5+ MB
# 数据训练集与测试集的维度及字段
print('训练集维度',Train_data.shape)
print('测试集维度',Test_data.shape)
print('训练集字段',Train_data.columns)
print('测试集字段',Test_data.columns)
训练集维度 (150000, 31)
测试集维度 (50000, 30)
训练集字段 Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'price', 'v_0', 'v_1', 'v_2', 'v_3',
       'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12',
       'v_13', 'v_14'],
      dtype='object')
测试集字段 Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'v_0', 'v_1', 'v_2', 'v_3', 'v_4',
       'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12', 'v_13',
       'v_14'],
      dtype='object')

异常处理

离群点检测方法 https://blog.csdn.net/mw21501050/article/details/75389267
探究离群点与噪声的关系

  1. 标准差法:
    在分布内,一个标准差内的数据为68% ,2个标准差内的数据为95%, 3个标准差内的数据为99.7%
  2. 四分位数极差法:
    比Q1小1.5倍的IQR或者比Q3大1.5倍的IQR的任何对象都视为离群点,因为Q1-1.5IQR和Q3+1.5IQR之间的区域包含了99.3%的对象。
# 封装一个异常处理代码
def outliers_proc(data, col_name, scale):
    """
    用于清洗数据异常,默认用box_plot(sacle=3)进行清洗
    :param data:接收 pandas 数据格式
    :param col_name:pandas列名
    :param scale: 尺度
    :return
    """
    
    def box_plot_outliers(data_ser, box_scale):
        """
        利用箱线图去除异常值
        :param data_ser :Series数据
        :param box_scale:箱线图尺度
        :return :
        """
        iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
        val_min = data_ser.quantile(0.25) -  iqr
        val_max = data_ser.quantile(0.75) +  iqr
        # 返回离群点布尔值
        outerlier_min = (data_ser < val_min)
        outerlier_max = (data_ser > val_max)
        return (outerlier_min, outerlier_max), (val_min, val_max)
    #进行deep copy
    data_n = data.copy()
    data_series = data_n[col_name]
    outerlier, val =box_plot_outliers(data_series, box_scale=scale)
    # 返回删除数字的索引
    index = np.arange(data_series.shape[0])[outerlier[0]|outerlier[1]]
    print("Delete number is: {}".format(len(index)))
    # 删除outlier
    data_n = data_n.drop(index)
    # 重设索引
    data_n.reset_index(drop=True, inplace=True)
    print("Now column number is: {}".format(data_n.shape[0]))
    index_low = np.arange(data_series.shape[0])[outerlier[0]]
    outliers = data_series.iloc[index_low]
    print("Description of data less than the lower bound is:")
    print(pd.Series(outliers).describe())
    index_up = np.arange(data_series.shape[0])[outerlier[1]]
    outliers = data_series.iloc[index_up]
    print("Description of data larger than the upper bound is:")
    print(pd.Series(outliers).describe())
    
    fig, ax = plt.subplots(1, 2, figsize=(10, 7))
    sns.boxplot(y=data[col_name], data=data, palette='Set1', ax=ax[0])
    sns.boxplot(y=data_n[col_name], data=data_n, palette='Set1', ax=ax[1])
    return data_n
Train_data = outliers_proc(Train_data, 'power', 3)
Delete number is: 963
Now column number is: 149037
Description of data less than the lower bound is:
count    0.0
mean     NaN
std      NaN
min      NaN
25%      NaN
50%      NaN
75%      NaN
max      NaN
Name: power, dtype: float64
Description of data larger than the upper bound is:
count      963.000000
mean       846.836968
std       1929.418081
min        376.000000
25%        400.000000
50%        436.000000
75%        514.000000
max      19312.000000
Name: power, dtype: float64

在这里插入图片描述

Train_data.shape
(149037, 31)

特征归一化、标准化

归一化的问题
概率模型不需要归一化,因为它们不关心变量的值,而是关心变量的分布和变量之间的条件概率,如决策树、rf。而像adaboost、svm、lr、KNN、KMeans 之类的最优化问题就需
要归一化。因为后者在使用梯度下降求解模型时可以更好的迭代从而找到最优解。

为什么使用独热编码 https://blog.csdn.net/xiaotian127/article/details/99451619 很多算法是在欧式空间计算的,所以对于特征内没有大小关系的变量应与其它特征保持等距

特征构造

特征构造一定要在数据处理之后

树模型

# 训练集和测试集放在一起,方便构造特征
Train_data['train'] = 1
Test_data['train'] = 0
# ignore_index = False 不对索引进行重排
data = pd.concat([Train_data, Test_data], axis=0, ignore_index=False, sort=False)
data.columns
Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'price', 'v_0', 'v_1', 'v_2', 'v_3',
       'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12',
       'v_13', 'v_14', 'train'],
      dtype='object')
# # 使用时间:data['creatDate'] - data['regDate'],反应汽车使用时间,一般来说价格与使用时间成反比
# 不过要注意,数据里有时间出错的格式,所以我们需要 errors='coerce'
data['used_time'] = (pd.to_datetime(data['creatDate'], format = '%Y%m%d', errors='coerce') -
                     pd.to_datetime(data['regDate'], format = '%Y%m%d', errors='coerce')).dt.days
# 看一下空数据,有 15k 个样本的时间是有问题的,我们可以选择删除,也可以选择放着。
# 但是这里不建议删除,因为删除缺失数据占总样本量过大,7.5%
# 我们可以先放着,因为如果我们 XGBoost 之类的决策树,其本身就能处理缺失值,所以可以不用管;
data['used_time'].isnull().sum()
15072
data.head()
SaleIDnameregDatemodelbrandbodyTypefuelTypegearboxpowerkilometernotRepairedDamageregionCodesellerofferTypecreatDatepricev_0v_1v_2v_3v_4v_5v_6v_7v_8v_9v_10v_11v_12v_13v_14trainused_time
007362004040230.061.00.00.06012.50.0104600201604041850.043.3577963.9663440.0502572.1597441.1437860.2356760.1019880.1295490.0228160.097462-2.8818032.804097-2.4208210.7952920.91476214385.0
1122622003030140.012.00.00.0015.0-436600201603093600.045.3052735.2361120.1379251.380657-1.4221650.2647770.1210040.1357310.0265970.020582-4.9004822.096338-1.030483-1.7226740.24552214757.0
221487420040403115.0151.00.00.016312.50.0280600201604026222.045.9783594.8237921.319524-0.998467-0.9969110.2514100.1149120.1651470.0621730.027075-4.8467491.8035591.565330-0.832687-0.22996314382.0
337186519960908109.0100.00.01.019315.00.043400201603122400.045.6874784.492574-0.0506160.883600-2.2280790.2742930.1103000.1219640.0333950.000000-4.5095991.285940-0.501868-2.438353-0.47869917125.0
4411108020120103110.051.00.00.0685.00.0697700201603135200.044.3835112.0314330.572169-1.5712392.2460880.2280360.0732050.0918800.0788190.121534-1.8962400.9107830.9311102.8345181.92348211531.0
# 从邮编中提取城市信息,相当于加入了先验知识
data['city'] = data['regionCode'].apply(lambda x : str(x)[0])
# 计算某品牌的销售统计量,同学们还可以计算其他特征的统计量
# 这里要以 train 的数据计算统计量
Train_gb = Train_data.groupby("brand")
all_info = {}
for kind, kind_data in Train_gb:
    info = {}
    kind_data = kind_data[kind_data['price'] > 0]
    info['brand_amount'] = len(kind_data)
    info['brand_price_max'] = kind_data.price.max()
    info['brand_price_median'] = kind_data.price.median()
    info['brand_price_min'] = kind_data.price.min()
    info['brand_price_sum'] = kind_data.price.sum()
    info['brand_price_std'] = kind_data.price.std()
    info['brand_price_average'] = round(kind_data.price.sum() / (len(kind_data) + 1), 2)
    all_info[kind] = info
brand_fe = pd.DataFrame(all_info).T.reset_index().rename(columns={"index": "brand"})
data = data.merge(brand_fe, how='left', on='brand')

data.head()
SaleIDnameregDatemodelbrandbodyTypefuelTypegearboxpowerkilometernotRepairedDamageregionCodesellerofferTypecreatDatepricev_0v_1v_2v_3v_4v_5v_6v_7v_8v_9v_10v_11v_12v_13v_14trainused_timecitybrand_amountbrand_price_maxbrand_price_medianbrand_price_minbrand_price_sumbrand_price_stdbrand_price_average
007362004040230.061.00.00.06012.50.0104600201604041850.043.3577963.9663440.0502572.1597441.1437860.2356760.1019880.1295490.0228160.097462-2.8818032.804097-2.4208210.7952920.91476214385.0110193.035990.01800.013.036457518.04562.2333313576.37
1122622003030140.012.00.00.0015.0-436600201603093600.045.3052735.2361120.1379251.380657-1.4221650.2647770.1210040.1357310.0265970.020582-4.9004822.096338-1.030483-1.7226740.24552214757.0413656.084000.06399.015.0124044603.08988.8654069082.86
221487420040403115.0151.00.00.016312.50.0280600201604026222.045.9783594.8237921.319524-0.998467-0.9969110.2514100.1149120.1651470.0621730.027075-4.8467491.8035591.565330-0.832687-0.22996314382.021458.045000.08500.0100.014373814.05425.0581409851.83
337186519960908109.0100.00.01.019315.00.043400201603122400.045.6874784.492574-0.0506160.883600-2.2280790.2742930.1103000.1219640.0333950.000000-4.5095991.285940-0.501868-2.438353-0.47869917125.0413994.092900.05200.015.0113034210.08244.6952878076.76
4411108020120103110.051.00.00.0685.00.0697700201603135200.044.3835112.0314330.572169-1.5712392.2460880.2280360.0732050.0918800.0788190.121534-1.8962400.9107830.9311102.8345181.92348211531.064662.031500.02300.020.015414322.03344.6897633305.67
# 数据分桶 以 power 为例
# 这时候我们的缺失值也进桶了,
# 为什么要做数据分桶呢,原因有很多,= =
# 1. 离散后稀疏向量内积乘法运算速度更快,计算结果也方便存储,容易扩展;
# 2. 离散后的特征对异常值更具鲁棒性,如 age>30 为 1 否则为 0,对于年龄为 200 的也不会对模型造成很大的干扰;
# 3. LR 属于广义线性模型,表达能力有限,经过离散化后,每个变量有单独的权重,这相当于引入了非线性,能够提升模型的表达能力,加大拟合;
# 4. 离散后特征可以进行特征交叉,提升表达能力,由 M+N 个变量编程 M*N 个变量,进一步引入非线形,提升了表达能力;
# 5. 特征离散后模型更稳定,如用户年龄区间,不会因为用户年龄长了一岁就变化

# 当然还有很多原因,LightGBM 在改进 XGBoost 时就增加了数据分桶,增强了模型的泛化性

# 异常值筛选后观察下特征分布
bin =[i*10 for i in range(31)]
print(bin)
data['power_bin'] = pd.cut(data['power'], bins=bin, labels=False)
data[['power_bin', 'power']]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300]
power_binpower
05.060
1NaN0
216.0163
319.0193
46.068
.........
19903211.0116
1990337.075
19903422.0224
199035NaN334
1990366.068

199037 rows × 2 columns

# 删除不需要的数据
# data = data.drop(['creatDate', 'regDate', 'regionCode'], axis=1)

print(data.columns)
print(data.shape)
Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'price', 'v_0', 'v_1', 'v_2', 'v_3',
       'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12',
       'v_13', 'v_14', 'train', 'used_time', 'city', 'brand_amount',
       'brand_price_max', 'brand_price_median', 'brand_price_min',
       'brand_price_sum', 'brand_price_std', 'brand_price_average',
       'power_bin'],
      dtype='object')
(199037, 42)
# 目前的数据其实已经可以给树模型使用了,所以我们导出一下
# data.to_csv('data_for_tree.csv', index=False)

LR模型

# 我们可以再构造一份特征给 LR NN 之类的模型用
# 之所以分开构造是因为,不同模型对数据集的要求不同
# 我们看下数据分布:
data['power'].plot.hist()
<matplotlib.axes._subplots.AxesSubplot at 0x1343d581188>

在这里插入图片描述

# 我们刚刚已经对 train 进行异常值处理了,但是现在还有这么奇怪的分布是因为 test 中的 power 异常值,
# 所以我们其实刚刚 train 中的 power 异常值不删为好,可以用长尾分布截断来代替
Train_data['power'].plot.hist()
<matplotlib.axes._subplots.AxesSubplot at 0x1343d569248>

在这里插入图片描述

# 首先对于power查看分布状态
# 数据监测
import scipy.stats as st
model_params = [st.johnsonsu, st.norm, st.lognorm]
for i, model in enumerate(model_params, start=1):
    plt.figure(i)
    plt.title(f'拟合模型{model}分布情况')
    sns.distplot(Train_data['power'],kde=False, fit=model)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 对power进行归一化
from sklearn import preprocessing
min_max_scaler = preprocessing.MinMaxScaler()
data['power'] = np.log(data['power'] + 1) 
data['power'] = ((data['power'] - np.min(data['power'])) / (np.max(data['power']) - np.min(data['power'])))
data['power'].plot.hist()
<matplotlib.axes._subplots.AxesSubplot at 0x1343e62ecc8>

在这里插入图片描述

# km 的比较正常,应该是已经做过分桶了
data['kilometer'].plot.hist()
<matplotlib.axes._subplots.AxesSubplot at 0x1343f14cc48>

在这里插入图片描述

# 所以我们可以直接做归一化
data['kilometer'] = ((data['kilometer'] - np.min(data['kilometer'])) / 
                        (np.max(data['kilometer']) - np.min(data['kilometer'])))
data['kilometer'].plot.hist()
<matplotlib.axes._subplots.AxesSubplot at 0x1343f30e3c8>

在这里插入图片描述

# 除此之外 还有我们刚刚构造的统计量特征:
# 'brand_amount', 'brand_price_average', 'brand_price_max',
# 'brand_price_median', 'brand_price_min', 'brand_price_std',
# 'brand_price_sum'
# 这里不再一一举例分析了,直接做变换,
def max_min(x):
    return (x - np.min(x)) / (np.max(x) - np.min(x))

data['brand_amount'] = ((data['brand_amount'] - np.min(data['brand_amount'])) / 
                        (np.max(data['brand_amount']) - np.min(data['brand_amount'])))
data['brand_price_average'] = ((data['brand_price_average'] - np.min(data['brand_price_average'])) / 
                               (np.max(data['brand_price_average']) - np.min(data['brand_price_average'])))
data['brand_price_max'] = ((data['brand_price_max'] - np.min(data['brand_price_max'])) / 
                           (np.max(data['brand_price_max']) - np.min(data['brand_price_max'])))
data['brand_price_median'] = ((data['brand_price_median'] - np.min(data['brand_price_median'])) /
                              (np.max(data['brand_price_median']) - np.min(data['brand_price_median'])))
data['brand_price_min'] = ((data['brand_price_min'] - np.min(data['brand_price_min'])) / 
                           (np.max(data['brand_price_min']) - np.min(data['brand_price_min'])))
data['brand_price_std'] = ((data['brand_price_std'] - np.min(data['brand_price_std'])) / 
                           (np.max(data['brand_price_std']) - np.min(data['brand_price_std'])))
data['brand_price_sum'] = ((data['brand_price_sum'] - np.min(data['brand_price_sum'])) / 
                           (np.max(data['brand_price_sum']) - np.min(data['brand_price_sum'])))
data = pd.get_dummies(data, columns= ['model', 'brand', 'bodyType', 'fuelType',
                                     'gearbox', 'notRepairedDamage', 'power_bin'])
print(data.shape)
data.columns
(199037, 373)





Index(['SaleID', 'name', 'regDate', 'power', 'kilometer', 'regionCode',
       'seller', 'offerType', 'creatDate', 'price',
       ...
       'power_bin_20.0', 'power_bin_21.0', 'power_bin_22.0', 'power_bin_23.0',
       'power_bin_24.0', 'power_bin_25.0', 'power_bin_26.0', 'power_bin_27.0',
       'power_bin_28.0', 'power_bin_29.0'],
      dtype='object', length=373)
# 这份数据可以给 LR 用
data.to_csv('data_for_lr.csv', index=0)

特征筛选

过滤式

# 相关性分析
features = ['power','kilometer','brand_amount', 'brand_price_average','brand_price_max','brand_price_median']
for i in features:
    print(data[i].corr(data['price'], method='spearman'))
0.5728285196051496
-0.4082569701616764
0.058156610025581514
0.3834909576057687
0.259066833880992
0.38691042393409447
correlation = data[features].corr()
f, ax = plt.subplots(figsize = (7,7))
plt.title('Correlation of Numeric Features with Price',y=1,size=16)
sns.heatmap(correlation, square=True,vmax=0.7)
<matplotlib.axes._subplots.AxesSubplot at 0x1343f391b88>

在这里插入图片描述

包裹式

X.head()
SaleIDnameregDatepowerkilometerregionCodesellerofferTypecreatDatev_0v_1v_2v_3v_4v_5v_6v_7v_8v_9v_10v_11v_12v_13v_14trainused_timecitybrand_amountbrand_price_maxbrand_price_medianbrand_price_minbrand_price_sumbrand_price_stdbrand_price_averagemodel_0.0model_1.0model_2.0model_3.0model_4.0model_5.0model_6.0model_7.0model_8.0model_9.0model_10.0model_11.0model_12.0model_13.0model_14.0model_15.0model_16.0model_17.0model_18.0model_19.0model_20.0model_21.0model_22.0model_23.0model_24.0model_25.0model_26.0model_27.0model_28.0model_29.0model_30.0model_31.0model_32.0model_33.0model_34.0model_35.0model_36.0model_37.0model_38.0model_39.0model_40.0model_41.0model_42.0model_43.0model_44.0model_45.0model_46.0model_47.0model_48.0model_49.0model_50.0model_51.0model_52.0model_53.0model_54.0model_55.0model_56.0model_57.0model_58.0model_59.0model_60.0model_61.0model_62.0model_63.0model_64.0model_65.0model_66.0model_67.0model_68.0model_69.0model_70.0model_71.0model_72.0model_73.0model_74.0model_75.0model_76.0model_77.0model_78.0model_79.0model_80.0model_81.0model_82.0model_83.0model_84.0model_85.0model_86.0model_87.0model_88.0model_89.0model_90.0model_91.0model_92.0model_93.0model_94.0model_95.0model_96.0model_97.0model_98.0model_99.0model_100.0model_101.0model_102.0model_103.0model_104.0model_105.0model_106.0model_107.0model_108.0model_109.0model_110.0model_111.0model_112.0model_113.0model_114.0model_115.0model_116.0model_117.0model_118.0model_119.0model_120.0model_121.0model_122.0model_123.0model_124.0model_125.0model_126.0model_127.0model_128.0model_129.0model_130.0model_131.0model_132.0model_133.0model_134.0model_135.0model_136.0model_137.0model_138.0model_139.0model_140.0model_141.0model_142.0model_143.0model_144.0model_145.0model_146.0model_147.0model_148.0model_149.0model_150.0model_151.0model_152.0model_153.0model_154.0model_155.0model_156.0model_157.0model_158.0model_159.0model_160.0model_161.0model_162.0model_163.0model_164.0model_165.0model_166.0model_167.0model_168.0model_169.0model_170.0model_171.0model_172.0model_173.0model_174.0model_175.0model_176.0model_177.0model_178.0model_179.0model_180.0model_181.0model_182.0model_183.0model_184.0model_185.0model_186.0model_187.0model_188.0model_189.0model_190.0model_191.0model_192.0model_193.0model_194.0model_195.0model_196.0model_197.0model_198.0model_199.0model_200.0model_201.0model_202.0model_203.0model_204.0model_205.0model_206.0model_207.0model_208.0model_209.0model_210.0model_211.0model_212.0model_213.0model_214.0model_215.0model_216.0model_217.0model_218.0model_219.0model_220.0model_221.0model_222.0model_223.0model_224.0model_225.0model_226.0model_227.0model_228.0model_229.0model_230.0model_231.0model_232.0model_233.0model_234.0model_235.0model_236.0model_237.0model_238.0model_239.0model_240.0model_241.0model_242.0model_243.0model_244.0model_245.0model_246.0model_247.0brand_0brand_1brand_2brand_3brand_4brand_5brand_6brand_7brand_8brand_9brand_10brand_11brand_12brand_13brand_14brand_15brand_16brand_17brand_18brand_19brand_20brand_21brand_22brand_23brand_24brand_25brand_26brand_27brand_28brand_29brand_30brand_31brand_32brand_33brand_34brand_35brand_36brand_37brand_38brand_39bodyType_0.0bodyType_1.0bodyType_2.0bodyType_3.0bodyType_4.0bodyType_5.0bodyType_6.0bodyType_7.0fuelType_0.0fuelType_1.0fuelType_2.0fuelType_3.0fuelType_4.0fuelType_5.0fuelType_6.0gearbox_0.0gearbox_1.0notRepairedDamage_-notRepairedDamage_0.0notRepairedDamage_1.0power_bin_0.0power_bin_1.0power_bin_2.0power_bin_3.0power_bin_4.0power_bin_5.0power_bin_6.0power_bin_7.0power_bin_8.0power_bin_9.0power_bin_10.0power_bin_11.0power_bin_12.0power_bin_13.0power_bin_14.0power_bin_15.0power_bin_16.0power_bin_17.0power_bin_18.0power_bin_19.0power_bin_20.0power_bin_21.0power_bin_22.0power_bin_23.0power_bin_24.0power_bin_25.0power_bin_26.0power_bin_27.0power_bin_28.0power_bin_29.0
00736200404020.4150910.8275861046002016040443.3577963.9663440.0502572.1597441.1437860.2356760.1019880.1295490.0228160.097462-2.8818032.804097-2.4208210.7952920.91476214385.010.3241250.3407860.0320750.0020640.2096840.2076600.08165500000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000001000000100000010010000001000000000000000000000000
112262200303010.0000001.0000004366002016030945.3052735.2361120.1379251.380657-1.4221650.2647770.1210040.1357310.0265970.020582-4.9004822.096338-1.030483-1.7226740.24552214757.040.4343410.8352300.2056230.0041280.7139850.4370020.25730500000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000100000100000010100000000000000000000000000000000
2214874200404030.5149540.8275862806002016040245.9783594.8237921.319524-0.998467-0.9969110.2514100.1149120.1651470.0621730.027075-4.8467491.8035591.565330-0.832687-0.22996314382.020.0461170.4335780.2849060.0918470.0825330.2523620.28183400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000001000000100000010010000000000000000010000000000000
3371865199609080.5319171.000000434002016031245.6874784.492574-0.0506160.883600-2.2280790.2742930.1103000.1219640.0333950.000000-4.5095991.285940-0.501868-2.438353-0.47869917125.040.4450990.9268890.1603770.0041280.6505910.3984470.22521200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000010000000100000001010000000000000000000010000000000
44111080201201030.4275350.3103456977002016031344.3835112.0314330.572169-1.5712392.2460880.2280360.0732050.0918800.0788190.121534-1.8962400.9107830.9311102.8345181.92348211531.060.1480900.2945450.0509430.0092880.0885240.1445790.07302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000100000010010000000100000000000000000000000
X = data[data['train']==1].drop(['price','train'], axis=1)
X = X.fillna(0)
from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from sklearn.linear_model import LinearRegression
sfs = SFS(LinearRegression(),
           k_features=10,
           forward=True,
           floating=False,
           scoring = 'r2',
           cv = 0)

y = Train_data['price']
sfs.fit(X, y)
sfs.k_feature_names_
('regDate',
 'kilometer',
 'v_3',
 'v_4',
 'v_13',
 'brand_price_std',
 'brand_price_average',
 'model_167.0',
 'gearbox_1.0',
 'power_bin_24.0')
# 画出来,可以看到边际效益
from mlxtend.plotting import plot_sequential_feature_selection as plot_sfs
import matplotlib.pyplot as plt
fig1 = plot_sfs(sfs.get_metric_dict(), kind='std_dev')
plt.grid()
plt.show()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值