基于 Kylin 的推荐系统效果评价系统

标签: tuicool | 发表时间:2017-03-04 08:00 | 作者:
出处:http://itindex.net/admin/pagedetail

OLAP(联机分析处理)是数据仓库的主要应用之一,通过设计维度、度量,我们可以构建星型模型或雪花模型,生成数据多维立方体Cube,基于Cube可以做钻取、切片、旋转等多维分析操作。早在十年前,SQL Server、Oracle 等数据库软件就有OLAP产品,为用户提供关系数据库、多维数据集、可视化报表的整套商业智能方案。 (本科毕业设计就是做OLAP分析,对相关理论和实践有兴趣的可以参阅我的论文,链接:https://share.weiyun.com/d6b7a9b521927d93c004efb9290ce8f1)

随着大数据的发展,Kylin、Druid、Presto 等基于大数据的OLAP开源工具开始涌现,我们可以对亿级的数据进行OLAP分析。Kylin 就是一款基于Hive的开源OLAP工具,我们可以设计Hive表的字段为维度和度量,通过Kylin来构建Cube,Kylin会将Cube结构存储在 HBase 之上,基于Cube我们可以做各种多维分析。在推荐系统开发过程中,我们往往需要按场景、策略、平台等多个不同维度来比较效果数据,推荐系统的线上效果评价是一个很强的多维分析应用场景。因此,我们基于Kylin搭建了推荐系统效果评价系统。

本文主要包含三部分,首先介绍了我们的需求背景,其次介绍了Kylin的基本概念和原理,最后介绍了我们如何利用Kylin来完成推荐系统的效果评价。了解Kylin基础的朋友可以直接阅读第三部分,对Kylin原理较生疏的朋友建议先阅读第二部分,尤其是Cube维度优化相关内容。

1 背景介绍

五八同城智能推荐系统是一个通用的推荐平台,旨在为五八同城不同业务线提供推荐服务。目前,我们接入了不同业务线在APP、PC、M三端上共计约六十个推荐位,包括大类页、列表页、详情页、公共页(如APP首页、消息中心页等)等推荐场景。在一些核心推荐位上,我们会持续迭代召回策略、排序算法以及展示样式,以不断优化推荐效果。比较和分析不同业务线、不同推荐场景、不同推荐算法的效果是我们的基础工作,早期我们是通过 Hive + MySQL的方式来实现效果数据的统计分析,但耗费了大量人力。在数据平台提供了Kylin服务之后,我们基于Kylin重构了我们的推荐系统效果评价系统,大大节约了人力成本,提高了开发效率。

2 Apache Kylin基本原理和架构

Apache Kylin是一个开源的分布式分析引擎,提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,能够支持TB到PB级别的数据量,最初由eBay Inc开发并于2014年10月贡献至开源社区,于2014年11月加入Apache孵化器项目,于2015年11月正式毕业成为Apache 顶级项目。

2.1 名词、概念解释

事实表:事实表是用来记录具体事件的,包含了每个事件的具体要素,以及具体发生的事情。

例如超市A的购物事实表:

时间         客户id    商品id  数量   支付id

2016-10-11 10:52:30  2      3    1    1003

2016-10-11 10:52:30  2      4    2    1003

2016-10-11 12:31:10  2      2    2    1005

2016-10-11 12:31:10  2      4    1    1005

这张事实表记录的其中一条事实为:客户id为2的客户在2016-10-11 10:52:30购买了1个商品id为3的商品。

维表:维表包含对事实表的某些列进行扩充说明的字段。例如超市A的商品维表:

商品id    商品名称    商品单价

2       泡泡糖     1

3       泡面      5

4       电池      2

事实表结合维表,可以得到更为详细的事实。当我们需要知道事实表中记录的某个事实的更加详细信息时,就需要使用对应的维表。

    星型模式:包含一个或多个事实表、一组维表,以及事实表与维表的join方式。例如:

 度量:度量是具体考察的聚合数量值,例如:销售数量、销售金额、人均购买量。计算机一点描述就是在SQL中就是聚合函数。

例如:select cate,count(1),sum(num) from fact_table where date>’20161112’ group by cate;

count(1)、sum(num)是度量

  维度:维度是观察数据的角度。例如:销售日期、销售地点。计算机一点的描述就是在SQL中就是where、group by里的字段

例如:select cate,count(1),sum(num) from fact_table where date>’20161112’ group by cate;

date、cate是维度

预计算结果:预计算结果是对事实表进行预计算的结果,预计算结果以键值对形式存在,键是维度的特定值、值是对应的度量值,一条预计算结果有一个对应的维度集合。例如商品销售的预计算结果:

键值对<商品id=’2’,日期=’20161223’>:<数量=12,金额=21>是一条预计算结果,它对应的维度集合是{商品id, 日期},这条预计算结果表示商品id为2的商品在20161223这一天总共卖出了12个,总价格为21元。

键值对<商品id=’2’,日期=’20161223’,城市=’北京’>:<数量=8,金额=14>也是一条预计算结果。它对应的维度集合是{商品id, 日期, 城市},这条预计算结果表示商品id为2的商品在20161223这一天的北京市总共卖出了8个,总价格为14元。

键值对<>:<数量=100,金额=300>也是一条预计算结果。它对应的维度集合是空集,这条预计算结果表示历史所有卖出的商品数量为100个,总价格为300元。

预计算结果全集:全部预计算结果组成的集合。

cuboid:预计算结果全集中对应的维度集合相同的预计算结果的集合.

例:<商品id, 日期>cuboid是预计算结果全集中对应的维度子集等于{商品id, 日期}的预计算结果的集合。

数学一点的表示:<商品id, 日期>cuboid =

{预计算结果 | 预计算结果对应的维度子集={商品id, 日期},预计算结果∈预计算结果全集}

 cuboid树:若干个不同的cuboid组成的有向树,满足孩子对应的维度集合是父亲对应维度集合的子集

例如下面这两棵cuboid树:

Cube:Cube是一个集合,包含若干个cuboid。

2.2 Apache Kylin核心思想

简单来说,Kylin的核心思想是预计算,用空间换时间,即对多维分析可能用到的度量进行预计算,将计算好的结果保存成Cube,供查询时直接访问。把高复杂度的聚合运算、多表连接等操作转换成对预计算结果的查询,这决定了Kylin能够拥有很好的快速查询和高并发能力。

2.3 Apache Kylin架构

kylin由以下几部分组成:

· REST Server:提供一些restful接口,例如创建cube、构建cube、刷新cube、合并cube等cube的操作,project、table、cube等元数据管理、用户访问权限、系统配置动态修改等。除此之外还可以通过该接口实现SQL的查询,这些接口一方面可以通过第三方程序的调用,另一方也被kylin的web界面使用。

· jdbc/odbc接口:kylin提供了jdbc的驱动,驱动的classname为org.apache.kylin.jdbc.Driver,使用的url的前缀jdbc:kylin:,使用jdbc接口的查询走的流程和使用RESTFul接口查询走的内部流程是相同的。这类接口也使得kylin很好的兼容tebleau甚至mondrian。

· Query引擎:kylin使用一个开源的Calcite框架实现SQL的解析,相当于SQL引擎层。

· Routing:该模块负责将解析SQL生成的执行计划转换成cube缓存的查询,cube是通过预计算缓存在hbase中,这部分查询是可以再秒级甚至毫秒级完成,而还有一些操作使用过查询原始数据(存储在hadoop上通过hive上查询),这部分查询的延迟比较高。

· Metadata:kylin中有大量的元数据信息,包括cube的定义,星型模型的定义、job的信息、job的输出信息、维度的directory信息等等,元数据和cube都存储在hbase中,存储的格式是json字符串,除此之外,还可以选择将元数据存储在本地文件系统。

· Cube构建引擎:这个模块是所有模块的基础,它负责预计算创建cube,创建的过程是通过hive读取原始数据然后通过一些mapreduce计算生成Htable然后load到hbase中。

2.4 Kylin的Cube优化

计算Cube的存储代价以及计算代价都是比较大的, 传统OLAP的维度爆炸的问题Kylin也一样会遇到。 Kylin提供给用户一些优化措施,在一定程度上能降低维度爆炸的问题。

在业务分析中有许多cuboid是我们不会用到的。例如我们的推荐中我们不会分析没有date维度的cuboid,就是说我们不会不指定日期来分析数据;我们在分析cuboid中带recname的时候,就一定有scene,就是说我们在分析数据recname的时候,一定会同时分析scene。

我们可以不存储也不计算这些我们不需要的cuboid。这样就节省了很大的硬盘空间和Cube构建时间。这些都是Cube可以优化的空间。

Kylin的4种维度类型:

1.普通维度(General dimension):普通维度是不做任何优化的维度。有n个普通维度的Cube的cuboid的数量为2^n

2.强制维度(Mandatory Dimensions):强制维度是Cube中所有cuboid中必有的维度。强制维度可以使Cube的cuboid减少一半。

3.层级维度(Hierarchy Dimensions),层级维度是有层次关系的维度,使得cuboid中低层次的维度总是伴随着高层次维度的出现。一个有n个层次的层次维度可以使cuboid的数量从2^n降到n+1。例如 年、月、日 可以作为3个层级的层级维度

4.组合维度(Joint Dimensions),组合维度是将几个维度组合成一个维度,使得这几个维度在cuboid中总是同时出现或总是同时不出现。一个有n个维度的组合维度可以使cuboid数量从2^n降到2。 例如 年、月、日 可以作为有3个维度的组合维度(日期)。

Cube的cuboid数量计算例子:

普通维度数有n个,强制维度有m个,i个维度和j个维度的层级维度各一个,x个维度和y个维度的组合维度各一个的Cube。

普通维度有出现和不出现于cuboid中两种情况,所以n个普通维度有2^n个不同的组合。

强制维度一定会出现在cuboid中,所以它不会使cuboid数目增加。

层级维度,在cuboid中低级的维度总是伴随着高级的维度出现,所以i个维度和j个维度的层级维度各有(i+1)、(j+1)种不同的组合。

组合维度,组合维度中的维度总是同时出现/不出现在cuboid中,所以有y个维度的组合维度和有y个维度的组合维度各有2种不同的组合。

所以此Cube的Cuboid数量 =  (2^n)*(i+1)*(j+1)*2*2。

做Cube优化需要我们对自己的分析业务非常了解。不然可能会将我们需要cuboid去掉,导致查不出结果,或在查询的时候引起不必要的较大的聚合使查询过慢。

例如:

有2个维度date、cate,1个度量count(1) as pv。不做任何优化的Cube X有所有的cuboid共2^2=4个,做了优化的的Cube Y 有 只有{date, cate }这个cuboid。在X上执行select count(1) from fact_table where ‘20161112’ = date

会直接在{date}这个cuboid上得到结果。在Y上执行select count(1) from fact_table where ‘20161112’ = date。因为Y没有{date}这个cuboid,所以会发生聚合计算,将{date,cate}中的date=’20161112’的预查询结果做聚合计算后返回结果

2.5 Kylin的distinct count聚合计算

Kylin中的度量,例如count、max、min、sum大部分我们都能理解是如何计算的,但count(distinct xxx)(UV)是如何计算的呢?

在Kylin有两中方式计算UV:

第一种是 近似Count Distinct。使用HyperLogLog算法实现了近似Count Distinct,提供了错误率从9.75%到1.22%几种精度供选择。算法计算后的Count Distinct指标,理论上,结果最大只有64KB,最低的错误率是1.22%。这种实现方式用在需要快速计算、节省存储空间,并且能接受错误率的Count Distinct指标计算。

第二种是 精准Count Distinct。使用bitmap数据类型来做标记,虽然是bitmap类型,但不是真正的位图,而是被当成了类似C++的bitset的数据结构。当数据类型为int、short int、tiny等32位以内的数值型时,会直接映射到bitmap上,当数据类型为long、string等其他类型时,会将数据值以字符串形式编成字典,在将字典上对应的字符串id映射到bitmap。这种实现方式提供了精确的无错误的Count Distinct结果,但是需要更多的存储资源。 

2.6 Kylin的Cube构建

逐层算法是构建Cube的一种算法,它将cuboid按对应维度子集中纬度的个数分层。逐层计算cuboid,对维度个数较多的cuboid做聚合操作得到维度个数较少的cuboid。

假设我们有date、platform、algo三个维度,count(1) as pv、sum(num) as sumofnum两个度量。不做任何的优化。事实集:

dateplatform    algo      num

20161213      android   13

20161214      ios     22

20161215      android   23

那么cuboid树为:

因为有4层,所以会做4次mapreducer计算。除了第一次mapreducer计算的输入是源数据集外,其他每一次mapreducer计算的输入输出的每一行都是一条预计算结果。

第一次mapreducer将源数据集作为输入,计算并输出第1层的cuboid {{date,platform,algo}},第二次的mapreducer以第一次的mapreducer的输出做为输入,计算得出第二层的第2层的cuboid {{date,platform}, {date,algo}, {platform,algo}}。之后的mapreducer类似第二次的mapreducer。

map阶段(除了第一次mapreducer的map),对于一行输入,根据cuboid树输出对应的若干行,例如:

对于输入:

<date=’20161213’,platform=’android’,algo=’1’>:<pv=1,sumofnum=3>

输出:

<date=’20161213’,platform=’android’>:<pv=1,sumofnum=3>

<date=’20161213’,algo=’1’>:<pv=1,sumofnum=3>

<platform=’android’,algo=’1’>:<pv=1,sumofnum=3>

对于输入:<date=’20161213’,algo=’1’>:<pv=1,sumofnum=3>

输出:<date=’20161213’>:<pv=1,sumofnum=3>

reducer阶段,将相同键的值做聚合操作,并输出预计算结果,例如:

对于输入:

<algo=’2’>:<pv=1,sumofnum=2>

<algo=’2’>:<pv=1,sumofnum=3>

输出:<algo=’2’>:<pv=2,sumofnum=5>

除了逐层算法,还有快速Cube算法。该算法的主要思想是对Mapper所分配的数据块,将它计算成一个完整的小Cube 段(包含所有Cuboid);每个Mapper将计算完的Cube段输出给Reducer做合并,生成大Cube,也就是最终结果,这里不在详细介绍。

2.7 参考资料

http://blog.csdn.net/xiao_jun_0820/article/details/50731117

http://webdataanalysis.net/web-data-warehouse/data-cube-and-olap/

http://webdataanalysis.net/web-data-warehouse/multidimensional-data-model/

http://blog.csdn.net/rogerxi/article/details/3966782

http://www.cnblogs.com/en-heng/p/5239311.html

http://www.cnblogs.com/hark0623/p/5521006.html

http://lxw1234.com/archives/2016/08/712.htm

http://www.infoq.com/cn/articles/apache-kylin-algorithm/

3 如何利用 Kylin 完成推荐系统的效果评价

我们的推荐系统是一个通用的推荐平台,为五八同城不同业务线提供推荐服务。目前,接入了不同业务线在APP、PC、M三端上共计约六十个推荐位,包括大类页、列表页、详情页、公共页(如APP首页、消息中心页等)等推荐场景。在一些核心推荐位上,我们会做AB Test多层实验,持续迭代不同的召回、排序、展示方式,以优化推荐效果,如下图所示:

       日常工作中,我们经常会比较不同业务线、不同客户端、不同推荐位、不同推荐策略的数据效果,例如我们会比较房产和车在相同推荐位上的数据对比,猜你喜欢场景上不同排序算法的数据对比,二手房详情页在Android和IPhone上数据对比。各种数据对比能帮助我们优化推荐策略,甚至发现某些业务线功能逻辑上的隐藏BUG,例如在我们推荐项目攻坚阶段,我们通过分析比较二手房详情页在Android和IPhone两端的推荐效果,发现了IPhone上详情页浏览回退的BUG,最终反馈给业务方并解决了该问题,该BUG的解决使得我们在二手房的推荐点击占比绝对值提高了百分之一。总之,我们的推荐效果数据分析是一个很好的多维分析场景。

早期,我们的推荐效果数据统计是通过 MR + Hive + MySQL 来实现的,首先会从编写MapReduce程序对原始埋点日志进行抽取生成Hive表,然后会编写大量的Hive SQL来统计各类指标数据,并将结果数据写入MySQL数据表,最终做可视化展示和邮件报表。由于我们的比较维度多,比较指标多,Hive SQL语句的编写消耗了我们不少人力。在数据平台部门提供了Kylin服务支持后,我们将我们的效果数据统计工作迁移到了Kylin之上,我们只需要设计好Hive源数据表,并设置好维度和度量,Kylin便能根据维度和度量来自动预计算结果数据,这省去了我们编写Hive SQL的工作,大大提高了效率。接入Kylin之后,我们的效果数据统计流程如下图所示:

Hive源数据表的设计

根据需求,维度和度量设计如下:

(1) 我们会从以下共计15个维度来做数据分析:

日期:比较不同日期的效果趋势。

平台:PC、M、APP(Android、IPhone)。

业务分类一级分类:如房产、车。

业务分类二级分类:如整租房、二手房;二手车、工程车。

推荐场景:如大类页、列表页、详情页、公共页等。

推荐位:如二手车详情页同价位、同品牌推荐位。

排序算法号:不同的机器学习排序算法。

召回策略号:不同的召回方式。

前端展现号:在某个推荐场景下可能会同时ABTest两种页面样式。

推荐规则号:例如在推荐逻辑的最后一步使用不同的去重规则或打散规则。

自定义维度:d1 ~d5,共五个扩展维度,以便于后续扩展。

(2) 我们的指标主要是点击,需要统计的度量有:

点击PV:详情页点击量,称作VPPV

点击UV:详情页点击用户量

曝光PV:推荐位(一般是一个列表)曝光次数

曝光UV:推荐位曝光用户量

曝光帖子数:推荐位上曝光的帖子数量。

基于这5个度量,会衍生出一些指标,例如我们关心的 点击率、人均VPPV等,以及一些中间指标如用户点击百分比、人均曝光帖子数、每次曝光帖子数等,这些中间指标很多人不关注,其实同样重要,往往能帮助我们发现系统的一些问题。相关指标数据实例如下图所示:

根据原始埋点所包含的信息以及我们设计的维度和度量,我们设计了推荐点击信息表和推荐曝光信息表两张Hive宽表,这两张Hive表中除了维度相关字段,还包括很多属性字段。

推荐曝光信息表主要字段如下:

CREATE EXTERNAL TABLE `gul_ext_58app_recommend_show`(

`imei` string,   // 用户id

`numofshowinfoid` int,  // 曝光帖子数量

`seqno` string, // 曝光序列号

`timestamp` string, // 时间戳

.......,   // 各种属性字段

`platform` string,       // 平台

`cate_path1` string,  // 一级分类

`cate_path2` string,  // 二级分类

`recname` string,  // 推荐位

`algo` string,       //算法号

`recall` string,     // 召回号

`viewno` string,  // 展示号

`ruleno` string,   // 规则号

`d1` string,

`d2` string,

`d3` string,

`d4` string,

`d5` string)

PARTITIONED BY (

`date` string,    // 日期

`scene` string) //  推荐场景

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\u0001'

COLLECTION ITEMS TERMINATED BY '\u0002'

MAP KEYS TERMINATED BY '\u0003'

LINES TERMINATED BY '\n'

LOCATION

'/home/xxx/58app_recommend_show_for_hive';

   推荐点击信息表主要字段如下:

CREATE EXTERNAL TABLE `gul_ext_58app_recommend_click`(

`imei` string,     // 用户id

`seqno` string,  // 点击序列号

`timestamp` string, // 时间戳

`position` string,  // 点击位置

`infoid` string,     // 点击帖子id

......,   // 各种属性字段

`platform` string,       // 平台

`cate_path1` string,  // 一级分类

`cate_path2` string,  // 二级分类

`recname` string,  // 推荐位

`algo` string,       //算法号

`recall` string,     // 召回号

`viewno` string,  // 展示号

`ruleno` string,   // 规则号

`d1` string,

`d2` string,

`d3` string,

`d4` string,

`d5` string)

PARTITIONED BY (

`date` string,    // 日期

`scene` string) //  推荐场景

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\u0001'

COLLECTION ITEMS TERMINATED BY '\u0002'

MAP KEYS TERMINATED BY '\u0003'

LINES TERMINATED BY '\n'

LOCATION

'/home/xxx/58app_recommend_click_for_hive';

我们按日期、推荐场景对Hive表做分区。我们的数据一般以天为单位,基本没有查看一周或一月内的汇总数据(如周/月活跃用户数)这种需求,所以按日期分区,kylin也只需构建不同日期的cube segment。由于APP Native埋点历史遗留原因,部分推荐场景的埋点数据格式不统一,不同推荐场景的埋点格式可能不尽相同 (题外话:埋点设计是一项非常重要的工作,产品初期设计通用合理的埋点能为后续工作节省大量的人力成本,后续我们将分享如何设计埋点)。在我们的开发工作中,不同推荐场景是由不同的工程同事负责,工程同事需要负责埋点抽取工作,因此为了方便不同工程同事独立抽取各自场景下的埋点,我们将推荐场景也设计成分区。 (为什么不安排一个人来独立完成抽取工作?这是因为写 ETL 程序是一个又苦又累的事情,而且技术含量不高,没有这样的人力来独立完成该项工作,所以我们将工作分散至多人。)

如何将原始数据抽取至Hive数据表

值得一提的是,五八APP每天所有埋点数据都集中在HDFS上一个目录下,数据非常庞大,而我们不同推荐场景下的埋点抽取都是一个独立的MR作业,若每次都从原始数据抽取,将会消耗大量的集群资源。因此,我们设计了一个中间Hive表,采用两个步骤得到最终的Hive数据表:第一步,基于曝光和点击埋点的通用字段,运行一个MR作业解析原始埋点数据,得到中间表,其实是原始埋点的一个子集;第二步,基于中间表,多个MR抽取作业来解析不同场景的埋点,将结果数据追加至最终Hive数据表。这样,便大大提高了抽取效率。抽取流程如下图所示:

Kylin Cube 设计以及维度优化

基于Hive源数据表,我们创建了曝光和点击两个Cube。

(1) 点击Cube:

事实表:上述设计的推荐点击信息表 gul_ext_58app_recommend_click。

维表:没有维表,直接利利用事实表中的字段做维度。

维度:date(日期)、scene(推荐场景)、platform(平台)、cate_path1(一级分类)、cate_path2(二级分类)、recname(推荐位)、algo(算法号)、recall(触发号)、viewno(展现号)、ruleno(规则号)、d1、d2、d3、d4、d5(扩展维度)。

度量:

    • count(1),即点击PV;

    • count(distinct imei),即点击UV。

Cube维度优化:

    • 强制维度:date      

    • 层级维度:

      • cate_path1→cate_path2  分类层级

      • scene→recname→algo    场景层级

    • 组合维度:(d1,d2,d3,d4,d5)

(2) 曝光Cube:

事实表:上述设计的推荐曝光信息表 gul_ext_58app_recommend_show。

维度:和点击Cube的维度相同。

度量:

    • count(1),即曝光PV;

    • count(distinct imei),即曝光UV。

    • sum(numofinfoid),即曝光帖子数。

Cube维度优化和点击Cube维度优化相同。

维度优化很重要

下面我们来解释一下曝光和点击Cube的几处优化:

第1处优化:我们在查询数据时,总是会带日期维度,所以我们将日期date作为强制维度,这会使得Cube中的所有cuboid对应的维度集合都包含date,即所有的预查询结果都包含date的特定值。

第2处优化:我们的业务分类是有层次关系的,二级分类 cate_path2 是一级分类 cate_path1 的下级,查询时若cate_path2出现,cate_path1也会一并出现,所以我们将 cate_path1→cate_path2 设计为一个二层的层级维度,这会使得Cube中所有的cuboid对应的维度集合在包含cate_path2的时候,必定也包含cate_path1。

第3处优化:在我们的业务中,推荐场景其实也有层次关系,算法号 algo 是推荐位 recname 的下级,推荐位 recname 是 推荐场景 scene的下级,因此,我们将 scene->recname->algo 设计为一个三层的层级维度。

第4处优化:d1、d2、d3、d4、d5是自定义维度,是作为扩展字段,实事表里大部分数据这五个字段是空值,小部分数据这五个字段的其中某几项有值。如果将他们作为普通维度,那么我们大约有 (2^5-1)/(2^5) = 31/32 的预查询结果是无意义的,而将 (d1,d2,d3,d4,d5) 作为组合维度的话,无意义的预查询结果会降至约 (2^1-1)/(2^1) = 1/2,因此将(d1,d2,d3,d4,d5)作为组合维度。这会使得Cube中所有cuboid对应的维度集合同时包含这5个维度或同时不包含这5个维度。在查询那小部分自定义维度有意义的数据时,SQL中出现这五个维度中的某几个,这会引起聚合计算,使得查询变的稍慢,但我们认为这是值得的,这算是在时间和空间中做的一个权衡。

经过这四处优化,我们的维度如下图所示:

最终共包含4个普通维度、1个强制维度、1个层次为2的层级维度、1个层次为3的层级维度、1个维数为5的组合维度。最终cuboid的数量为 (2^4)*1*(2+1)*(3+1)*2 = 384,而不做Cube优化的cuboid数量是 2^15 = 32768,可想而知,维度优化有多重要。

Kylin Cube 数据可视化

为了直观的查看推荐效果数据,我们还需要对效果数据进行可视化,以图和表的形式展示数据。我们调研了一些开源可视化工具,部分不满足我们的需求,部分部署麻烦,最后我们自主开发了数据展示模块。我们自主设计了前端页面和后台查询接口,在后台查询接口中调用了Kylin 的 REST API来获取数据。下图是一个可视化页面实例。

4 总结和展望

本文主要介绍了Kylin的基本概念和原理,以及我们如何利用Kylin来完成推荐系统的效果评价。然而,当前是基于批量历史数据的多维分析,我们的实时数据统计仍旧采用的是传统的计算模式,下一步我们将接入实时多维分析。

后续我们将分享通用推荐平台设计、个性化Push、机器学习通用特征框架、埋点设计、大规模机器学习应用实践方面的文章,敬请期待。

作者简介

唐汉英,五八集团 TEG 智能推荐部 2017届校招实习生,湖南科技大学大四在读,校ACM战队主力成员,曾三次荣获ACM亚洲区域赛铜奖,现从事推荐系统数据和算法开发工作。

詹坤林,五八集团 TEG 智能推荐部负责人、算法架构师,前腾讯高级工程师,从事推荐算法和架构设计工作。

------ 请长按二维码关注我们 -----

相关 [kylin 推荐系统 效果] 推荐:

基于 Kylin 的推荐系统效果评价系统

- - IT瘾-tuicool
OLAP(联机分析处理)是数据仓库的主要应用之一,通过设计维度、度量,我们可以构建星型模型或雪花模型,生成数据多维立方体Cube,基于Cube可以做钻取、切片、旋转等多维分析操作. 早在十年前,SQL Server、Oracle 等数据库软件就有OLAP产品,为用户提供关系数据库、多维数据集、可视化报表的整套商业智能方案.

Apache Kylin 性能优化

- - V2EX - 技术
聚合组 Aggregation Groups. Cube Designer 的 Advanced Setting 中可以配置 Aggregation Groups. 理论上 N 维度 Cube 会构建 2^N 个 Cuboid,随着维度的增多,Cuboid 数量会指数增长,存储空间占用增大,构建时间增长.

一文读懂Apache Kylin - 简书

- -
                              —— 中国古谚语. 随着移动互联网、物联网等技术的发展,近些年人类所积累的数据正在呈爆炸式的增长,大数据时代已经来临. 但是海量数据的收集只是大数据技术的第一步,如何让数据产生价值才是大数据领域的终极目标. Hadoop的出现解决了数据存储问题,但如何对海量数据进行OLAP查询,却一直令人十分头疼.

Min-Hash和推荐系统

- - xlvector - Recommender System
前几年看Google News Recommendation的那篇Paper,对里面提到的MinHash的算法基本没有注意,因为之前的习惯都是只注意论文的模型那块,至于怎么优化模型一般都只是扫一眼. 不过最近看了大量的Google Paper,发现Google在实现一个算法方面确实有很多独到之处. 其实,Min-Hash是LSH(Locality Sensitive Hash)的一种,我之前对LSH的了解仅仅限于知道它能把两个相似的东西Hash成两个汉明距离接近的2进制数.

推荐系统实战

- - 博客园_首页
推荐算法:基于特征的推荐算法. 推荐算法准确度度量公式:. 其中,R(u)表示对用户推荐的N个物品,T(u)表示用户u在测试集上喜欢的物品集合. 集合相似度度量公式(N维向量的距离度量公式):. 其中,N(u)表示用户u有过正反馈的物品集合. 其中,S(u,k)表示和用户u兴趣最接近的K个用户集合;N(i)表示对物品i有过正反馈的用户集合;w(u,v)表示用户u和用户v的兴趣相似度;r(v,i)表示用户v对物品i的兴趣.

推荐系统杂谈

- - 后端技术杂谈 | 飒然Hang
推荐系统是近些年非常火的技术,不管是电商类软件还是新闻类app,都号称有精准的推荐系统能给你推送你最感兴趣的内容. 现象级的资讯类app“今日头条”就得益于此成为了势头非常猛的一款产品. 本文就针对推荐系统讲述一些相关概念和实践经验. 首先需要明确的就是推荐系统的目标,一般来说不外乎以下几个:. 用户满意性:首当其冲的,推荐系统主要就是为了满足用户的需求,因此准确率是评判一个推荐系统好坏的最关键指标.

个性化推荐系统综述

- Tony - 所有文章 - UCD大社区
上个月写过一篇产品推荐的文章,详情请见《我所了解的产品推荐》,内容很泛,多为工作心得. 本周读了几篇相关的论文,收获颇多,分享点干货. 以下内容摘自《个性化推荐系统的研究进展》,该文发表于2009年1月的《自然科学进展》专题评述,作者是刘建国、周涛、汪秉宏. 我略去了具体的算法和许多公式,重点看原理、思路和比较.

推荐系统开源工具 – SVDFeature

- Roger - Resys China
SVDFeature是我们(上海交大Apex实验室)在参加KDDCUP 2011期间开发的. 通过这个工具,我们和港科大(HKUST)的联合小组InnerPeace在KDDCUP 2011中获得Track 1第三名,并创造单模型最好成绩. 在此分享给大家,并希望和大家有更多的交流. (1)基于feature的可扩展性 —— SVDFeature实现了我们的基础模型feature-based matrix factorization.

Reculike : 开源论文推荐系统

- votis - Resys China
今天这篇博文主要总结一下reculike的系统架构. 两周前我们宣布发布了reculike的alpha版. 本着分享的原则,今天在这儿介绍一下我们的各个模块的设计方法. 我们这个项目一开始叫paperlens,这是因为我们想学习业界的前辈movielens,开发一个源代码和数据都开源的系统. 关于数据的开源,我想当用户数达到一定程度后,每个月会dump一次我们所有的数据库(密码等隐私信息除外),放到网络上供大家下载.

推荐系统那些事儿1

- - 冰火岛
知识库:用户知识库,Item知识库,用户评分数据(显性和隐性)等.不同的业务背景不一样,譬如电商,社交网络,视频,app应用等. 协同过滤引擎:根据用户评分数据集,通过collaborative filtering方法,计算用户喜欢的top N item. 数据格式: userid, itemid,score.