数据预处理作为机器学习中的关键一环,这里介绍其中的Binning 分箱

基本原理
Binning分箱指的是将连续的数值型特征转换成离散的类别型特征。一方面,极端的异常数值被转换为类别特征后,降低了异常数值大小的影响,提升模型鲁棒性;另一方面,相比于连续型特征,离散的类别型特征取值范围有限,降低了过拟合风险。例如,我们可以将原始的年龄数值特征转换为童年、青年、中年、老年这种类别特征
事实上,分箱的最大神奇之处在于:可以为模型引入非线性能力,来提升模型表现。例如,使用线性回归模型通过人群年龄来预测年收入。我们知道,一开始,年收入水平会随着年龄的增加而增加;但当过了某个年龄阶段后,年收入水平即会随着年龄的增加而下降。即呈现所谓的倒U形
如果使用原始的年龄数值作为特征输入,则年龄特征对应的就只有1个权重参数。显然这样的一条直线是无论如何也无法去拟合呈倒U形分布的样本点
但当我们通过分箱将其转换为类别特征(少年、中年、老年)并使用独热编码,就会有3个特征输入(少年、中年、老年),相应的就有3个权重参数。此时,即使在线性模型下,模型也可以为每个类别学习到一个独立的权重。具体地:w1、w3参数会获得一个较低的权重,而w2参数会获得一个较高的权重。这样一个线性的模型也可以很好的去贴合现实世界中的非线性现象
常见的分箱方法有:
- 等频分箱:划分为若干个箱子,使得每个分箱包含的样本数基本一致
- 等宽分箱:划分为若干个箱子,使得每个分箱区间的宽度基本一致
可使用Sklearn提供的KBinsDiscretizer实现等频/等宽分箱
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import numpy as np from sklearn.preprocessing import KBinsDiscretizer
age = np.array([7, 5, 3, 1, 99, 98]).reshape(-1,1)
quantile_discretizer = KBinsDiscretizer(n_bins=3, strategy='quantile', encode='ordinal')
quantile_discretizer.fit(age) age_quantile_binning = quantile_discretizer.transform(age)
edge = quantile_discretizer.bin_edges_[0] for i in range(len(edge)-1): print(f"#{i}号 分箱的取值区间: [{edge[i]:.2f}, {edge[i+1]:.2f})" )
print(age_quantile_binning)
print("-"*80)
uniform_discretizer = KBinsDiscretizer(n_bins=3, strategy='uniform', encode='onehot-dense')
uniform_discretizer.fit(age) age_uniform_binning = uniform_discretizer.transform(age)
edge = uniform_discretizer.bin_edges_[0] for i in range(len(edge)-1): print(f"#{i}号 分箱的取值区间: [{edge[i]:.2f}, {edge[i+1]:.2f})" ) print(age_uniform_binning)
|
输出结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #0号 分箱的取值区间: [1.00, 4.33) #1号 分箱的取值区间: [4.33, 37.33) #2号 分箱的取值区间: [37.33, 99.00) [[1.] [1.] [0.] [0.] [2.] [2.]] -------------------------------------------------------------------------------- #0号 分箱的取值区间: [1.00, 33.67) #1号 分箱的取值区间: [33.67, 66.33) #2号 分箱的取值区间: [66.33, 99.00) [[1. 0. 0.] [1. 0. 0.] [1. 0. 0.] [1. 0. 0.] [0. 0. 1.] [0. 0. 1.]]
|
参考文献
- 机器学习 周志华著
- 机器学习公式详解 谢文睿、秦州著
- 图解机器学习和深度学习入门 山口达辉、松田洋之著