亚马逊AWS官方博客
使用 Amazon Personalize 在 StockX 上拓展个性化用户体验
原文链接:
本文为 StockX公司Sam Bean与Nic Roberts II撰写的客座文章。援引他们的表述,“StockX是一家来自底特律的初创公司,希望以独特的竞价/出价市场革新电子商务体系。我们平台的设计灵感源自纽约证券交易所,并将运动鞋与街头潮牌服饰等商品视为高价值可交易商品。凭借运营透明化的市场交易体验,StockX 将帮助消费者以真实市场价购买备受追捧的真品。”
2019年,StockX 公司正经历高速增长,我们的机器学习(ML)工程师小组也开始尝试使用 Amazon Personalize 在主页上添加“为您推荐”产品推荐行。最终,这项新功能成了主页上最受欢迎的部分。在本文中,我们将分享 StockX 使用 Amazon Personalize 的整个过程,探讨如何借此提供出色的定制化用户体验。
我们的市场动态需要提供个性化的用户体验。StockX 网站的流量激增,在很大程度上源自相关商品市场供应量的下降。没错,在运动鞋与街头潮牌服饰市场上,最受欢迎的一定是那些需要提前预订的限量版产品。虽然客户对于产品多样性的追求一直在增加,但是客户经常搜索的还是那些最新发布的特定热门款式。最终,我们的平台开始经历一波又一波强度几乎接近DDoS的合法流量,让我们意识到再不扩大后端的规模伸缩能力、我们将无法顺利开展自身业务。另外,我们的团队还计划在黑色星期五之前上线“为您推荐”功能。这项功能的基础,自然是强大的推荐引擎——我们希望该引擎同样拥有强大的扩展能力,可以实时调整以适应不断变化的客户意图。
在公司成立的三年当中,我们逐渐将用户体验的个性化视为核心发展目标。我们的客户群体已经从单纯的运动鞋爱好者,逐步发展为越来越多休闲及抱有好奇心的新用户。感恩节购物季则为我们提供绝佳机会,以更具个性化的体验吸引这些新客户,最终提高整体客户忠诚度。尽管即将到来的2019年假期为我们的计划增加了额外的时间限制,但Amazon Personalize切实帮助我们为不断发展的用户群体打造精心设计且引人入胜的体验,最终顺利应对季节性流量激增带来的一系列挑战。
早期阶段
我们的团队最初打算寻求第三方供应商来填补平台中的个性化缺失环节。但是,购买现成解决方案不仅成本高昂,而且对于我们独特的电商业务而言也缺少灵活性。我们需要更大的灵活施展空间,但又不太可能单纯依靠内部解决方案搞定全部难题。
接下来,我们开始考虑构建起与 Amazon Personalize 核心推荐引擎(分层递归神经网络,简称HRNN)类似的自定义神经网络。虽然我们的团队具备一定的自主建模能力,但却难以处理一系列令人头痛的变量:健壮性、可扩展性以及开发周期等等。我们需要争分夺秒地构建优质服务,为我们的客户提供引人入胜的体验并在假期购物季来临前及时将其上线。为了确定到底是该自建模型、还是直接选择现成解决方案,我们列举了构建机器学习微服务架构的基本要求。经过整理,我们的具体要求如下:
- 数据收集——建立高性能推荐程序的第一步,自然是对网站进行正确跟踪。除了通过调查、评级以及偏好设置等方式收集明确的客户喜好指标之外,我们还需要考虑从原始点击流中提取隐式证据,借此建立起更加精彩的使用体验。而收集点击流数据,自然成为创建高性能推荐程序的重要基础。
- 数据位置——在收集到正确的数据类型之后,下一步就是为该数据确定准确的存储位置。为此,我们需要找到点击流与产品目录数据所在的位置,并获取访问权限。
- 数据整理与特征工程——在找到数据源与存储位置之后,接下来需要找到其中真正有价值的部分。这是一项高度依赖于经验的过程,因为在进行实际尝试之前,我们往往很难预判算法如何从数据当中提取信号。
- 模型开发——这一步也是整个开发生命周期当中,数据科学元素最为密集的部分。大多数团队会以notebook中的原型为起点,逐步尝试解决业务问题,而后以面向对象的方式进行模型训练。这一步骤与之前各步骤相互依存,前者中的数据可用性也将直接影响候选模型集的实际组成。
- 模型测试与评估——在完成模型训练之后,必须启用快速健全性检查以执行定性分析,借此补充训练指标。我们建议大家先创建一个小规模可视化应用程序,用于在模型提出的建议内容旁边提示用户正在与哪些产品进行交互。这能让我们更直观地审视不同算法以及超参数设置对建议结果产生的影响,同时结合业务经验对结果做出比较。
- ETL开发——在确定数据中的主要特征之后,我们还应该建立一套自动化ETL体系,用于提取原始数据、执行特征工程,并将数据放置在生产训练程序能够轻松访问的位置。这一步至关重要,因为ETL中的任何细微错误都可能拉低输入数据质量、最终影响输出结果的置信度。更可怕的是,这类错误往往很难在训练结束后、输出可视化之前被检测出来。
- 后端服务开发——将模型推理机制与后端服务打包在一起,可以显著改善监控、稳定性与抽象性水平。对我们来说,这也是一条重要的“护堤”,防止流量的过度涌入。我们在AWS Lambda中选择了无服务器解决方案,将getRecommendations API打包在Amazon Personalize当中。
- 生产部署——CI/CD等自动化流程,用于训练并部署模型的最新版本,保证建议结果始终符合客户的实际需求。一旦这一步骤出现问题,可能导致建议结果过时,最终降低客户参与度。在完成这一部分之后,我们的机器学习微服务架构也就构建完成了。
构建本地解决方案,意味着我们需要从头开始完成以上八个具体步骤。Amazon Personalize提供自动化特征工程与模型开发(步骤3和4)功能,帮助我们快速搞定这两个最为耗时的环节。使用Amazon Personalize提供的标准HRNN(一套由Amazon 本身使用过的、经过重重考验的实践模型),我们的用例只需要一套仅包含五列数据的简单数据集即可开始训练。将这两个步骤交由Amazon Personalize之后,我们得以专注于实现强大的ETL、后端与生产部署系统。此外,我们还省下了更多时间用于实现第5步中提到的可视化流程——这是以往需要开发完整技术栈时,我们根本不敢想象的。当然,直接使用Amazon Personalize也会带来一定妥协,意味着我们将无法对标准算法中的具体杠杆做出针对性调整。
这自然在我们的团队内部引发激烈讨论:我们到底是该承担起高昂的成本,以换取对模型的完全控制;还是以可调整性为代价,完全信任AWS提供的解决方案?最终,我们决定信任AWS在构建企业级机器学习模型方面的专业水平。我们的团队预见到,内部开发的深度学习推理引擎在可扩展性方面一定会带来巨大风险。如果不拿出时间进行负载测试,我们将很难衡量大规模流量涌入时系统的实际弹性,这将把StockX的整体业务置于随时可能崩溃的危险境地。另外,生产型深度学习微服务架构是个相对较新的议题,与此相关的文献资料并不完备,这同样令问题变得更加复杂。
开发
在决定将推荐程序的核心模型开发与生产推理扩展交由AWS负责之后,我们开始使用Amazon Personalize进行开发,并很快感受到将其集成至全扩展机器学习工作流所带来的卓越便捷性。下图所示,为这套解决方案的基本架构。
我们将Amazon Personalize插入两部分代码库当中,这两套代码库分别用于创建数据集以及配置Amazon Personalize基础设施。以此为基础,我们成功实现了由Amazon Personalize驱动的实时推荐引擎的创建、部署与重新训练流程的全面自动化。
创建数据集
Amazon Personalize为用户提供多种选项,能够根据用户特征与推荐引擎的特定应用方式进行选择。部分recipe选项允许您在模型训练过程中考量用户特征(例如HRNN元数据),另一部分recipe则只关注平台上各用户间的交互(与单一特征/HRNN无关)。我们对具体recipe的选择,决定了训练数据集的实际构建方式、以及最终将向Amazon Personalize提供多少训练数据集以建立模型解决方案。
我们首先开发出用于训练及测试所有三种HRNN变体(纯文本、元数据以及冷启动)的基础,并对结果做出比较。在添加元数据集时,我们刚开始并未发现推荐内容获得任何重大改进;而且发现HRNN-冷启动在未进行额外特征工程开发的情况下,并不能生成更为有机的推荐结果。虽然我们怀疑在元数据特征工程方面投入更多精力也许能最终提高性能,但我们仍决定尝试其他更为简单、且同样有望提供高质量建议的解决方案。
要使用Amazon Personalize HRNN recipe,我们需要为其提供单一数据集,并在其中包含任意时段之内的用户交互数据。这套交互数据集将包含并定义影响核心推荐算法的训练特征。对于像StockX这样的电子商务平台,这种交互特征可能表现为产品页面浏览量、搜索结果点击流或者与购买行为相关的操作等指标。
为了构建起交互数据集,我们创建了一条自动化Python ETL工作流以查询我们的点击流数据源与产品目录、处理交互数据以提取所需特征,并最终执行CSV格式化操作以支持Amazon Personalize的摄取要求。由于Amazon Personalize原生支持从Amazon Simple Storage Service (Amazon S3)导入数据集,因此创建这样的自动化管道并不困难,我们可以节约下大量时间和精力来考虑如何选择最佳recipe以及最佳交互时段。
自动创建Amazon Personalize基础设施
接下来,我们开始着手对Amazon Personalize整体基础设施进行自动化创建。大家当然可以在AWS管理控制台上手动建立Amazon Personalize服务,但配合AWS SDK for Java,我们能够在规模更大的推荐服务管道中实现全自动化与可重复性能力。在这里,我们选择Scala作为客户端以创建Amazon Personalize基础设施,具体包含以下内容:
- 数据集组
- 数据集
- 导入任务
- 解决方案
- 解决方案版本
- 实时活动
对于一次性训练来说,在控制台上构建基础设施确实更为简单;但要打造出一套真正的全自动化可复用管道,SDK绝对是不二之选。
部署策略
更重要的是,我们的Scala客户端还承担起对生产部署流程进行仲裁的额外责任,负责保证在推荐模型在重新训练过程中不会造成停机状况。随着用户与平台的持续交互,我们当然有必要对模型进行重新训练,从而及时包含新的交互信息并据此提供最新的推荐。当每天用最新的交互数据重新训练模型时会导致长时间服务中断,因为在此期间活动端点将不可用。我们可以建立两个独立的实时活动端点(以及解决方案版本)来缓解这个问题,但相关成本过高——意味着即使不提供任何实时流量,我们都需要为各端点支付相应的AWS费用。
为了解决这项部署挑战并建立起更具成本效益的微服务架构,我们围绕中间Lambda函数建立起独特的部署策略。该函数负责响应活动端点并向前端客户端提供推荐内容。我们还将一套特殊的数据集组标签(下图最左侧的两个框体)打包至Lambda环境变量当中,用于指示当前处于活动状态并服务于生产流量的活动端点。
每天夜间,Scala客户端都会启动新的训练任务,并首先检查实时数据集组中产生的Lambda环境变量。客户端将加载新的交互数据集,重建休眠的数据集组,而后在端点上执行心跳检查以保证端点创建成功。接下来,客户端会指示Lambda函数更新其活动的相关环境变量并指向新的端点。最后,不再使用的Amazon Personalize基础设施将被撤销。
通过这种方式,我们的微服务架构能够自动高效对Amazon Personalize模型进行重新训练,每天按时更新用户推荐内容,且不会带来昂贵的冗余支出或者任何服务停机问题。另外,使用Lambda函数还允许我们启用自定义指标对系统进行跟踪与故障监控,及时提醒模型训练的问题或活动端点的错误。这种围绕Amazon Personalize精心设计的强大微服务部署策略,在公司发展历史中最为繁忙的购物季期间为StockX推荐引擎带来了近乎完美的可用性。下图所示,为这套解决方案的基本架构。
实时功能
在完成了训练与部署流程的设计之后,我们只剩下最后一个问题需要解决:如何在不同训练运行轮次之间,随用户兴趣的变化更新推荐内容。Amazon Personalize在这方面提供一套简单的解决方案,即事件交互数据集。我们使用Amazon Personalize putEvents API将点击流事件添加到模型当中。此点击流源将把各项事件实时推送至Lambda函数,该函数又将事件编组为Amazon Personalize能够处理的既定格式。事件被添加至数据集后的几秒内,建议内容即可获得快速体现。下图所示,为这一工作流的基本架构。
测试与部署
我们的发布方案现在已经成为StockX公司的内部标准——“向您推荐”主页集合被部署在用于A/B测试的功能标记后面,内部团队能够安全地将该功能推广至1%的用户以执行初始金丝雀测试。最终,我们的测试范围将涵盖60%的用户——其中30%的用户继续获得旧有体验,30%的用户则获得个性化首页体验,另外40%用户不受测试影响。在逐步扩大功能涵盖范围的过程中,我们发现错误率或延迟并没有随之增长。为了保证万全,我们进行了为期两周的测试。
尽管“向您推荐”显示在首页中的第二行位置,但其点击率却超过了显示在最顶端的“最受欢迎”行。按百分比计算,“向您推荐”已经成为我们表现最好的购买通道。而在其支持下,我们整个主页的总体客户参与度提高了50%,这证明个性化、甚至只是单一页面的个性化,也足以提高业务体系的总体使用感受。
时至今日,个性化已经成为企业高管团队的一大核心战略目标。而我们打造的推荐引擎,正是其中一项关键成果。与负责产品发现体验的产品负责人共同制定出战术决策之后,作为独角兽初创企业的我们深刻意识到个性化的重要性,并通过A/B测试实际证明了个性化的强大能力。在获得初步成果之后,困扰我们的已经不再是要不要推广个性化,而是如何保证个性化元素能够渗透至StockX客户体验的每一个角落。机器学习团队一直是StockX内部最具数据驱动能力的工程团队之一,而此次进行的实验也证明我们完全有能力通过可量化的KPI改善客户的实际体验。
总结
在项目实施期间,机器学习团队学到关于构建机器学习微服务架构的许多知识。我们将这些心得体会总结如下:
- 尽早集成——在项目生命周期中尽早发布演示方案非常重要。即使是简单的推荐算法,也会给各相关方留下深刻的印象,并帮助我们顺利争取到内部资源与更高的项目优先级。
- 可视化——可视化工具对于机器学习模型的测试至关重要。单纯将原始产品ID作为健全性检查对象还远远不够,我们需要并行提供推荐产品的图片与隐性关联证据,借此评估推荐程序的实际效果。
- 预防过度复杂——Amazon Personalize提供多种机器学习框架选项,各选项在复杂度方面也有着巨大差异。我们也曾尝试从复杂的recipe起步,并发现很难理解其为何会提出一些奇怪的建议。而从简单的HRNN recipe起步,我们得以快速开发出令人印象深刻的工作示例。
- 估算成本——机器学习成本高昂。请保证对于工程决策的对应预算需求拥有明确的估计。除了云基础设施使用成本之外,开发人员为此投入的时间也是一种重要的成本构成元素。
- 了解扩展特性——要构建自己的深度学习推荐系统,请首先保证对推理任务的扩展特性拥有充分了解。忙活了半天,却发现自己的解决方案跟不上流量峰值期间的业务要求,绝对会令人陷入崩溃。
- 彻底消除手动操作——相较于传统后端服务架构,机器学习微服务架构包含有更多活动部件。因此,请务必自动处理工作流中的所有内容——只要还有任何一部分ETL或者部署流程需要人工干预,即代表着项目失败。机器学习的工程部分已经相当困难了,没人愿意同时再承担一部分运营压力。
“为您推荐”成为我们团队乃至整个StockX公司的一次巨大胜利。我们开始迅速将机器学习技术整合至企业中的各个层面。而我们获得成功的秘密,在于企业决策者同意将Amazon Personalize集成至更多StockX体验当中,并不断扩大我们在机器学习领域投入的精力。可以肯定地讲,个性化如今已经成为StockX内部的头等大事。
我们的团队在这场假期购物季的几周之前着手项目开发,并在购物季到来时及时将其上线。可以自豪地说,在Amazon Personalize的帮助下,我们的微服务架构在整个假期当中都表现出近乎完美的可用性。