大规模推荐引擎和广告点击率预估引擎中的TopK计算

转自:https://chuansongme.com/n/2035198

推荐引擎的研究结果成千上万,绝大部分工作都来自于矩阵分解或者类似,在针对用户和Item分别训练出特征向量之后,根据向量内积计算返回针对特定用户的Top K Item。类似的场景在广告点击率预估中也同样存在,然而,成千上万的工作里,却极少有适合于大规模推荐引擎的:想一想有上千万甚至上亿的Item等待推荐,针对每个用户都要计算这上千万的内积,不论是离线,还是在线计算,都是一笔昂贵的开销—我们假定内积运算都是浮点数,用户和Item的向量表示都有20维,那么计算用户跟1个Item的相似度就可能需要20次浮点运算,在2G主频的服务器下,这需要耗时40纳秒左右,1千万次计算,就需要0.04秒,1亿次计算,就会有0.4秒了。如果向量表示的维度更高,比如50维乃至100维,那么计算开销会继续成倍增加,考虑到其他因素,比如虚拟机损耗,内存cache miss等等,实际时间比以上结果还要高很多。对于离线计算,如果有1千万用户和1千万item,假定有几十个mapreduce任务,那么就需要数小时,如果有更多的用户和item,这个数字会直线增加。 对于在线计算,推荐引擎,还有广告点击率预估,这些都是高并发场景的典型应用,给单个用户计算就耗时几十毫秒甚至接近1秒,那么支撑数千的并发,将需要多少服务器资源呢?由此可见,这的的确确是一个现实的工程问题,更是个大数据场景中容易忽略的挑战。

这样一个具有典型意义的问题在2012年之前几乎没人提及,这时距离推荐引擎的诞生已经有十年了,距离推荐引擎的研究高潮也过去了五,六年。那么,为什么这个经常遇到的场景却很少有人提及,或者有人去关注呢?想来有这么一些原因:

  1. 早期推荐引擎并没有面临很多的Item项可以推荐,就算是书籍这样的大规模推荐,也不过数百万规模。至于Netflix这种闻名的音像制品,Item只有上万条;

  2. 一些大规模的推荐引擎,比如Youtube,采用的是协同过滤,没有面临这样的大规模内积求解问题;

  3. 还有一些电商类的推荐引擎,事先做好了有效的降维,例如针对类目,品牌等聚合后的结果计算;

  4. 还有的则做了各种牺牲,比如牺牲了新鲜数据引入模型的时效性,完成离线训练后模型几乎不再更新或者很长时间才去更新;或者仅仅针对部分用户做模型更新,等等,不一而足。

上面的解决方案,有的是很有效的,例如降维,不过手段都是ad hoc的。那么,有没有通用的解决之道呢?从2012年之后,这方面的问题逐渐引起关注,14年之后,这个问题引起了更多人的注意,跟大数据的流行应当也有一定关系。下面汇总一下这方面的资料,并不一定完整,但基本思路已经都涵盖了:

  1. Efficient Retrieval of Recommendations in a Matrix Factorization Framework. Koenigstein, Noam and Ram, Parikshit and Shavitt, Yuval, CIKM 2012

  2. Learning Binary Codes for Collaborative Filtering. Zhou, Ke and Zha, Hongyuan, SIGKDD 2012

  3. Maximum Inner-Product Search using Tree Data-structures. Ram, Parikshit and Gray, Alexander G, arXiv preprint arXiv:1202.6101

  4. Asymmetric LSH (ALSH) for Sublinear Time Maximum Inner Product Search (MIPS). Shrivastava, Anshumali and Li, Ping, arXiv preprint arXiv:1405.5869

  5. Asymmetric Minwise Hashing for Indexing Binary Inner Products and Set Containment. Shrivastava, P Li, WWW 2015

  6. Speeding Up the Xbox Recommender System Using a Euclidean Transformation for Inner-Product Spaces. Bachrach, Yoram and Finkelstein, Yehuda and Gilad-Bachrach, Ran and Katzir, Liran and Koenigstein, Noam and Nice, Nir and Paquet, Ulrich, RecSys 2014

  7. Preference Preserving Hashing for Efficient Recommendation. Zhang, Zhiwei and Wang, Qifan and Ruan, Lingyun and Si, Luo, SIGIR 2014

  8. On Symmetric and Asymmetric LSHs for Inner Product Search. Behnam Neyshabur and Nathan Srebro, arXiv preprint arXiv:1410.5518

  9. Clustering is Efficient for Approximate Maximum Inner Product Search. Alex Auvolat, Pascal Vincent, arXiv preprint arXiv:1507.0591

  10. LEMP: Fast Retrieval of Large Entries in a Matrix Product. Teflioudi, Christina and Gemulla, Rainer and Mykytiuk, Olga, ACM SIGMOD 2015

  11. Fast and Accurate Maximum Inner Product Recommendations on Map-Reduce. R Hall,J Attenberg, WWW 2015

  12. Music Recommendations at Spotify. http://www.slideshare.net/erikbern/music-recommendations-mlconf-2014

稍微总结一下以上各种思路和方案:这个问题跟最近邻搜索有一些像,假设度量空间中有很多点,给定一个点,返回跟该点距离最近的所有点就是最近邻查询。常见的距离度量有欧氏距离,Cosine距离等。内积空间的最近邻,跟Cosine距离很类似,如果所有点的坐标全部归一化,那么Cosine距离就是内积。图中显示的是没有归一化的三种距离,可以看到差别是很大的:


跟点q欧氏距离最近的是Pe,Cosine距离最近的是Pc,内积距离最近的是Pi。
 

在Cosine距离最近邻检索上,一种常用的手段是借助于LSH局部敏感哈希,LSH用于把对象投射到整数上,使得整数之间的汉明距离等同于对象之间的相似度,也就是相似的对象有更高的概率被投射到相同的哈希桶。然而,普通的LSH并不能用于内积空间检索,这是因为通常的LSH要求度量空间的距离满足三角形不等式,既两边之和大于第三边,然而对于内积来说,即便坐标归一化之后,可能仍然不满足,例如:假设3个点x,y,z,已经归一化,||x||=||y||=||z||=1,x,y,z之间的夹角分别为(π/4-0.1),π/4,(π/2-0.3),那么d(x,y)+d(y,z)


2012年,首个解决内积空间检索的方案采用“Ball Tree”的方法,在度量空间构造球形树。树的每个节点代表度量空间中的点的集合,节点不断划分,直到叶节点包含的点在阀值之下。


构造Ball Tree时,可选取最远的两个点,然后把所有点按照跟这两个点的距离划分为两部分放入Ball Tree节点,每个节点内还存放圆心和半径(既分别为内部包含点的均值和最大距离),然后分别递归构造直至叶节点内的数量达到阀值。搜索时,通常采用深度优先遍历。Ball Tree的方式跟K-D Tree很类似,后者通常用于高维数据最近邻检索,因此,缺点跟K-D Tree也类似,维度高时复杂度高,甚至逐渐退化为线性扫描。

2014年,LSH研究者专门为内积空间设计了一种特殊的LSH方案,针对没有归一化的内积空间,称为非对称局部敏感哈希ALSH,用来区别传统的LSH—后者实际上是对称型。作者把LSH的计算分为两个阶段:索引和检索,两者使用同样的哈希函数,而ALSH则分别采用不同的哈希。没有归一化的内积计算缺乏一个相似度计算的基本性质:自己跟自己的距离并不是最小的,例如Cosine距离,一定有 <= ,但内积则不一定。ALSH的理论证明见论文。

尽管前文提到归一化的向量内积计算,无法用LSH近似,可是在线音乐推荐公司Spotify却仍然在把所有用户和Item的向量表示归一化之后,采用LSH的一个变种针对Cosine距离近似求解TopK—利用Random Projection来针对Cosine距离做近似近邻查找ANN(Approximate Nearest Neighbour),性能远高于KD-Tree类的方案:基于Random Projection构建树,在每个树的中间节点,选择一个随机超平面,把空间划分成子空间。重复k次之后得到了一系列树。利用Random Projection就可以绕过常规LSH对于三角形不等式的等价变换依赖,这点本人还没想明白。

工艺品电商Etsy的方案是转化内积计算为欧氏距离,首先,Etsy针对ALSH的提出疑问,认为后者是假定用户和Item之间的内积很大得出的近似,然而有些时候即便是TopK,可内积的值依然很小,所以ALSH的近似计算会存在问题。Etsy的方案依然是类似LSH,但主要是以离线MapReduce的方式进行计算,并通过LSH加速。首先,Etsy把用户和Item的向量表示全部归一化,并增加1维,这样可以把内积最大问题转化为求欧氏距离最小。然后把用户和Item分别映射到哈希桶中,那么桶中的用户和Item就是欧氏距离最近的相似对。哈希桶的大小大体按照Item数量的平方根来操作,Etsy并没有很严格地证明自己的方案,但在实际使用中得到了很好的加速和近似。附图是分别针对用户和Item增加1维的方案。

微软在给XBox使用的推荐引擎里提出了另外一种解决方案。但跟Etsy的方法有类似,都是通过给数据增加1个维度把内积空间问题转化为欧氏空间检索问题。毕竟是出自研究院的成果,对理论的正确性更加看重,因此在方案一开始就提到了内积不满足三角形不等式关系,所以许多加速方案都无法实施。XBox增加1个维度的方式见附图,可以跟Etsy做个对比:


在转换为欧氏空间问题之后,微软采用了一种称为PCA(Principal Component Axes)树的方式进行检索。PCA树,顾名思义,就是针对变换后的数据进行SVD分解,但个人对该方案并不认可,既然已经解决了不等式问题,那么像Etsy这样转而采用LSH显然是一种更快速和有效的计算手段。

除此之外还有一些解决手段依赖于纯学术的哈希学习(Hash Learning),思想是通过机器学习把数据映射成二进制串,从而显著减少数据存储和计算的开销。然而,目前相关领域的研究才刚刚开始,距离实用,乃至大数据场景的还有待于进一步深入思考,因此尽管上述文献列出相关工作,但仅仅是以示关注而已。

所以可以看出,尽管在之前,相关问题并没有引起足够的重视,但这几年来自工业和学术界的工作已经取得了显著成绩,在海量用户和Item数基础之上构建大规模推荐引擎(点击率预估引擎)已经是商业验证过的方案。

然而,从理论上证明上述2个商业方案(Spotify和Etsy)的正确性:就是把内积距离转化为Cosine和欧氏距离之后,为什么采用的类LSH算法就不会再收到三角形不等式的约束,这个问题是留待考虑的,有兴趣给本公众号留言。Etsy在自己的论文里提到自己确实也没有很好的证明自己方法的正确性。

猜你喜欢

转载自blog.csdn.net/muyimo/article/details/88698168