零基础入门数据挖掘比赛(天池二手车交易价格预测)
以下以Datawhale与天池举办的二手车交易价格预测这个数据挖掘赛题做的数据挖掘入门Task3笔记
Task3:特征工程
特征工程目标
通常做比赛,首先得了解赛题:
- 对于特征进行进一步分析,并对于数据进行处理 ;
- 完成对于特征工程的分析,并对于数据进行一些图表或者文字;
特征工程具体内容
异常处理
- 通过箱线图(或 3-Sigma)分析删除异常值 ;
- BOX-COX 转换(处理有偏分布) ;
- 长尾截断。
特征归一化/标准化
- 标准化(转换为标准正态分布);
- 归一化(抓换到 [0,1] 区间);
- 针对幂律分布,可以采用公式: l o g ( 1 + x / 1 + m e d i a n ) log(1+x/1+median) log(1+x/1+median);
- 定性变量编码,Label Encoder、Onehot Encoder、Distribution Encoder
# 我们对power为例 取log做归一化
from sklearn import preprocessing
min_max_scaler=preprocessing.MinMaxScaler()
#具体minmax的过程
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()
数据分桶
- 等频分桶;
- 等距分桶;
- Best-KS 分桶(类似利用基尼指数进行二分类);
- 卡方分桶;
- 了解预测值的分布:总体分布概况(无界约翰逊分布等);
# 数据分桶 也就是把连续的数据进行离散化切分,一类一类的
#以 power 为例
# 为什么要做数据分桶呢,原因有很多
# 1. 离散后稀疏向量内积乘法运算速度更快,计算结果也方便存储,容易扩展;
# 2. 离散后的特征对异常值更具鲁棒性,如 age>30 为 1 否则为 0,对于年龄为 200 的也不会对模型造成很大的干扰;
# 3. LR 属于广义线性模型,表达能力有限,经过离散化后,每个变量有单独的权重,这相当于引入了非线性,能够提升模型的表达能力,加大拟合;
# 4. 离散后特征可以进行特征交叉,提升表达能力,由 M+N 个变量编程 M*N 个变量,进一步引入非线形,提升了表达能力;
# 5. 特征离散后模型更稳定,如用户年龄区间,不会因为用户年龄长了一岁就变化
# 当然还有很多原因,LightGBM 在改进 XGBoost 时就增加了数据分桶,增强了模型的泛化性
data['power'].describe()
bin=[i*10 for i in range(31)]#设置划分的间隔是10,0、10、20\....300
data['power_bin']=pd.cut(data['power'],bin,labels=False)
data[['power_bin', 'power']].head()
# 删除不需要的数据
data = data.drop(['creatDate', 'regDate', 'regionCode'], axis=1)
缺失值处理
- 不处理(针对类似 XGBoost 等树模型);
- 删除(缺失数据太多);
- 插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等;
- 分箱,缺失值一个箱;
异常值处理
- 简单统计,如describe()的统计描述、散点图等;
- 正态分布、箱型图删除、截断;
- 利用模型进行离群点检测,聚类、k近邻、One Class SVM、Isolation Forest;
# 我们可以删掉一些异常数据,以 power 为例。
Train_data = outliers_proc(Train_data,'power',scale=3)
特征构造
- 构造统计量特征,报告计数、求和、比例、标准差等;
- 时间特征,包括相对时间和绝对时间,节假日,双休日等;
- 地理信息,包括分箱,分布编码等方法;
- 非线性变换,包括 log/ 平方/ 根号等;
- 特征组合,特征交叉;
- 仁者见仁,智者见智;
# 特征构造
#训练集和测试集放在一起,方便构造特征
Train_data['train'] = 1
Test_data['train'] = 0
data=pd.concat([Train_data,Test_data],ignore_index=True)
# 使用时间: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
# .dt.days两个时间做差后转化为int64形式的,也就是差了n天
特征筛选
- 过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系数法/卡方检验法/互信息法;
#特征筛选
#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'))
- 包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有 LVM(Las Vegas Wrapper);
- 嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有 lasso 回归;
特征降维
- PCA/ LDA/ ICA;
- 特征选择也是一种降维;
其他
- 删除无效列、更改dtypes、删除列中的字符串、将时间戳从字符串转换为日期时间格式等;
以上为特征工程概述图
经验总结
上述为比赛中特征工程的一些操作,实际的特征工程可以按照实际的情况和比赛以及数据来不断的做一些处理。在整个比赛包括工业界中,EDA和特征工程这两步骤中,占据整一个内容非常高的权重,特别尤为重要,好的特征工程对整体的得分也会显著的提升。