美团机器学习——特征工程
和几位同学交流了一下,也结合我这半个月学习机器学习原理的体会,我感觉我确实学不了机器学习,真的是太TM难!!!!痛定思痛,我决定舍弃机器学习了,转做开发去了。所以这应该是kaggle系列最后一篇博文了!
特征工程
更多的数据胜于聪明的算法,而好的数据胜于多的数据
在机器学习应用中,我们大多数时间都在进行特征工程和数据清洗,而算法和模型的优化仅仅占了一小部分
数值特征
1:截断。对于连续型数值特征,有时候太多的精度可能只是噪声。因此,可以在保留重要信息的前提下对特征进行截断
2:二值化。数值特征的一种常用类型是计数特征,如网站每天的访问量、餐厅的评论数、用户对一首歌的播放次数等。在大数据时代,计数可以非常快地累加。处理计数特征时,首先要考虑的是,保留为原始计数还是转换为二值变量来标识是否存在或者进行分桶操作。
3:分桶。在购物网站上,每件商品都会显示用户的评论次数。如果商品的评论次数跨越不同的数量级,则它不是一个好的特征。分桶是将数值变量分到一个桶里并分配一个桶编号
对于固定宽度的分桶,每个桶的值域是固定,如果每个桶的大小一样,它也称为均匀分桶,例如将人的年龄分为09岁、1019岁等。除此之外,桶的宽度也可以自定义。如果数值跨越不同数量级,可以根据10(或者其他任何适当的常数)的幂来分桶,如09、1099、100999、10009999等,另一种分桶方式是分位数分桶,虽然固定宽度的分桶易于实现,但如果数值变量的取值存在很大间隔时,有些桶里没有数据,可以基于数据的分布进行分桶,也即分位数分桶,其对应的桶里面数据一样多0-20%,20-40%
4:缩放。缩放即将数值变量缩放到一个确定的范围。:
标准化缩放(也称为Z缩放),即将数值变量的均值变为0,方差变为1
最大最小值缩放及最大绝对值缩放;
基于某种范数的归一化,如使用L1范数、L2范数将数值向量的范数变为
平方根缩放或对数缩放,对数缩放对于处理长尾分且取值为正数的数值变量非常有效,它将大端长尾压缩为短尾,并将小端进行延伸,平方根或者对数变换是幂变换的特例,在统计学中都称为方差稳定的变换
Box-Cox变换是简化的幂变换,Box-Cox 转换仅对取值为正数的数值变量起作用;
参考链接
5:特征交叉。特征交叉可以表示数值特征之间的相互作用,例如可以对两个数值变量进行加、减、乘、除等操作,可以通过特征选择方法(如统计检验或者模型的特征重要性)来选择有用的交叉组合。有些特征交叉组合,虽然没有直观的解释,但有可能对于模型效果有很大的提升。
特征交叉对于线性模型可以学习到非线性特征。
两个特征:年龄和性别,可以组合成 年龄_性别
6:非线性编码。线性模型往往很难学习到数据中的非线性关系,除了采用特征交叉的方式之外,也可以通过非线性编码来提升线性模型的效果。例如使用多项式核,高斯核等。另外一种方法是将随机森林模型的叶节点进行编码喂给线性模型,这样线性模型的特征包含了复杂的非线性信息。还有基因算法以及局部线性嵌入、谱嵌入、t-SNE等。
7:行统计量。除了对原始数值变量进行处理之外,直接对行向量进行统计也可以作为一类特征,如统计行向量中空值的个数、0的个数、正值或负值的个数,以及均值、方差、最小值、最大值、偏度、峰度等。
类别特征
类别数据的取值可以是数值类型(例如“1”代表男性,“0”代表女性),但是数值没有任何数学意义,它们不能进行数学运算
1:独热编码。通常,直接将类别特征的自然数编码特征喂给模型,效果可能比较差,尤其是线性模型。这是因为,对于类别特征的自然数编码,取值大小没有物理含义,直接喂给线性模型没有任何意义。我们常用的一种做法是对类别特征进行独热编码,这样每个特征取值对应一维特征,独热编码得到稀疏的特征矩阵。
2:分层编码。对于邮政编码或者身份证号等类别特征,可以取不同位数进行分层,然后按层次进行自然数编码,这类编码一般需要专业领域知识。
3:散列编码。对于有些取值特别多的类别特征,使用独热编码得到的特征矩阵非常稀疏,因此在进行独热编码之前可以先对类别进行散列编码,这样可以避免特征矩阵过于稀疏。实际应用中我们可以重复多次选取不同的散列函数,利用融合的方式来提升模型效果。散列方法可能会导致特征取值冲突,这种冲突通常会削弱模型的效果。自然数编码和分层编码可以看作散列编码的特例。
4:计数编码。计数编码是将类别特征用其对应的计数来代替,这对线性和非线性模型都有效。这种方法对异常值比较敏感,特征取值也可能冲突。
5:计数排名编码。它利用计数的排名对类别特征进行编码,其对线性和非线性模型都有效,而且对异常点不敏感,类别特征取值不会冲突。
6:目标编码。它基于目标变量对类别特征进行编码。对于基数(类别变量所有可能不同取值的个数)很大的离散特征,例如IP地址、网站域名、城市名、家庭地址、街道、产品编号等,上述预处理方法效果往往不太好。一种有效方式则是基于目标变量对类别特征进行编码,其适用于分类和回归问题。例如对于分类问题,采用交叉验证的方式,即将样本划分为5 份,针对其中每一份数据,计算离散特征每个取值在另外4 份数据中每个类别的比例。为了避免过拟合,也可以采用嵌套的交叉验证划分方法。回归问题同样采用交叉验证的方式计算目标变量均值对类别变量编码。在实际问题中,我们往往利用历史数据来预测未来结果。因此我们一般基于时间信息来划分训练集和验证集,利用相同时间窗口大小的历史数据来对类别特征进行编码。例如,在广告点击率预测问题中,我们计算广告主ID在过去固定一段时间内的点击率,对广告主ID进行目标编码。目标编码方法对于基数较低的离散变量通常很有效,但对于基数特别高的离散变量,可能会有过拟合的风险。因为很多类别特征的取值样本个数太少,不具有统计意义。对于这种情况,我们通常采用贝叶斯方法,即对统计特征进行贝叶斯平滑,如拉普拉斯平滑或者先验概率和后验概率加权平均的方式。
类别特征之间交叉组合。除了前面提到的数值特征之间的交叉组合外,类别特征之间的交叉组合也是很重要的特征。两个类别特征进行笛卡儿积操作可以产生新的类别特征,这种操作适用于两个类别特征的基数较小的情况。两个类别特征的笛卡儿积取值个数是两个类别特征取值个数的乘积,如果两个类别特征的基数很大时,交叉后的特征基数太大,效果可能并不好。除了两个类别特征的交叉,多个类别特征也可以交叉组合,根据实际需要可以进行二阶及二阶以上的交叉组合,最后通过特征选择方法选取重要的组合方式。除了上面提到的交叉组合外,另一种特征组合方式是基于统计的组合。例如针对城市ID和商品ID两个类别特征,我们可以计算某个城市有多少不同的商品ID以及当前ID出现次数的分布,从而得到新的数值特征,或者计算某个城市出现次数最多的商品ID,从而得到一个新的类别特征。对于多个类别特征也可以进行同样的操作。例如针对年龄、性别、产品ID三个类别特征,可以计算某个年龄段不同性别的人购买过多少产品或者对当前产品ID购买次数的分布等。在实际应用中,类别特征之间的组合方式千变万化,这类特征一般从业务逻辑的角度出发进行构造。相比类别特征之间的笛卡儿积操作,基于分组统计的特征组合方式计算更加复杂,而且一般强依赖专业领域知识,因此需要对业务逻辑有较好的理解。
类别特征和数值特征之间交叉组合。除了数值特征之间的组合以及类别特征之间的组合之外,类别特征和数值特征之间也可以进行组合。这类特征通常是在类别特征某个类别中计算数值特征的一些统计量。例如针对用户ID,统计过去一段时间内在网站上的浏览次数、购买次数,以及购买价格的统计量,如均值、中位数、标准差、最大值和最小值等;针对产品,统计用户对产品的评分、评价次数、购买次数、浏览次数等。再比如,统计产品在某个区域的销量、产品的价格,或者当前产品的价格跟产品所在区域内的平均价格的差价等。可以看出,这类特征也强依赖专业领域知识。上面的这种组合方式也可以看作是利用数值特征对类别特征进行编码,与前面提到的基于目标变量对类别变量进行编码的方法不同的是,这里不需要划分训练集进行计算。
数值特征和类别特征是机器学习应用中最常见的两类特征。上面我们提到了关于这两类特征的一些常用的特征预处理技巧,基于这些技巧可以构造大量特征。但我们无法构造所有可能的特征表达形式,一方面要考虑模型的使用成本,另一方面也要考虑特征的构造成本。当然,我们可以通过特征选择选取重要的特征,但特征选择成本也很高。因此,在实际应用中我们选择性地构造特征。对于不同类别的特征采取哪一种或者哪几种方法,则依赖于我们对业务和数据本身的理解以及对模型的理解。通过对数据内部结构和规律的探索性分析,可以找到跟目标变量相关的信息,进而根据模型需要的输入形式利用预处理技术对这些信息进行编码,即构造特征。