在多数数据和机器学习的blog里,特征工程 Feature Engineering 都很少被提到。做模型的或者搞Kaggle比赛的人认为这些搞feature工作繁琐又不重要不如多堆几个模型,想入手实际问题的小朋友又不知道怎么提取feature来建模型。我就用个性化推荐系统做个例子,简单说说特征工程在实际的问题里是怎么做。
定义
特征工程 Feature Engineering 在一篇Kaggle blog上有很好的定义:
By feature engineering, I mean using domain specific knowledge or automatic methods for generating, extracting, removing or altering features in the data set.
基本上说是,用目标问题所在的特定领域知识或者自动化的方法来生成、提娶删减或者组合变化得到特征。这些特征可能是显而易见比如说商品的品牌,也有可能需要复杂的模型计算,比如Facebook上用户A和用户B之间关系的紧密程度(FB使用了一个决策树来生成一个描述这个程度的向量,这个向量决定了他们News Feed推荐内容。)。这篇blog覆盖了一些用领域知识的方法,自动化方法在这里没有提及。
背景
个性化推荐系统 Personalized recommender system 比其他的机器学习方法更依赖特征工程,所以我拿它来当作问题的背景,结合我之前做过的一个推荐系统里相关经验来说说特征工程具体是个什么东西。
关于推荐系统和个性化推荐系统,可以参看wikipedia具体不赘述,以下的要点也尽量点到为止,否则这篇又成了“收藏了Mark了”但是不会读的冗余长文。以下如果不特别指出,我就用推荐系统作为“个性化商品推荐系统”的简称。简单来说,推荐系统就是你买了商品A,我们给你算出来个推荐列表 B C D E 等等。商业上来说个性化的推荐比一般化的推荐更能吸引顾客点击或购买,所以利用特征功能提取这些“个性化”的特征放到推荐模型里就很重要,比如在我们的推荐系统里,把“品牌”的特征加进去,相对于 baseline 提高了20%左右的nDCG。推荐系统可以是机器学习的模型也可以是基于关联或者统计规则的模型,对后者来说特征对推荐效果的提升占的比重更大。
利用领域知识生成和提取特征
这几乎是特征工程里占大半时间的工作了:如何描述个性化并且用变量表示成特征。一般方法就是,想想你就是该商品的目标用户,你会想要什么样的个性化。
比如说我们做一个女性衣服类的推荐引擎,这个网站卖各种牌子颜色尺寸等。我们列出可能相关的一些特征,然后在实际购买数据里面检查他们是否对购买结果产生影响和关联性。比如,从购买数据里可以看出,女性对衣服的品牌多数有固定偏好,比如我太太就很喜欢LOFT的衣服。这些能对购买产生影响的因素都可以成为特征。
这部分工作需要很多领域知识,一般需要一组的研究人员讨论,要认真的思考这个特定问题有些什么和别的问题不同的特征,也建议和市场部销售部等有领域知识的专家讨论。经验上来说,这些特征提取的越多越好,并不用担心特征过多,因为推荐系统的数据量都比较大,并且基于一些规则可以很好的筛选特征。
很多机器学习的方法也可以拿来提取一些比较不容易得到的直接特征,比如说原始数据里面没有人工标记过商品的颜色,这些颜色可以通过图像识别得到。统计规则也可以从销售数据里得到一些特征,比如该商品的流行程度。
注意,这些特征可能是固定不变的,比如颜色,品牌等。它也有可能随着时间变化,比如商品的销售排名。实际经验来说,时间变化采样的颗粒度要按照实际推荐效果来决定,很可能过去三个月的销售排名对推荐效果来说可以很稳定,也或许昨天的排名对今天的推荐效果比三个月平均更好。
特征的表达
大家都知道特征可以是“红”“绿”“蓝”这些离散特征,也可以是1.57这样的连续值特征。一个特征具体如何表达,要看在它在具体模型上怎么用。某些特定问题更倾向于离散特征,因为像推荐系统这样数据很大的情况可以利用模型训练这些特征得到比连续值表达更好的效果。
比如说,商品的流行度可以是一个特征,因为对于某些流行的商品大家都抢着买,喜欢跟风买热门商品这一特性可以作为推荐的特征。我们可以按照销量排名然后归一化得到每个商品的流行度值,但是直接用这个连续值会有一些问题,比如说用户甲买了流行度分数为 0.75 0.5 0.2 0.1的四个商品,用户乙买了流行度为0.7的一个商品,他们两个怎么比?
如果还记得算法书上说的,定义几个桶buckets,把流行度分到这几个buckets里面,可以解决这个问题。比如定义三个桶:很流行1-0。95,较流行0.95-0.75,普通0.75-0.4。这样用户甲的特征就是[0,1,1]用户乙的特征就是[0,1,0],这样你的推荐模型就可以做一些对比他们俩的相似度或者其他推荐计算了。
顺道提一下就是,为什么在这里直接把0.4之后的丢掉了以及为什么取了三个buckets。这个要看具体问题里面具体特征的用处。
如果这个模型是学习训练出来的,可以用一些feature selection的办法自动去掉一些不需要的bucket。对于那些不是学习出来的模型比如是简单的相似性模型,按照实际推荐效果思考一下用户的行为特征,需要丢弃一些特征。我之前包含过0.4以下的部分但是实际测试的时候发现推荐结果会恶化,也就是说对于我们的问题,用户喜欢跟风买热门的,但是不喜欢一直买冷门的。
特征需要按照实际购买数据进行修正和理解。三个buckets是我们系统里效果最好的。
一个比较高级的例子是 Facebook 在他们的 Machine Learning meetup 上提到的推荐News feed的特征。每个用户对于其他用户的 news 的点赞和留言以及其他的动作都会得到一个评价值,这是一系列的连续值,直接拿来训练模型效果不好。他们的做法是做了一个简单的决策树,训练的输入是这些连续值,训练目标是看对于用户A是否应该显示用户B的 news 。这个决策树显然很粗糙,但是树的每个叶子节点可以成为一个特征,那么这些叶子节点就可以当作用户A的特征向量,拿来训练其他模型比如Logistic Regression,效果不错。
直接特征和间接特征
直接特征 Extacted Feature 就是比如商品的品牌,间接特征 Derived Feature 可以是从直接特征或者各种数据组合里计算推导出来的。
间接特征的一个例子还是品牌特征,拿女性服饰类举例。比如我太太很喜欢LOFT的衣服,但如果一个推荐引擎使劲给推荐LOFT牌的衣服,她也会很烦。所以品牌并不完全是一个直接特征,它可以有一些变化。比如从购买数据里面看到,购买了LOFT牌衣服的,有20%也购买了J Crew牌,15%也购买了Ann Taylor牌。所以 LOFT 这个特征应该变成一个向量[LOFT:1, J_Crew:0.2, Ann_Taylor:0.15,…]。实际效果上它提高了推荐的多样性,在多个测试函数中都有不错的提升。
间接特征另外一个高级一些的例子就是用户职业。绝大多数用户都不会填自己的职业等个人相关信息,主要是因为隐私或者就是因为麻烦。从用户的购买记录和浏览记录里面,我们可以定义几个预设的职业类型然后用户的职业预测到这几个类型里。比如用户买过一些转换插头和充电器还有旅行电脑包,所以他可能常外出旅行,所以以后推荐的商品可能是轻便携带;又比如用户买过母婴用品就知道该用户可能自己是妈妈或者家里有小孩。
关于间接特征我印象最深的是美国亚马逊上的性别特征。我有一次给我太太买了给女生修眉毛的剃刀,亚马逊的推荐内容就立刻从推荐相机鼠标键盘等男性特征较强的变成了推荐时尚杂志这种有女性特征的东西。
间接特征的提取可以用到很多机器学习的技术,比如根据商品的文本描述提取它的文本向量,以这些文本向量为特征训练多分类的分类器,可以把商品分类对应到各种用户职业特征上。它也可以利用人工标记的类型列表,比如时尚杂志的女性特征。它也可以利用一些统计规则,比如单反相机的购买记录里,男性的比例会高于女性,所以单反相机的性别特征向量可以是购买人数性别的比例值。
特征选择
这部分的工作就看起来比较高级一些,比较贴近机器学习的研究工作。一般来说是两个方法:基于领域知识的手工选择以及自动选择方法。
对于关联规则和统计规则的模型来说,手工选择的比重要大一些。比如我们已有了baseline的特征向量,现在加进去品牌偏好,给一定的权值,看评价函数输出的结果是否增强了推荐效果。对于学习的模型来说,可以通过模型自动选择每个特征的权值,按照和效果的关联来调整模型的参数。这里需要提醒的是,这个选择过程不是单增单减,很可能遇到两个特征组合A+B效果很好,A+C效果也很好,但是A+B+C效果就呵呵了。个人建议在关联和统计规则里面把最重要的几个特征放进去然后优化关于这几个特征的规则,把复杂的特征选择留给学习出来的模型。
自动选择方法就很多了,用的也是常用的各种自动选择方法,什么forward selection啊backward selection啊各种regularization等等,全写在这里篇幅就太长,推荐看看一些其他关于机器学习里 feature selection 的blog和综述。值得提醒的是选择方法和评价函数的关联。推荐系统的评价函数一般不是AUC曲线等按照error计算的函数,也就是说推荐的效果并不是按照“精准”来衡量,要遵循特定问题需要的评价函数比如nDCG,所以以error matrix为标准的一些方法可能效果会不好。比如说用PCA降低特征的维度很可能把那些对推荐效果很重要的长尾特征给舍弃了。
特征的组合变化
这部分工作看起来就比较碉堡,可发挥的空间就看你的想像力和经验了。这里的组合变化远不限于把已有的特征加减乘除(比如Kernel Tricks之类),我举个比较有想像力的例子。
现在市面上社交网络里面“你可能认识的人”的推荐算法几乎都是基于补全网络的办法,这样推荐的人可能只是单纯的补充和完善朋友圈,推荐的人可能很无趣,这样会导致推荐效果不好让用户失去接受推荐的兴趣。目测新浪微博用的还是这种补全的方法,因为整天向我推荐丁一晨李开复姚晨等人或者最近关注的人的共同关注人,所以推荐的人很无趣几乎都不会点关注。
斯坦福小帅哥教授 Jure Leskovec 在2010年的一篇文章“Predicting Positive and Negative Links in Online Social Networks”说到过一种基于用户反馈的推荐“你可能认识的人”的推荐算法,他把邻近三人之间的三角关系总共16种正负反馈的组合当作特征向量用来表达用户A和被推荐目标用户C之间的正负反馈,在图里去掉一些已知正负反馈的边来构建训练数据,用简单的Logistic Regression训练模型达到了不错的效果。可以谷歌找到这篇文章的幻灯片,里面有图示讲解。
结语
这篇文章就简单提及一些特征工程的常用方法,说的是手工提取特征,从这些入手可以深入研究研究具体问题的具体做法,这是一个很细致的工作可以多钻研钻研。这里面没有说到自动提取方法比如深度学习和卷积网络等等,也没说到推荐系统的其他方面比如大规模用户聚类。构建一个推荐系统需要涉及很多东西,绝对不是GraphLab或者Mahout跑个协同过滤就能上马的,这里面特征工程是很重要的一部分工作,在很多其他数据和机器学习的工作里面特征工程也差不多是从根本上改变模型效果的重要办法之一。大家在欢乐调参的过程中不妨考虑考虑搞搞特征。