写点什么

用 Kiji 构建实时、个性化推荐系统

  • 2014-04-03
  • 本文字数:3739 字

    阅读完需:约 12 分钟

现在网上到处都有推荐。亚马逊等主流电子商务网站根据它们的页面属性以各种形式向用户推荐产品。Mint.com 之类的财务规划网站为用户提供很多建议,比如向用户推荐他们可能想要办理的信用卡,可以提供更好利率的银行。谷歌根据用户搜索历史记录的信息优化搜索结果,找到相关性更高的结果。

这些知名公司使用推荐提供情境化的、有相关性的用户体验,以提高转化率和用户满意度。这些建议原来一般由每天晚上、每周或每月生成新推荐的批处理作业计算提供。

然而对于某些类型的推荐,响应时间有必要比批量处理作业所需的时间更短,比如为消费者提供基于地理位置的推荐。比如电影推荐系统,若用户先前看过动作片,但现在要找一部喜剧片,批量推荐很可能会给出更多动作片,而不是最相关的喜剧片。本文将会介绍如何使用 Kiji 框架,它是一个用来构建大数据应用和实时推荐系统的开源框架。

Kiji,以实体为中心数据和 360 度视角

要构建实时推荐系统,首先需要一个能存储 360 视角客户的系统。此外,我们需要具备迅速获取与指定用户相关数据的能力,以便在用户与网站和移动应用交互时做出推荐。 Kiji 是一个构建实时应用的模块化开源框架,它收集,存储和分析这类数据。

一般情况下,一个 360 度视图所需的数据可以被称为以实体为中心的数据。一个实体可以是任意数量的东西,比如客户、用户、帐户,或者 POS 系统或移动设备之类更抽象的东西。

一个以实体为中心的存储系统要能在一行数据中存储与某个特定实体有关的一切信息。这对传统的关系型数据库来说是个挑战,因为这些信息可能既有状态型数据(如姓名,电子邮件地址等)又有事件流(如点击)。传统的系统需要把这些数据存放在多张表中,处理时再把这些表联接起来,这使得它很难做到实时处理。为了解决这个问题,Kiji 用了Apache HBase,它在四个维度 - 行、列族、列标识和时间戳- 存储数据。借助时间戳维度和HBase 存储多个版本Cell 的能力,Kiji 能够存储有更多状态的缓慢变化的事件流数据。

HBase 是 Apache Hadoop 使用的一个键 - 值存储系统,它构建在 HDFS 之上,为大数据解决方案提供了必需的可扩展性。在 HBase 上开发应用程序面临的巨大挑战是,它要求所有进出系统的数据都是字节数组。为了解决这个问题,Kiji 的最终核心组件是 Apache Avro,被 Kiji 用来存储易于处理的数据类型,如标准字符串和整数,以及由用户定义的更复杂的数据类型。 读写数据时,Kiji 为应用程序做必要的序列化和解序列化处理。

开发用在实时中的模型

Kiji 为开发模型提供了两套 API,Java 和 Scala,两套 API 都支持批量和实时组件。如此划分的目的是将模型执行划分为不同阶段。批量阶段是训练阶段,是一个典型的学习过程,在该过程中,将使用完整的数据集来训练模型。该阶段的输出可能是线性分类器的参数,或者聚类算法的群集位置,或在协同过滤系统中相互关联条目的相似性矩阵。实时阶段被称为评分阶段,取得经过训练的模型,并将它与实体数据相结合产生衍生信息。关键是这些衍生数据被当作一等公民,也就是说它可以存回到实体所在的行中,用于推荐,或作为后续计算的输入。

Java API 被称为 KijiMR, 而 Scala API 构成了 KijiExpress 工具的核心。 KijiExpress 利用 Scalding 库提供 API 来构建复杂的 MapReduce 工作流,同时避免了大量 Java 冗余代码,以及串联 MapReduce 作业所必需的任务调度和协作。

个体与总体

之所以要划分出批量训练和实时评分两个阶段,是因为 Kiji 观察到总体趋势变化缓慢,而个体趋势的变化迅速。

比如一个包含上千万次购买记录的用户总体数据集。多一次购买不太可能对总体趋势的好恶造成重大影响。但对于一个只有 10 次购买记录的特定用户而言,第 11 次购买将对系统判断用户兴趣产生巨大影响。鉴于这种主张,应用程序只需在收集到足以影响总体趋势的数据时再重新训练它的模型。但对于特定用户而言,我们可以通过实时响应用户的行为来改善推荐的相关性。

实时给模型评分

为了做到实时评分,KijiScoring 模块提供了一个惰性计算系统,应用程序可以只为经常与其交互的活跃用户生成最新推荐。通过惰性计算,Kiji 应用程序不必为那些不经常光顾或再没回来过的用户生成推荐。这还有些额外的好处,Kiji 可以在推荐时考虑像移动设备的位置之类的情境信息。

KijiScoring 的主要组件叫 Freshener。Freshener 实际上是另外两个 Kiji 组件的组合:ScoringFunctions 和 FreshnessPolicies。正如前面提到的,一个模型包括训练和评分两个阶段。ScoringFunction 是一段代码,描述了如何把经过训练的模型和单一实体的数据组合起来产生一个分数或建议。FreshnessPolicy 定义数据变得陈旧或过时的时间。比如说,普通的 FreshnessPolicy 会指出超过一个小时后数据就过期了。更复杂的策略可能会在实体经历过一定次数的事件后将其标记为过期,比如点击或产品访问等事件。最后,ScoringFunction 和 FreshnessPolicy 被附着在 Kiji 表中特定的列上,在必要时被触发来刷新数据。

进行实时评分的应用程序中包含一个服务器层,被称为 KijiScoring 服务器,它是负责刷新陈旧数据的执行层。当用户与应用程序交互时,请求将被传递到 KijiScoring 服务器层,它直接与 HBase 集群通信。KijiScoring 服务器将会请求数据,并且在获取到数据后根据 FreshnessPolicy 检查数据是否是最新的。如果是最新的数据,它将其直接返回给客户端。如果是过时的数据, KijiScoring 服务器将为发出请求的用户运行指定的 ScoringFunction。你需要掌握的要点是它只为发出请求的用户刷新数据或推荐;而不是执行批处理操作,刷新所有用户的数据。这样 Kiji 就可以只是做那些有必要做的工作。数据刷新完成后会被返回给用户,同时写回 HBase 以备后用。

一个典型的 Kiji 应用程序将包括一定数量的 KijiScoring 服务器,它们是可以向外扩展的无状态 Java 进程,并能够运行使用单一实体的数据作为输入的 ScoringFunction。Kiji 应用程序通过 KijiScoring 服务器过滤客户端请求,由它决定数据是否是最新的。若有必要,它会在把所有推荐传回客户端之前运行 ScoringFunction 进行刷新,并将重算后的数据写到 HBase 中,以备后用。

将模型部署到生产系统中

能够轻松迭代其底层的预测模型是实时推荐系统的一个重要目标,避免因为要将新的或改进过的模型部署到生产环境而停掉应用程序。Kiji 为此提供了 Kiji 模型库,它结合了描述模型以及用来训练模型和给模型评分的代码如何执行的元数据。KijiScoring 服务器需要知道什么样的列访问会触发刷新,要用的 FreshnessPolicy,以及将在用户数据上执行的 ScoringFunction,以及所有经过训练的模型的位置,或给模型评分所必需的外部数据。元数据也存在一个 Kiji 系统表中,只是另一种最底层的 HBase 表。此外,模型库在受管的 Maven 库中为已注册的模型存储代码工件。KijiScoring 服务器为新登记或未登记模型定期轮询模型库,按需加载或卸载代码。

整合到一起

使用协同过滤是一种非常常用的推荐提供方式。协同过滤算法通常会建立一个大型的相似矩阵,用来存放一个产品跟产品目录中其它产品的关联信息。矩阵中的每一行代表一个产品 Pi,每一列代表另一种产品 Pj。(Pi,Pj)中的值就是两个产品之间的相似度。

在 Kiji 中,相似矩阵是通过批量训练过程计算出来的,然后被存储在文件或 Kiji 表中。相似矩阵中的每一行都会被存放在 Kiji 产品表中某一行的单独列中。在实践中,这一列可能会变得非常大,因为其中放的是目录中所有产品的清单和相似性。通常情况下,批处理作业也会挑出相似度最高的条目存到表中。

相似矩阵在评分时是通过 KeyValueStore API 访问的,这个 API 可以访问外部数据。对于无法完全放在内存中的大型矩阵,可以把它们放在分布式的表中,这样应用程序可以只请求计算必需的数据,从而大幅降低对内存的需求。.

既然我们在评分阶段之前已经做了很多繁重的​​工作,那么评分自然成了一种相当简单的操作。如果我们想基于被查看的条目展示推荐信息,一个通用的评分函数只是从产品表中查找相关产品,并显示它们。

将该过程再推进一点并对结果做个性化处理是一个相对简单的任务。在个性化系统中,评分函数将会取得用户最近对产品的评级,并使用 KeyValueStore API 查找与用户评价过的产品相似的产品。结合评级和存储在产品表中的产品相似度,应用程序可以预测用户给相关条目下的评级,并将预测评级最高的产品推荐给用户。通过限制所用评级和所有已评级的相似产品的数量,系统在用户与应用程序进行交互时可以很轻松地处理上述操作。

结论

在本文中,我们可以了解到如何用 Kiji 开发一个可以实时刷新推荐的推荐系统。利用 HBase 进行低延迟处理,用 Avro 存储复杂的数据类型,使用 MapReduce 和 Scalding 处理数据,应用程序能够在实时情境中给用户提供相关推荐。如果你想看看这个系统的样例代码,请访问 WibiData Github

关于作者

Natkins**(@ nattyice)是WibiData的现场工程师,他专注于帮助用户在KijiWibiEnterprise之上构建大数据应用。在为WibiData工作之前,乔恩曾是ClouderaVertica系统的软件工程师。**


感谢吴海星对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2014-04-03 22:4619165

评论

发布
暂无评论
发现更多内容

图解计算机结构与体系分类!!

冰河

编程 程序员 高并发 计算机结构 操作系统原理

传统线程同步通信技术

武哥聊编程

Java 多线程 28天写作

第五周作业

oooh-la

就算知道了答案,真的会改变吗?「幻想短篇 25/28」

道伟

28天写作

第十周 模块分解作业

简简单单

第十周 学习总结

简简单单

高性能缓存 Caffeine 原理及实战

vivo互联网技术

Java Caffeine 本地缓存

极客大学·产品经理训练营·第二章作业(二)

二大爷

极客大学 产品训练营

产品经理训练营作业 02

KingSwim

不要在nodejs中阻塞event loop

程序那些事

node.js Event 事件循环 程序那些事 nodejs event

话题讨论|过年回家你带电脑吗?

熊斌

话题讨论 28天写作

【WOW.js】Animate.css的黄金搭档

德育处主任

CSS 动画 js 28天写作 2月春节不断更

史上最清晰的Tarjan算法详解

华为云开发者联盟

算法 静态分析 语法树 Tarjan 数据流

开发质量提升系列:标准模板(中)

罗小龙

最佳实践 方法论 28天写作

持续交付

lidaobing

持续交付 28天写作

大背景 (28天写作 Day25/28)

mtfelix

28天写作 新能源汽车 新能源革命 碳中和

云原生动态周报 | Google推出VM Manager

华为云原生团队

Docker 开源 云原生 华为云

产品训练营第二章作业(二)

Arnold

第三章:产品解决方案作业

让时间说真话

产品经理

持续进步的不二法宝-PDCA

Ian哥

28天写作

Python 中 sorted 如何自定义比较逻辑

zikcheng

Python sorted cmp

时间约束帮助我写作

Justin

方法论 创意 习惯养成 28天写作

python爬虫入门-通过茅台脚本讲些爬虫知识,应用和价值

大佬sam

Python python 爬虫 2月春节不断更

安卓开发软件有哪些?分析Android未来几年的发展前景,吐血整理

欢喜学安卓

android 程序员 面试 移动开发

第三章:产品解决方案作业

让时间说真话

产品经理

创业失败启示录|样茶里的商机

阿萌

28天写作 创业失败启示录 青城 2月春节不断更

机器学习·笔记之:Matrices and Vectors

Nydia

安卓开发交流!一线互联网移动架构师筑基必备技能之Java篇,Android岗

欢喜学安卓

android 程序员 面试 移动开发

第三章: 产品解决方案作业

让时间说真话

产品经理 产品经理训练营

ModelArts AI Gallery与HiLens Kit联合开发丨行人社交距离风险提示Demo

华为云开发者联盟

华为云 modelarts hilens 行人 社交距离

【并发编程的艺术】详解单例模式的实现方式(Java)

程序员架构进阶

设计模式 Java内存模型 七日更 28天写作 2月春节不断更

用Kiji构建实时、个性化推荐系统_大数据_Jon Natkins_InfoQ精选文章