推荐系统的特征工程
推荐系统中最重要的两部分是特征和模型,早期模型上没有很大突破的时候,人工特征工程是推荐系统发展的主要方向。在这里我总结一下做特征工程的思路和不同特征的处理方式。
1. 创造特征的思路
- 业务背景特征
在推荐系统中猜测用户是否点击内容,可以仔细分析用户从打开手机到看到推荐内容的整个过程中的任何因素,比如这个过程大致分为用户打开手机、用户看到推荐内容、用户是否点击三个过程,针对用户打开手机这个动作,可以产生的特征是打开的时间、地点、手机的类型、手机应用启动时间、手机屏幕大小等因素。针对用户看到推荐内容这个过程,可以找到的特征有推荐内容出现的位置、推荐内容的类型、推荐内容的大小、推荐内容的出现次数、是否有类似推荐内容、推荐和历史推荐的相关性等等特征。找业务背景特征需要将自己代入业务环境下,思考自己在整个过程中每一个动作和目标之间的关系,最终找到合适的特征 - 数据本身的特征
针对推荐系统来说,推荐涉及到的物件有用户、推荐内容、推荐平台、客观环境因素。这些因素背身的特征也是关键的因素 - 交叉特征
在早期,无数的工程师竭尽全力创造特征,无穷的特征被发现,创造特征已经成为流水化工作,想要继续创造新的特征在今天是一件非常困难的事情,所以更好的方式是利用以往创造的特征,从细粒度上描述用户,所以就出现了特征交叉创造特征的方式。
2. 特征的处理方法
2.1 离散特征
在推荐系统中,大多数特征是离散特征。同时连续特征也会转换成离散特征,所以离散特征的处理方式决定整个模型的数据输入。离散特征通常有LabelEncoding、OnehotEncoding、HashEncoding和Embedding四种处理方式。
2.1.1. LabelEncoding
是将离散特征编码成连续的数字。sklearn.preprocessing.LabelEncoder工具可以实现这个功能。
优点:
直接、简单
缺点:
只有简单的数字,数字容易给对数值敏感的模型带来损失,比如SVM、LR还有NN模型。所以这种方法很少用到。
2.1.2. OnehotEncoding
OneHotEncoder同样是对离散特征编码,离散特征中有多少不同的值,就用多少维来表示该特征。sklearn.preprocessing.OneHotEncoder工具可以实现这个功能。onehot之后成为稀疏矩阵,可以用sparse工具存放。
Onehot主要作用在两个场景上:
1)文字离散特征进行Labelhot之后。在对数据集进行处理时候我们会遇到一些包含同类别的数据(如:country)。这样的数据是非numerical的数据,所以我们可以用数字来代替,比如不同的国家我们可以用1,2,3区分不同国家,但是这样会出现一个比较严重的问题。就是国家之间的地位是相同的,但是数字有顺序大小之分。所以我们用另一种方法,就是将不同的类别(如不同国家)另外分为一个列,属于这个国家的设置为1,不属于的设置为0.
2)数字离散特征。原因同上。
优点:
避免数值长度对模型的影响
缺点:
其一,造成维度过高过稀疏的问题。举例来说对于普通的离散特征用户类型,可能只有登录用户,未登录用户,vip用户等十几种用户类型,onehot后维度只增加十几维。但是对于用户ID类型(一般是对象原始ID和hash之后的ID)的离散特征,每个ID之间没有关联,每个用户都有一个ID,ID数量巨大,onehot之后的维度增加到成百上千,甚至更多,特征数量急剧增多,整体成为海量稀疏。其二,onehot只有每个特征只在一个数据点上被激活,完全不具有可推广性。所以推荐系统针对ID类特征做了HashEncoding和Embedding的转换,也有开发了FM、FFM以及各种深度Embedding模型。
2.1.3. HashEncoding
针对离散特征中的user_id,advertisement_id,直接做one-hot会导致维度爆炸的问题,通过hashing trick对feature先做hash之后取模降低维度,缓减这一问题。这种方式是目前推荐系统用的最广泛的方式。
优点:
通过哈希函数自定义变换后的维度长度,节约存储空间和时间;省掉onehot的对照表,只保留hash函数
缺点:
对于相同意义或者相近的词语容易产生hash冲突,导致结果共享位置,影响模型;hash之后的结果没有实际意义;hash之后的结果也无法映射到原来的离散特征。
hash方式在推荐系统中的应用,在这篇文章中总结的很好,有兴趣的可以看一下。
2.1.4. Embedding
2010年FM模型首次提出为每个特征学习隐向量的概念,通过模型为每个特征学习到一个相关向量,向量大小可以自定义,向量之间存在相似性。这种方式首次解决了维度变化之后特征失去联系的问题。之后随着技术的发展,word2vec、FFM模型、DepFM、item2vec等工具都可以产生特征的embedding向量,后来更是everything 皆可embedding的状态。
优点:
- Embedding向量可以表示词语之间的关系。训练模型的过程中,每个嵌入的向量都会得到更新。如果你看到了博客上面的图片你就会发现在多维空间中词与词之间有多少相似性,这使我们能可视化的了解词语之间的关系,不仅仅是词语,任何能通过嵌入层 Embedding 转换成向量的内容都可以这样做;
- 向量之间具有语义信息,所以基于向量的操作可以带来更多特征和信息;
- 向量的长度是可控的。
缺点:
需要大量的语料训练embedding向量,如果数据较少,embedding学习不充分,结果得不到保证。
2.2. 连续特征
在推荐系统,特征是数值类型,且数值是连续具有实际意义的特征被称为连续特征。
连续特征的广泛取值范围对模型的非常大,模型容易倾向连续特征,所以通常将连续离散化,变成离散特征。
2.2.1. 离散化的好处
- 连续特征重要的不是数值,是分段和所处的位置。比如年龄特征,15岁,这个信息是没有意义的,但是15处于12-18之间,表示青少年,这个特征更有意义。
- 连续特征经常出现小数和异常数字,这些数字容易使模型产生过拟合现象,离散化之后,没有具体数值,增加数据的健壮性,避免模型过拟合。
- 离散化后得到稀疏向量,稀疏向量内积乘法运算速度只和有值的向量有关,计算速度非常快,计算结果方便存储,有大量的优化算法,比如CSR、CSC等
- 离散化后的特征增加和减少非常容易,适合模型的快速迭代
2.2.2. 离散的坏处
离散化将是数值变成符号,损失大量数值,带来的损失也会降低模型的推荐效果。通常会尽可能地从多种角度离散化,避免信息损失。也会考虑合适的离散化标准,比如分桶离散化中桶的大小,分段离散化中段的间隔等等。
2.2.3.离散化的处理方式
- 分箱
分箱法又分为等宽分箱法和等频分箱法,前者制定定长的间隔将特征放入不同箱子内,后者根据频率划分箱子,这两种做法都有一定的缺陷。
等宽分箱法对异常点比较敏感,比如数据正常范围是30-60,现在出现了一个特征本来是30不小心读取成了300,那么宽度会被拉长,实例就主要集中在前面的箱体中,后面的箱体几乎没有实例,解决的方法主要是设立阈值移除阈值以外的实例。
等频分箱法的缺陷是完全按照频率划分会出现实例特征相同却不在同一个箱体内的情况,解决办法也很简单,在划分完成后进行微调就可完成。 - 1R方法
这个方法是分箱法的有监督版本,把前6个实例放入箱子中,然后后面实例放入箱子时,对比当前实例标签与箱子中大部分实例标签是否相同,如果相同放入,如果不相同,那么形成下一个6实例的新箱子,等到最后全部放入箱子中,将箱子中大多数实例标签作为箱子的标签,再将标签相同的箱子合并。在大多数算法中使用的是这种方法。 - 基于卡方的方法
首先将数值特征的每个不同值看做一个区间对每对相邻区间计算卡方统计量,如果大于阈值就合并,递归进行直到找不到卡方统计大于阈值的时候停止。 - 基于熵的方法:
其实就是照搬了决策树的思路,使用合成的方法或者分裂的方法根据熵计算和阈值判定来决定合成或分裂。
知乎上有个关于离散的见解,个人觉得是个新思路,所以记录在这里:知乎地址
总结来说:推荐系统的特征流程是数据预处理->离散化->Labelhot->Onehot->Embedding->模型