原文链接:http://click.aliyun.com/m/13855/

推荐引擎是阿里云的一套推荐服务框架。大家可能在淘宝上很早就听过“个性化推荐”、“千人千面”一类的词,对于为什么能把喜欢的宝贝准确得推给不同的买家感到好奇,希望自己也能有这样一套推荐系统吧。这篇帖子,就以推荐引擎产品上的离线算法和在线算法给大家说明下,并且方便后续如果在产品使用中如果发现通用的计算规则不符合自己的场景的时候,需要做一些优化的时候,也能更好地指导怎么调。
如果是最开始的怎么使用产品,可以看产品文档,和视频

系统架构

推荐引擎是怎么工作的,为什么只需要提供一些用户、商品、行为数据,就知道谁谁喜欢什么呢?我们可以一起来看下文档里的一个图,推荐引擎的框架大概是这样:

咱们先不讨论API写入和实时修正一段。数据从MaxCompute准备好,到最后能被调用,实时地生成推荐结果,需要经过2个步骤:要先在离线计算里计算出推荐结果,离线计算的结果会被保存到表格存储里。第二步会通过在线算法,对推荐结果进行加工并展示。所以,如果算的结果不对,比如推荐了个完全不相干的商品,那就查离线算法。比如召回个数要调整,或如果召回数量过少用默认值去填充一类的需求,就要在在线算法上下功夫(当然默认值的生成可能需要用到离线计算)。在线算法和离线算法是配合使用的,所以可以看到模板里也是配套的。

离线计算

我们从默认detail模板(detail_ofl)去了解离线算法。打开这个算法,可以看到这个算法的流程图是这样:

这个图里的每个线表示任务的依赖。这样看起来还不直观,我做了下修改:

可以看到detail_ofl模板的离线计算其实是有2条主线,一条是通过crs_04和crs_02各自生成item_item_rec_list,最后通过st_cb_01整理成一张对外输出的结果。另外一条是crs_05和crs_03生成user_item_rec_list,最后通过st_cb_02整理成一张结果表。item_item_rec_list表里记录了根据item来进行推荐的结果,可以理解成这两个商品比较接近,比如啤酒和尿布的例子就是典型的item_item_rec的例子。而user_item_rec_list是针对用户进行推荐的,比如说系统发现我和你都是跑步爱好者。有一天我买了双不错的鞋子,然后可以猜你可能也会喜欢。

在线计算

我们来看下detail_ofl配套的在线算法,流程图是:

这个图比较简单,先用mg_usr_itm_reclist把离线算法的item-base和user-base推荐结果。item_item_rec_list的数据被放在前面,因为一般来说,根据item召回的结果数量会比较少但是相对比较准确。鉴于两个union all后可能出现走item-base和user-base都会推荐同一个商品,于是接着做了个uniq_reclist进行去重。最后用一个get_top来设置召回个数(也就是最开始我们提到的问题)。

其他算法

看好了detail模板,我们再来对比一下main模板,会发现更加简单了。首页推荐就是根据人进行推荐,没有item的部分,所以其实就是detail模板的st_cb_02,计算user_item_rec_list线。对应的在线算法里,没有两个表的结果的聚合去重,只有get_usr_based_rec来获得user的召回结果,再过一下topn就好了。

然后我们再看下detail_dft,其实就是在detail_ofl基础上,用simple_default_list计算默认的推荐列表。然后用对应的在线模板里的get_default_rec来补足。

最后我们再来看个算法,就是快速入门里的用电影数据进行电影推荐的例子,例子里针对对电影的评分,来筛选出每个人对电影的喜爱程度,这个数据需要用的是spl_grd_svd。而如果用了detail_ofl来算的话,会在数据离线计算的时候报错。对比一下两个模板,可以发现spl_grd_svd开始用的是grade_based_sm,而detail_ofl用的是ig_sm_02。ig_sm_02用的是'click','search_click','consume','use','read','collect','comment','share','like','view',而grade_based_sm只选择bhv_type='grade'对应的bhv_amt作为评分进行计算。如果针对电影数据使用detail_ofl,发现里面只有grade的操作,没有其他的行为,会因为没有找到用户行为数据而报错。

算法类目

可以看到算法的框架是定的,如果后面需要修改,也不是完全推翻重头做起。可以选一个模板在其基础上做修改。每个算法都有各自的数据输入、输出,有一些算法其实只是算法的内部不一样,输入输出,用在什么上下游一样。所以后面如果要根据自己的实际数据写自定义算法,可以先根据前面提到的,找到其中哪个步骤觉得算法还可优化的,然后针对地写个算法替换。是不是看起来很像是在搭积木,用一个同样形状的积木来代替以前的组件。这样一个个相同的积木,就叫做一个类目。在自定义算法的时候,需要设置算法的类目,也正是这个意思。

经过以上的介绍,大家应该对推荐引擎的计算逻辑有一个大致的理解。不过实践出真知,纸上谈兵不如动手做一个,你说呢~

本文使用的产品涉及大数据计算服务(MaxCompute),地址为https://www.aliyun.com/product/odps
和推荐引擎 https://dtboost.shuju.aliyun.com/re#/myre 完成的。