之前在做机器学习课的大作业时,我们组用到了2014年kaggle的点击率预测数据,于是我们特意参考了第二名的一个思路——mean encoding,我在这里把这个方法完整记录下来。
该思路的来源是一篇非常古老的2001年KDD论文:
A Preprocessing Scheme for High-Cardinality Categorical Attributes in Classification and Prediction Problems
高基数类型特征的常见处理方法
mean encoding方法建立在一系列前提方法的基础之上。网络上已有相对完善的资料,我将其总结补充在这里介绍一下。
-
one-hot encoder和label encoder
这两者是最机器学习领域最常见的定类变量预处理方法,不做过多介绍,可参考sklearn的OneHotEncoder和LabelEncoder文档。
然而在邮编、IP地址、家庭住址还有我们遇到的device_ip等等情况时,它们有着极多的类别数量。这些特征如果直接用独热编码将会产生无数新特征,处理起来在时间和内存上都无法接受;如果使用label encoder则又会暗含从0-N-1的数字顺序关系,这对于定类变量来说是毫无道理也会影响模型结果的。
那么针对高基数这一问题,一个常见的基于one-hot encoder的思路如下: -
clustering[1]
- 将1到N(N非常大)的映射问题通过聚类转换为1到K(K<<N)
- 然后再进行独热编码
举个例子,家庭地址的数量,即使限制在一个小区内讨论数量也会极大,如果我们不按门牌号而是按照楼分类,比如把属于16号楼的所有住址全部设置为16号楼而不具体下去,那么这样一下就减少了大量的特征取值。然后再将所有的楼号通过独热编码变为N列,就完成了类别值到数值的转换。这也就是聚类的思路。
然而这种做法导致了特征信息的丢失(本来有很多不同楼层、位置的具体细节,结果都看成一种一栋楼了)。
-
smoothing
那么我们把这种clustering泛化一下,不要强迫为[1号楼、二号楼](0、1)了,改成概率估计(0 ~ 1之间的小数、0 ~ 1之间的小数),也就产生了smoothing。
平均数编码就是smoothing的一种实现。
值得一提的是,smoothing作为连续化标签的一种方式,在各种场合都很常见,比方说在做医疗数据时,一般情况下病人的各种病症(diagnosis code)是作为二值变量,需要被预测的。然而可以想见很多常见病症比如肥胖、之类的,是与否,只不过是判断其是否达到了一个设定好的阈值。于是当判断肥胖病人时,临近阈值和和刚过阈值显然差距不大,却在分类任务里被设置为了两类;临近阈值和数值很小的病人明显差距很大却被分为一类。解决这种问题的一个办法也就是smoothing,把离散数值变为连续数值,当然在此情况下做这样的转换需要专业的医疗知识。
算法思路
具体算法细节可以参考知乎文章,简要来说就是使用贝叶斯的方法。
记先验数据属于某一个 target 的数量, N 为先验数据总量。
先验概率:数据属于某一个 target(y) 的概率。
P ^ ( y = target ) = C ( y = target ) N \hat{P}(y=\operatorname{target})=\frac{\mathrm{C}(\mathrm{y}=\operatorname{target})}{\mathrm{N}} P^(y=target)=