推荐系统中常用的权重计算方法
说起推荐方面的技术,大家首先提到的往往是回归、Learning to rank这些数据挖掘或者说机器学习方面的名词,连协同过滤都少提了,可能是因为它太基础。然而基础的才是最重要的,实际上给推荐效果带来巨大差异的,往往不是模型的复杂度,而是对数据的处理是否足够完善。
首先,被推荐的内容我们称为Item,用大写字母I来表示,比如在线视频中的电影、阅读App里的图书、电商网站里的商品等等,都叫Item;第二呢,我们用U来表示用户(User);第三,我们用T,也就是Tag(标签),来描述I的属性和U的喜好。
本应先说数据收集的工作,但由于在实践中预处理环节往往会被忽视,这里先说一下预处理要做的事情。第一是处理多义问题。比如“苹果”这一个标签,它可以是一种水果,也可以是手机的品牌。可以通过给标签添加领域词作为前缀的办法来解决多义的问题。第二是同义问题,比如“C罗”和“克里斯蒂亚诺·罗纳尔多”就是指同一个人。对于同义词,可以将它们映射到同一个ID上面,或者映射到一个最常用词上面。第三要说的是过滤,在真实的数据里面,脏数据的占比往往会超乎想象,错误的或者无效的标签会有很多。
可以使用词表(也就是黑名单)、DF(Document Frequency)的方式实现标签的过滤工作。DF的方法很简单,就是统计一下每一个标签在多少个内容里面出现过,这个值就是DF值,把DF值过大或者过小的标签过滤掉。最大和最小值要根据内容总数量和具体的应用场景来确定。
以上所说主要是数据的清理、规整化工作。实际上数据的集成、变换、归约等操作也是预处理阶段要做的事情,这些工作我们在下文中需要它们的地方再做介绍。
下面说一下数据收集的工作。
首先是内容本身的属性数据,包括内容的生产时间、长度、质量度(比如视频的清晰度、流畅度、画面精美度等等);第二是内容的meta信息,这里简化一下,认为它们是标签(T)的集合;第三是用户的描述信息,比如年龄、性别、生活地域、教育程度、家庭组成等等;第四是用户在内容上的行为数据,包括消费行为数据(购买商品、阅读图书、观看视频等等)、寻找行为数据(搜索、分类浏览、推荐结果的曝光和点击等)、以及主动的兴趣表达行为(收藏内容、分享内容、评分、评论、顶/踩等等);第五,还有一些其它数据,比如标签的流行度等等,可以从搜索引擎等站外数据源获取到。
我们这里做一下简化,在数据收集阶段,目标是获得以下几组数据。
1、<U, I, Score>,也就是用户U对内容I的喜好程度(Score)。Score的取值根据用户U对内容I的行为而定,这个跟业务有密切的关系,这里不作细述。
2、<I, Score>,就是每一条Item本身的得分,一般用来体现Item的流行度、新鲜度、本身质量等指标的综合得分。
3、<I, T, Weight>,就是对于一条内容I,它每一个标签T的重要程度。
4、<U, T, Preference>,表示用户U对标签T的喜好程度。
本文的一下部分分别介绍上面的score、weight、preference都如何计算。本文建议这些Score、weight、或者preference的取值都归一化到(0, 1)区间内,这样能为各种计算提供方便。
其中MAX的取值一般是所有|(x-Me)|里面最大的那个(绝对值)。不过真正操作的时候,要注意x里面是不是存在个别特别大的值,根据个别特别大的x计算得来MAX是不合适的,一般会把它们去掉之后再算MAX。去掉奇异值之后,会导致最终的x’的取值有个别不在(-N, N)之内的情况,不过它们带来的影响很小,可以忽略掉。
<U, I, Score>里面的Score是对“用户U对内容I的喜好程度”的一个客观描述,可以通过直接的计算来获取。举个例子,假如U是一个视频用户,I是一部电影,那么Score可以是用户U对电影I的观看时长t的sigmoid值。
说到这里,要引入一个“空间”的概念。假如我们要用sigmoid(t)来计算用户对视频的喜好Score,那么把电影和电视剧放一起就不是一个明智的做法。因为一部电影的时长一般在90~120分钟之间,而一部20集的电视剧,假设一集就30分钟,那么也有600分钟的总时长。这时候我们要分“空间”分别计算Score的取值,将同类内容放到同一个空间里,不同内容放在不同的空间里。
假如新来一位用户,对其我们一无所知,那么该给她推荐哪些内容?当然最热门的内容是不错的选择,同时我们不能忽略了新内容,尤其对于新闻这样的时效性非常强的应用领域来说。我们这里介绍<I, Score>里面Score的计算,它是内容Item本身流行度/质量分和时效性得分的综合。我们这里用P_Score表示流行度得分(可以认为流行度也包含了对内容质量的评价),用F_Score表示时效性得分(Freshness Score)。
对流行度得分P_Score的计算比较容易,在应用领域里面收集最能代表用户对内容喜好的指标值,再使用上面介绍过的sigmoid函数对该指标值进行处理即可。比如在视频领域,用户对视频的观看次数(Video View)就很有代表性。在新闻应用里面,可以使用阅读新闻的用户数。这
里还有两个要点需要说明,其一是,在每个应用领域里面都有多个指标能够代表用户对内容的喜好程度,比如视频领域里除了观看次数,还可以用观看时长、观看人数、用户评分、评论次数/人数等等,我们选择最有代表性的一个即可。如果有兴趣,可以研究一下把它们综合使用(可以引入一些数据挖掘的手段),看是否比单一使用有更好的效果。要说明的第二点是,在收集用户喜好的时候一定要注意数据的清洗。比如计算视频的观看次数的时候,会把观看时长小于一定值的观看给过滤掉,因为这说明用户并不是真的要去观看该视频。
对F_Score的计算需要引入一些技巧。在介绍F_Score的计算方法之前,我们先看看为什么要计算F_Score,以及应该如何用它。
首先,F_Score应该能够一定程度上解决“新内容”的问题,也就是冷启动问题的一种。新内容的问题就是我们对它们的流行度一无所知,也就是它们的P_Score还都是0。那么这时候F_Score就要为其作出补偿。其次,而当积累一定用户流量之后,对于优质内容来说,它们的P_Score就会快速提升,这时候F_Score的值应该相应地下降。
对于那些P_Score没有及时提升的内容来说,它们的整体得分就应该下降,从而在推荐排序中不断下降,减少被曝光的机会。P_Score的取值是sigmoid的结果,分布在(0, 1)区间里,对于新内容来说其值是0,这时候其F_Score的值应该是最大的,接近1。随着时间的推移,F_Score的值应该下降,其下降速度应该与多数内容的P_Score值的上升速度相当。
底数a的选择比较关键。这我们定义一个半衰期T,来表示经过多长时间内容的时效性得分就减半,取a为T的倒数即可,即:a=1/T
其中T>1。可以结合主流内容的流行度得分随着时间的上升速度来确定T,使得P_Score和F_Score结合之后的得分对于主流内容来说比较平稳的T就是好的选择。
最后再解释一下使用加法来结合P_Score和F_Score的思路,那就是把二者看做是互补的两个值,在P_Score很小的时候F_Score取值较大,反之F_Score衰减到较小值的时候,优质内容的P_Score值已经得到了相应的提升。当然劣质内容在我们不知道真相时也会得到曝光机会,但是会随着用户的反馈而迅速衰减。
关于内容上面标签的得分,也就是<I, T, Weight>里面的Weight,分两种情况简单介绍。其一是对于文本内容来说,T的含义不是Tag,而是信息检索领域里的Term,有一种成熟的计算方式,就是tf-idf,请参考tf-idf的百科解释。其二就是像音乐、视频、商品等领域的标签信息,这些标签都是人工添加的,认为其权重都是1是最常见的做法。