“零基础入门数据挖掘 - 二手车交易价格预测”学习赛的Task03-学习日志


前言

本文章为天池“零基础入门数据挖掘 - 二手车交易价格预测”学习赛的Task03-学习日志,旨在了解特征工程及具体分析内容,通过特征工程分析数据,对数据进一步处理,提高预测的可靠性,使得之后的估计及模型建立更加顺畅合理。
学习网址添加链接描述


一、特征工程学习思维导图

在这里插入图片描述


二、特征工程是什么

- 特征工程(Feature Engineering)是将原始数据转化成表达问题本质的特征的过程,其将特征运用到预测模型中并提高对不可见数据的模型预测精度。通俗来说,就是发现对因变量有影响的重要特征。

- 特征与VS属性:特征认为是对建模有用的属性,或对解释y起重要作用的属性。

-即根据特征对被解释变量的重要性(解释程度)给变量赋值打分,并按分值排序,具有较高得分的特征可以被选出来包含在训练集中,同时剩余的就可以被忽略。相关系数和其他单变量的方法(每一个变量被认为是相互独立的)是比较通用的评估方法。 更复杂的方法是通过预测模型算法来对特征进行评分。这些预测模型内部有这样的特征选择机制,比如MARS,随机森林,梯度提升机。这些模型也可以得出变量的重要性。

具体流程图可参考正阳的深度了解特征工程。学习地址:添加链接描述


三、特征使用和获取

在这里插入图片描述

1.明确目标,寻找影响因素

明确研究问题及预测目标,尽可能找出影响预测目标的可能性因素。


2.特征可用性评估

评估标准包括:

1.获取速度,即特征有可获取性,如果需要长时间高难度作业,则考虑剔除。
2.覆盖率,即所选取特征尽可能多的可以解释因变量。
3.准确率


3.特征的选取与构造

需要根据所研究领域与所研究问题的数据特征做具体判断,常用特征如下:

-构造统计量特征,报告计数、求和、比例、标准差等
-时间特征,包括相对时间和绝对时间,节假日,双休日等;
-地理信息,包括对常规特征进行分箱,分布编码等方法获取新的特征集;
-对常规特征非线性变换,包括 log/ 平方/ 根号等获取;
-通过特征组合,特征交叉获取;

4.特征的储存


四、特征处理

在这里插入图片描述

1.特征的清洗

选取特征后,会发现不同特征的相应数据存在许多问题,有的问题较大,如果假如训练集对后期建模的准确性影响较大,所以需要通过简单的数据描述来发现问题,数据的描述统计分析主要包括以下几个方面:

-数据结构
-质量检验:标准性、唯一性、有效性、正确性、一致性、缺失值、异常值、重复值
-分布情况:统计值、探索性数据分析(EDA)、集中趋势、离中趋势、分布形状

其次,采集过程中会出现样本不均衡,针对此问题,有以下几种方法解决:
-过采样和重采样
-每个Batch对每类样本设置比例,保证在一个Batch里是相对均衡的
-focal loss(多用于检测中二分类,不是严格意义上的长尾数据)
-loss reweight
学习地址:添加链接描述


2.预处理

预处理原因: 1.量纲不一致:单位,数据大小不一致的变量无法在一起比较; 2. 存在缺失; 3. 数据存在异常; 4. 定性特征不能直接使用; 5. 信息可利用率低。

2.1针对单个特征值

2.1.1 无量纲化-归一化/标准化

标准化:通过减去均值后除以标准差实现,通常是为了转换为标准正态分布。

在这里插入图片描述

归一化:常见的一种为利用两个最值进行缩放,目的为了转换到[0,1]区间内。

在这里插入图片描述

二者区别:标准化是依照特征矩阵的列处理数据,其通过z-score的方法,将样本的特征值转换到同一量纲下;归一化是依照特征矩阵的行处理数据,其目的在于样本向量在点乘运算或其他核函数计算相似性时,拥有统一的标准,也就是说都转化为“单位向量”
具体参考:小T数据站的“特征工程添加链接描述


2.1.2 Dummy coding(哑变量)

哑变量定义:哑变量(Dummy Variable)是人为虚设的变量,通常取值为0或1,来反映某个变量的不同属性。对于有n个分类属性的自变量,通常需要选取1个分类作为参照,因此可以产生n-1个哑变量。

引入哑变量的情况:
1.无序多分类变量(如:色彩-红黄蓝);
2. 有序多分类(如:对某事物态度-好、一般、坏)
3 连续型变量(对连续型变量分组,对每组赋值)


2.1.3 缺失值处理
2.1.3.1 缺失类型

1.随机缺失:数据缺失概率与丢失数据本身无关,二者相互独立,但是可能依赖其他完全变量;
2.完全随机丢失:缺失完全随机,缺失不影响随机性;
3. 非随机丢失:数据的缺失与不完全变量自身的取值有关。
前两种情况下可以根据其出现情况删除缺失值的数据,第三种删除会带来偏差。

2.1.3.2 缺失处理方法

1.直接删除:适用于少量缺失值,且缺失值与其他变量独立

2. 插值补全:
(1) 人工填写:主观性较大,对数据规模大,空值较多时不建议使用;
(2)特殊值填充:如所有的空值都用“unknown”填充,不建议使用;
(3)平均值填充:适用于空值为数值型数据
(4)热卡填充(就近补齐):在完整数据中找到一个与它最相似的对象,然后用这个相似对象的值来进行填充;
(5)K最近距离邻法:根据欧式距离或相关分析来确定距离具有缺失数据样本最近的K个样本,将这K个值加权平均来估计该样本的缺失数据
(6)可能值填充
(7)回归:通过未缺失数据回归估计(常用)
(8)期望值最大化
(9)C4.5法
(10)多重插补

3.不处理缺失值:此种方法适用于贝叶斯网络和人工神经网络等处理数据方法。

4.数据分箱:将缺失值单独一箱

具体学习链接:添加链接描述

2.1.4 异常值处理

1.通过箱线图(或 3-Sigma)分析删除异常值;
2.BOX-COX 转换:非正态分布下使用,通过Box-Cox做如下变换后可寻找到最佳的λ值,再根据λ值对因变量进行变换;
在这里插入图片描述
3. log/指数变换:主要适用于长尾数据或偏态严重数据。

2.2 针对多个特征

2.2.1降维

(1)主成分分析算法(PCA):通过线性投影,将高位数据映射至低维,,并期望在所投影的维度上数据的方差最大,以此使用较少的数据维度,同时保留住较多的原数据点的特性;

(2)LDA:是一种有监督的线性降维算法,为了使得降维后的数据点尽可能地容易被区分;

(3) 局部线性嵌入 (LLE):是一种非线性降维算法,它能够使降维后的数据较好地保持原有流形结构.
原理:添加链接描述

2.2.2数据分桶

分箱必要性:
(1) 对异常数据有很强的鲁棒性;
(2)逻辑回归中,因为哑变量的引入,使得非线性可能性增大,分箱可以加大拟合;
(3)缺失值可单独分箱作为特殊变量
(4)降低模型运算复杂程度
分桶方法:
(1) 等距分桶
(2)等频分桶
(3)卡方分摊
(4)Best-KS 分桶(类似利用基尼指数进行二分类)
学习链接:添加链接描述

2.2.3 特征筛选
2.2.3.1 过滤式

思路:先对数据进行特征选择,然后通过学习器将自变量和目标量关联。
常用方法:Relief,方差分析,相关系数,卡方检验,互相信息法

2.2.3.2 包裹式

定义:直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有 LVM(Las Vegas Wrapper);
思路:通过目标函数决定是否加入变量
常用方法:完全搜索、启发搜索、随机搜索(GA/SA)

2.2.3.3 嵌入式

定义:结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有 lasso 回归
思路:学习器选择特征自动化
常用方法:正规化(lasso/Ridge)、决策树、深度学习

五. 案例分析-二手车数据

1.删除异常值

以power为例删除异常值,代码如下:

# 这里我包装了一个异常值处理的代码,可以随便调用。
def outliers_proc(data, col_name, scale=3):
    """
    用于清洗异常值,默认用 box_plot(scale=3)进行清洗
    :param data: 接收 pandas 数据格式
    :param col_name: pandas 列名
    :param scale: 尺度
    :return:
    """

    def box_plot_outliers(data_ser, box_scale):
        """
        利用箱线图去除异常值
        :param data_ser: 接收 pandas.Series 数据格式
        :param box_scale: 箱线图尺度,
        :return:
        """
        iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
        val_low = data_ser.quantile(0.25) - iqr
        val_up = data_ser.quantile(0.75) + iqr
        rule_low = (data_ser < val_low)
        rule_up = (data_ser > val_up)
        return (rule_low, rule_up), (val_low, val_up)

    data_n = data.copy()
    data_series = data_n[col_name]
    rule, value = box_plot_outliers(data_series, box_scale=scale)
    index = np.arange(data_series.shape[0])[rule[0] | rule[1]]
    print("Delete number is: {}".format(len(index)))
    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])[rule[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])[rule[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])
    plt.show()
    return data_n


train = outliers_proc(train, 'power', scale=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

在这里插入图片描述
结果分析:power中过高异常值较多,呈现右偏,长尾效应较为明显,但数量过多不适合直接删除,暂时做保留处理。

2.特征构造

1.数据合并查看空集,代码如下:

train['train']=1
test['train']=0
data = pd.concat([train, test], ignore_index=True, sort=False)

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'))

data['used_time'].isnull().sum()

结果如下:

15072

结果分析:空值数量过多不适合直接删除,并且之后会使用XGBoost 之类的决策树,其本身就能处理能力,缺失值暂时做保留处理。

2.数据分桶,代码如下:

bin = [i*10 for i in range(31)]
data['power_bin'] = pd.cut(data['power'], bin, labels=False)
data[['power_bin', 'power']].head()

# 完成分桶后,就可以删掉原始数据了
data = data.drop(['creatDate', 'regDate', 'regionCode'], axis=1)

结果如下:

	power_bin	power
0	5.0	60
1	NaN	0
2	16.0	163
3	19.0	193
4	6.0	68

3.有偏分布处理,查看power分布代码如下:

data['power'].plot.hist()
plt.show()

结果如下:在这里插入图片描述
对其取 log,做归一化分布代码如下:

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()

结果如下:

在这里插入图片描述

3.特征筛选

3.1 过滤式

可通过相关系数或相关性可视化判断是否过滤。
相关系数代码如下:

print(data['power'].corr(data['price'], method='spearman'))
print(data['kilometer'].corr(data['price'], method='spearman'))
print(data['brand_amount'].corr(data['price'], method='spearman'))
print(data['brand_price_average'].corr(data['price'], method='spearman'))
print(data['brand_price_max'].corr(data['price'], method='spearman'))
print(data['brand_price_median'].corr(data['price'], method='spearman'))

结果如下

0.5737373458520139
-0.4093147076627742
0.0579639618400197
0.38587089498185884
0.26142364388130207
0.3891431767902722

可视化代码如下

data_numeric = data[['power', 'kilometer', 'brand_amount', 'brand_price_average', 
                     'brand_price_max', 'brand_price_median']]
correlation = data_numeric.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.8)
plt.show()

结果如下
在这里插入图片描述

3.1 包裹式

处理代码如下:

# k_feature 太大会很难跑,没服务器,所以提前 interrupt 了
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)
x = data.drop(['price'], axis=1)
x = x.fillna(0)
y = data['price']
sfs.fit(x, y)
sfs.k_feature_names_ 

# 画出来,可以看到边际效益
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()

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值