江离CIKM用户兴趣高效检索方案简述
来源: | 作者:木贼 | 发布时间: 2019-12-27 | 2115 次浏览 | 分享到:
CIKM2019超大规模推荐之用户兴趣高效检索


演视文稿下载链接




  天池CIKM2019超大规模推荐之用户兴趣高效检索是江离于2019年7月决定派代表队参加的天池四赛之一。这里简单地介绍一下我们在这场比赛中所设计的方案。





一、赛题


  这个题目的业务场景比较常见,就是利用用户历史的交互商品记录,预测这个用户未来一天的最有可能交互的50件商品;但是这里多了一个要求,就是预测的商品不能是用户交互过的,这题目因而变得有趣起来。


图1 数据

  评价指标也是赛题的一部分。这个赛题的评价指标recall@50,就是求出每个用户前50个商品的召回率,然后对这些召回率求均值。我也搞不清楚如果改成precision@50、F1@50或是recall@200会有怎样的影响。大概我的方案不会有什么本质上的变化。

  另外这个赛题还有一个规则。记商品全集的大小为n,要求选手的方案的时间复杂度是O(n)。我认为这实在是一个很多余的规则,因为大部分团队的方案应该都是O(1)的(谁会那么无聊地把商品全集中的每一个商品都预测一遍,大部分团队的方案应该都是和n无关的)。限制时间复杂度不如直接限制运行时间。






二、线下测试

  线下测试应该没有什么疑问。取最后一天的交互数据作为线下测试集,用之前的数据来预测这一天的交互行为。

  数据挖掘的各种问题都应由客观事实来决定。我遇到很多次「事实与我的判断严重不符」的情况了;每次看一个想法或是一个结论,怎么看怎么想都觉得非常有道理,但验证一下却怎么都不对。我们凭借生活经验以及对数据的分析、对业务的理解等得到的结论,虽然难以保证每一个都去实际验证一下,但也要尽可能根据线下测试的结果来判断。

  (可笑的是,偏有人在有明确的客观成绩的情况下选择相信自己的主观臆测。)






三、基本思路

  我们要预测的是用户将要交互,而且没有交互过的商品。我们掌握的用户信息包括性别,年龄,购买力,以及用户交互过的商品。

  那么我们要用哪个信息?看起来,性别、年龄、购买力这些信息都不太靠谱,你不能认为所有男生或是所有20多岁的年轻人都会购买相近的商品,这些是比较弱的特征;而用户交互过的商品才是关键。比如某用户交互过商品甲,我们就可以把这个用户归类为「会交互商品甲的用户」,然后看看「会交互商品甲的用户」一般还会交互什么;比如这类用户一般都会交互商品乙,那么我们就可以把商品乙作为这个用户的预测。

  也就是说,我们要找出经常被用户同时交互的商品(注:这里的同时与时间无关,并非表示同一时间)——如上面的商品甲商品乙;我们称这样的商品为关联商品——用它们构造一个关联商品表;然后对于用户交互过的商品甲,我们要找到和它相关联的商品乙,并将商品乙作为预测。也就是

[公式]

这样的商品乙可能有很多,我们应该选择哪50个呢?我们要根据用户对这件商品甲的交互情况,及商品甲商品乙的关联程度来给这些商品乙打分。因此,我们要解决的问题有两个:1. 设计商品甲商品乙的关联打分;2. 设计用户对商品甲的交互打分。解决这两个问题之后,我们就可以用类似

[公式]

的形式来计算用户未来交互商品乙的可能性打分。

  (话说相关联可能是因为原本就是相关联的,也有可能是因为经常被展视在一起而相关联的。如果后者的情况占了绝大多数,那么这就是一个很古怪的题目了)

  (再进一步地讲,用户交互某个商品,本来就有可能因为看到了被曝光的商品,而被曝光的商品也是利用算法选出的,而不是随机选出的)

  这便是一个基本的思路,即一个简单的基于商品的协同过滤规则。那么基于用户可以吗?当然也可以,只是我还没有来得及尝试。因为根据以往的经验,基于用户的协同过滤规则在这类问题上的效果都比较一般,我通常会优先尝试基于商品。






四、关联打分

  那么我们就来讨论关联打分。

4.1 基础

  一个简单的基线是,我们直接统计两件商品被多少个用户同时交互过。比如商品甲商品乙被10个用户交互过,那么它们之间的关联打分便是10。

  可是仔细想想,如果一个用户交互了1次商品甲和1次商品乙,我们把这两件商品的关联打分算作1;另一个用户交互了5次商品丙和4次商品丁,我们依然算作1,就不太合理;看起来后者对商品丙商品丁的兴趣是可靠的,而前者说不定就是随便点了一下商品甲商品乙。因此此时商品丙商品丁的关联打分应该大于1才对。那么是多少?5×4吗?5+4吗?或是更泛化的[公式] 次?

  然后如果有 [公式] 个用户,每个用户计算出商品甲商品乙的关联打分分别是 [公式] ,又该如何将他们聚合?直接相加?或者泛化一下,用 [公式] 

  我实在难以用理论来确定这里 [公式] [公式]的形式,只能大致判断它们都是增函数。在数值不大时,我们可以用一种增函数来拟合另一种增函数;通常我会尝试一些简单而初等的函数,主要包括幂函数、指数函数、对数函数等,并根据线下测试选择其中最优秀的。对于[公式]的形式,我经过测试选择采用 [公式] (就是前面提到的5×4);对于 [公式] 的形式,我在测试[公式][公式][公式]等几个形式(一般就是这几个最好)之后,发现它们之间差别不大(差别在误差范围内,分辨不出哪个更好),所以选择最简单的形式[公式]。(所以忙活了半天,最终还是采用了最基本的形式;不过有些情况下,选用不同的形式在效果上会有明显的差别)

  于是如果一个用户交互过5次商品甲,4次商品乙,另一个用户交互过3次商品甲,6次商品乙,那么用这两个用户计算出的商品甲商品乙的关联打分便是5×4+3×6。

图4.1 基础关联打分的一个奇怪的形式(其实是等价的)

4.2 一个小问题

  但是这样做实际上有一个小问题。比如一个用户交互了20件不同的商品,那么就要产生190个关联商品对。这样得到的关联商品对实在是太多了,我的机器不肯接受这样巨大的工作量。因此我们需要想一些办法来简化。

  我能想到的办法就是要预先过滤一些。大概有这么两个想法:1) 只统计历史交互次数超过n次的商品;2) 只统计同类目(或同店铺、同品牌)的关联商品对。当然,在得到所有的关联商品对之后,也要再过滤一次,

  于是我将这两个想法结合起来。一方面,我分别统计同类目、同店铺、同品牌的关联商品对;另一方面,我先过滤掉交互次数少于32的商品(这个数值当然越小越好,不过实际上即便取大一些也不会有太大影响)然后再统计关联商品对。

4.3 进阶

  再仔细想想,上面的规则也不够合理。例如一个用户交互了商品甲商品乙,我们把商品甲商品乙的打分算作1;另一个用户交互了商品丙商品丁以及另外二十件商品,我们把商品丙商品丁的打分也算作1,这就有问题了。因为前一个用户对商品甲商品乙感兴趣,这两件商品很有可能是关联的;而后一个用户的兴趣太广泛,他可能对什么都感兴趣,那么商品丙商品丁的关联性就不够可靠,因而它们的关联打分应该是小于商品甲商品乙的。因此我们应该对用户交互的次数做一些惩罚,也就是加一个系数,使得交互次数越多时这个系数越小。

  另一方面,如果一个用户交互了商品甲商品乙,那么它们的关联打分也应该和这两次交互的时间差(或单序差)有关。那么我们又要加一个时间差(或单序差)惩罚,也就是加一个系数,使得交互时间差(或单序差)越大时这个系数越小。

  对于上面两个系数,我们已经大致确定了它们与标签的相关性。那么一个自然的想法便是

[公式]

这里的参数需要经过线下测试确定。显然它们都是正数。这类参数通常不会特别敏感,我们可以从1开始,手动测试一些参数,选择其中最优的。例如这里我测试的过程大概是

参数甲:初始值1→尝试2(变差)→尝试0.5(变好)→尝试0.2(变好)→尝试0.1(变差)→选择0.2
参数乙:初始值1→尝试2(变好)→尝试4(变好)→尝试8(变差)→选择4

一个非常简单粗暴的方式。

  (然而总有人觉得确定这些参数非常麻烦,觉得只有我可以选出比较好的参数而普通人不能。这是把普通人当成弱智了吗?我本来也可以用一些算法来选择最优参数,可是上面描述的手动过程实在是太简单了,我懒得用那些复杂的算法。)


图4.3 我们最终采用的关联打分的形式(还是有点奇怪)

4.4 选取

  前面提到,我会分别计算同类目、同品牌、同店铺和全体的关联商品。此时我们从这四类中各选取一定的比例。当然这个比例越大越好,但是要考虑我的机器和线上机器的资源限制。我最终选取的数量如下:


图4.4 每类关联商品的选取数量

这个数量在变大的过程中对效果的影响越来越小。所以其实随便取取效果都差不多。

4.5 合并

  接下来我们要将这四类关联商品合并,方法是直接加权求和。如下图所示

图4.5 关联商品的合并

这里的权重我线下稍微尝试了一下,感觉不太好调整,便都取了1。

  举个例子来说,商品甲商品乙在同类目关联中计算出的关联打分是0.5,在同品牌中是0.3,而在同店铺和全体中没有出现(按0计算)。那么最终的关联打分是0.5+0.3=0.8。

  (按道理来讲,4.4和4.5的顺序应该调换一下,也就是应该先合并再按比例选取。这里是有些历史原因。简单地说,我在比赛过程中没有注意到这件事,赛后写PPT的时候才反应过来。不过这个对成绩影响不大。)






五、交互打分

  接下来就是交互打分。

5.1 基础

  我们此时已经计算出了关联打分。如果不设定交互打分,或者说设定为1,那么大概就是这样


图5.1 基础交互打分

简单地说,就是沿着

[公式]

的路径找到商品乙,并把商品甲和商品乙的关联打分作为未来交互的可能性打分;如果有多条路径可以抵达商品乙,那么就把这些路径上的关联打分直接相加。

5.2 进阶

  和前面类似,这里也存在着交互次数和时间的问题,我们和前面类似地增加了两个系数,这里便不再细说。

  此外我们还考虑到购买的问题。也就是说,用户在购买了一个类目的商品之后,可能就不会再交互同类目的其它商品。因此我们又增加了一个和这个相关的参数。


图5.2 我们最终采用的交互打分形式






六、预测及补充

  预测也没什么好说的,我们的PPT写的足够清楚


图6-1 预测

以及补充


图6.2 补充

  (话说我真的有尝试过lightgbm。就是先用上面的方法选出打分较高的用户-商品对作为候选,把上面计算出的打分作为特征,然后再加入年龄、性别、购买力等特征及用户和商品、类目、店铺等的统计特征。这样比我的规则确实有一点提升,但是训练模型要太久了,我最终没有采用)






七、总结

  我在这场比赛中所付出的精力确实要略少一些。比赛的最后一天我用了最后一次机会后,连成绩都来不及看便急匆匆赶去参加另一场比赛的答辩,侥幸得到了还算可以的排名。因此我们的成绩应该还有很大的上升空间(当然官方说的0.07听一听就好,一般情况下官方在这种场合都会吹一吹的;我相信这个问题能做到0.07,我不相信他们能做到0.07)(噢,对了,官方只是说7开头,说不定是0.007)。

  其实各种数据挖掘问题,我们要做的都是想办法利用好我们所掌握的信息;无论是自行设计打分函数来处理这些数据,还是从数据中提取成特征交给梯度提升决策树,或是处理成特定的形式交给神经网络,都是如此。机器学习算法不过是一些工具,一些帮助我们利用好这些信息的工具。我们需要的时候,可以将这些工具信手拈来;在不需要的时候,也可以直接手动去处理这些信息。人工规则和机器学习模型本来就是没有本质上的区别的。因为一些强行找的借口而使用一些机器学习算法是毫无道理的。评价一些据挖掘方案不应该依据这个方案使用的算法。

  遗憾的是,目前数据挖掘领域在工业界存在大量的专家,凭借自己的地位来打压异己者。今天XX网络盛行,要求下属使用XX网络的专家就会跳出来称赞使用XX网络的方案而贬低其它方案;明天YY网络盛行,要求下属使用YY网络的专家就会跳出来称赞使用YY网络的方案而贬低其它方案。这实在是十分无奈的事情。