本文参考《零基础入门数据挖掘 - 二手车交易价格预测》部分内容和代码,数据集为自建数据集。读者可使用原文数据集进行阅读试验。
常见特征工程
异常处理
- 通过箱型图(或3-Sigma)分析删除异常值;
- BOX-COX转换(处理有偏分布);
- 长尾截断;
特征归一化/标准化
- 标准化(转换为标准正态分布);
- 归一化(转换到[0,1]区间);
- 针对幂律分布,可以采用公式:log(/frac{1+x}{1+median})
数据分桶
- 等频分桶;
- 等距分桶;
- Best-KS分桶(类似利用基尼指数进行二分类);
- 卡方分桶;
缺失值处理:
- 不处理(针对类似XGBoost等树模型)
- 删除(缺失数据太多)
- 插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等;
- 分箱,缺失值一个箱;
特征构造
- 构造统计量特征,报告计数、求和、比例、标准差等;
- 时间特征,包括相对时间和绝对时间,节假日,双休日等;
- 地理信息,包括分箱,分布编码等;
- 非线性变换,包括log/平方/根号等;
- 特征组合,特征交叉
特征筛选
- 过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择法/相关系数法/卡方检验法/互信息法;
- 包裹式(wrapper):直接把最终要使用的学习器性能作为特征子集的评价准则,常见方法有LVM(Las Vegas Wrapper);
- 嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的方法有lasso回归;
降维
- PCA/LDA/ICA;
- 特征选择
部分特征工程实现代码
通过箱线图删除异常值
在箱型图中,数据被从大到小按顺序排列,图中出现的元素代表含义如下:
- 上四分位数Q3:75%分位点所对应的值
- 中位数Q2:50%分位点对应的值
- 下四分位数Q1:25%分位点所对应的值
- 上边缘(须):Q3+1.5(Q3-Q1)
- 下边缘(须):Q1+1.5(Q3-Q1)
那么,在箱线图中,位于合理范围的x值为:
$$Q1-1.5(Q3-Q1)\leqslant x \leqslant Q3+1.5(Q3-Q1)$$
和使用3σ准则剔除异常值相比,箱线图不需要数据服从正态分布,能真实直观的表现数据形状;箱线图以四分位数和四分位距作为判断异常值的标准,四分位数具有一定的耐抗性,多达25%的数据可以变得任意远而不会很大地扰动四分位数,使得异常值无法对数据形状造成巨大影响,因此箱形图识别异常值的结果比较客观。
下面给出使用箱线图进行异常值剔除的代码块:
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])
return data_n
Comments NOTHING