Uplifting conversion across the acquisition funnel with personalization using contextual bandits on AWS

TL;DR · AI 摘要
Uplifting conversion across the acquisition funnel with personalization using contextual bandits on AWS Artificial Intel...
核心要点
- 主题聚焦:Uplifting conversion across the acquisition funn
- 来源:AWS Machine Learning Blog,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
在 AWS 上使用上下文多臂老虎机实现个性化,提升获客漏斗转化率 | 人工智能
在 AWS 上使用上下文多臂老虎机实现个性化,提升获客漏斗转化率
生成式 AI 使我们能够以低成本快速生成大量个性化内容。在我们之前的博客中,我们展示了 Amazon Bedrock 上的生成式 AI 如何在遵循品牌规范和安全限制的前提下实现个性化内容的大规模生成。现在面临的新挑战是选择问题。在众多选项中,应该向每位客户展示哪一个?需要多长时间才能学习到答案?本文将探讨在生成式 AI 爆发式增长后随之而来的选择挑战。
在本文中,我们将分享 Amazon Payments 如何使用 Amazon SageMaker AI 上的多目标上下文多臂老虎机(MAB)将基于 AI 的个性化应用到产品获客漏斗中。在目前进行的为期七周的在线 A/B 测试中,我们观察到某个客户群体的最终漏斗转化率实现了高个位数百分比的提升,而另一个客户群体则与现有体验相比没有改进。问题最终被发现是内容本身,而非模型。我们将解释多臂老虎机的原理,介绍我们如何扩展方法以优化整个转化漏斗,以及解决方案背后的 AWS 架构。我们还提供了一个代码仓库,您可以用它在合成数据上测试这种方法,并通过 Amazon SageMaker AI 亲身体验该方法。
生成式 AI 时代多臂老虎机的日益重要性
多臂老虎机(MAB)是一种强化学习方法,专为具有众多选项和有限流量的场景设计。它在持续服务客户的同时学习哪种选项表现最佳。它将每种内容变体视为一个“臂”,在实时流量中尝试每个臂,并逐步将展示偏向表现较好的臂,同时保留一部分流量继续测试其他选项。这是利用(服务当前最佳臂)与探索(尝试不确定性较高的臂以收集证据)之间的基本权衡。由于老虎机会持续进行这两项操作,因此随着新变体的添加,它会不断改进,且无需等待测试结束。A/B/n 测试仍然有其用武之地,但随着生成式 AI 加速增加可学习的变体数量,我们预计老虎机将在未来发挥越来越重要的作用。
文献中存在多种老虎机选择策略,包括 ε-贪心、上置信界(UCB)、汤普森采样等。如需深入了解这些方法及其在 AWS 上的部署,请参阅我们之前的博客《使用 Amazon SageMaker MLOps Projects 进行机器学习模型的动态 A/B 测试》。
在 Amazon Payments,我们选择了 UCB 策略,该策略选择具有最高估计奖励加上不确定性奖励的臂,自然平衡了利用与探索。其确定性的选择规则为每次展示提供了可审计、可复现的决策,确保所有服务决策在需要时都能被解释和复现。然而,标准老虎机为整个受众学习一个最佳臂。个性化需要根据访客身份进行条件判断,这就是上下文老虎机提供的功能。
使用上下文老虎机添加上下文信息
而不是询问“哪种内容总体上最好?”,上下文老虎机会根据访问的相关信号来做出决策。分段老虎机为每个预定义的组运行独立的实例,但这些组是任意划分的,每个组都需要独立的流量。上下文老虎机直接基于特征向量(属性的数值表示)进行决策,因此在一个上下文中学习到的模式可以自然地应用到所有相似的访问中,无需为每个组分配独立流量。我们的生产系统用行为信号(支付行为、交易组合等)的上下文向量表示每个客户,取代固定的分组。实体ID(如entity_id这样的不透明键)仅用于将学习到的推荐结果路由回正确的访客,它永远不会作为模型的输入。
LinUCB:在特征层面进行学习
对于上下文方法,我们选择了线性UCB(LinUCB),这是Li等人(2010)提出的一种算法。尽管存在更新的老虎机算法,LinUCB仍然是经过实战验证的方法,计算效率高,可审计(确定性臂选择),并且能自然处理大规模臂空间和有限的初始数据。其核心假设是:某个臂的期望奖励是上下文向量的线性函数,这使它能够泛化到未见过的访客。
每个臂在每次展示时都会更新两个运行中的统计量:
- b,奖励账本:记录哪些访客信号导致了转化(b += 奖励 · x)。
- A,经验账本:记录该臂见过的访客(A += x·xᵀ,从单位矩阵开始)。
用经验除以奖励可得到估计值(θ = A⁻¹·b)。随着证据积累,经验账本还会缩小探索奖励。臂的评分公式为:
score(a, x) = θᵀ·x + α · √(xᵀ · A⁻¹ · x)
\_____/ \________________/
估计值 不确定性奖励奖励与上下文相关。对于该臂很少见过的访客类型,奖励会很大;对于常见访客类型,奖励会很小。普通老虎机以单一全局速率探索,而LinUCB会根据每个访客调整探索程度。
优化整个漏斗
在我们的用例中,客户旅程包含三个步骤:应用启动、提交和批准。因此目标是多阶段结果而非单一指标。这些阶段不会同步推进。针对启动优化的内容通常能吸引广泛受众,但批准取决于优惠是否真正适合申请人。单独优化某一阶段可能会损害其他阶段。我们将这种现象称为跷跷板问题。相反,如果仅优化批准率,模型会因批准事件稀少且延迟而缺乏信号。
我们通过为每个阶段(启动、提交、批准)运行一个LinUCB模型,并通过线性组合合并它们的UCB评分,从而同时优化整个漏斗:
selected_arm = argmax_a [ w_start · UCB_start(a, x)
+ w_submit · UCB_submit(a, x)
+ w_approve · UCB_approve(a, x) ]阶段权重可根据业务优先级分配,或通过独立的校准步骤学习。我们使用了大致相等的权重。实际上,一旦模型预热完成,可以增加批准权重,或在存在激烈权衡时使用帕累托前沿。
以下是Python中的核心模型代码。每个LinUCBDisjoint为每个臂维护独立参数,而MultiObjectiveLinUCB组合了三个这样的实例:
import numpy as np
class LinUCBDisjoint:
"""使用独立参数的LinUCB算法。
每个臂维护自己的奖励矩阵和经验矩阵。"""
def __init__(self, n_arms, n_features, alpha=1.0):
self.n_arms = n_arms
self.n_features = n_features
self.alpha = alpha # 探索与利用的权衡参数
# A: 经验矩阵 (d x d); b: 奖励向量 (d) - 每个臂一个
self.A = [np.eye(n_features) for _ in range(n_arms)]
self.b = [np.zeros(n_features) for _ in range(n_arms)]
def update(self, arm, context, reward):
"""精确增量更新 - 无需重新训练。"""
self.A[arm] += np.outer(context, context)
self.b[arm] += reward * context
class MultiObjectiveLinUCB:
"""通过加权求和将每个漏斗阶段的LinUCB组合在一起。"""
def __init__(self, n_arms, n_features, alpha=1.0,
weights=(1/3, 1/3, 1/3)): # 阶段权重 (开始, 提交, 批准)
self.n_arms = n_arms
self.alpha = alpha
self.weights = weights # [开始, 提交, 批准]
self.app_start_bandit = LinUCBDisjoint(n_arms, n_features, alpha)
self.app_submit_bandit = LinUCBDisjoint(n_arms, n_features, alpha)
self.app_approved_bandit = LinUCBDisjoint(n_arms, n_features, alpha)
def select_arm(self, context):
combined = []
for a in range(self.n_arms):
score = 0.0
for w, bandit in zip(
self.weights,
[self.app_start_bandit,
self.app_submit_bandit,
self.app_approved_bandit],
):
A_inv = np.linalg.inv(bandit.A[a])
theta = A_inv @ bandit.b[a]
ucb = theta @ context + self.alpha * np.sqrt(
context @ A_inv @ context)
score += w * ucb
combined.append(score)
return int(np.argmax(combined))
def update(self, arm, context, r_start, r_submit, r_approve):
self.app_start_bandit.update(arm, context, r_start)
self.app_submit_bandit.update(arm, context, r_submit)
self.app_approved_bandit.update(arm, context, r_approve)我们为Amazon SageMaker AI构建了一个快速入门的Jupyter Notebook来测试这种方法。该仓库还包含命令行演示和单元测试。
调整alpha参数。α参数控制探索与利用的平衡。较大的值会鼓励探索测试不足的臂,较小的值则更倾向于利用。α=1.0是一个合理的默认值(Li等,2010)。在实践中,当臂空间较大且历史数据有限时,建议从较高值开始,随着证据积累逐步降低α。典型范围是0.1到2.0。过高的值会导致流量浪费在表现差的臂上,过低的值则可能锁定次优臂。由于α是单一标量,网格搜索非常直接。
处理延迟反馈。在我们的场景中,批准决策会延迟数天,因此最终漏斗阶段的奖励要在展示很久之后才能观测到。我们通过归因窗口来解决这个问题。开始和提交操作会立即更新模型,而批准结果会延迟到下一个批次周期更新,从而避免未决申请带来的向下偏差。这与我们每周的处理节奏自然契合。
大规模发布安全内容
多臂老虎机的效果取决于手臂池的质量。在保持内容监督的前提下,规模化构建丰富手臂池是下一个需要解决的问题。
关键思路是通过少量经过审核的基础模块组合出多种变体。我们的内容由两类部分组成:行业主题的图片和以利益为导向的标语。手臂空间是这些部分的笛卡尔积,因此每个手臂对应一组(图片,标语)配对。少量的基础模块就能生成大量独特的页面变体。
图1:基础模块经过单独审核后,再组合成完整的手臂池
这种结构通过多层控制机制,使方法在保持监督的同时具备可扩展性。
审核组成部分而非组合方式。一些内容元素由利益相关者需求固定。我们不会审核所有可能的组合(随着空间扩展这将变得不切实际),而是提前审核每个单独的基础模块。由于基础模块数量保持较小且可审核,而组合方式却迅速增长,一次性审核组成部分即可覆盖整个组合空间。
设计系统确保一致性。如我们之前的博文所述,将内容锚定到设计系统(批准的颜色、布局、组件和模式)能通过构造而非偶然保持视觉一致性。
通过生成式AI扩展池。在初始部署中,即使生产过程由生成式AI工具辅助,基础模块仍由人工详细审核。我们清楚看到显著提升组成部分池(文本、图像、布局)的潜力,这将扩大老虎机的选择空间。随着池的扩展,老虎机和生成式流水线形成良性循环:生成式AI扩展候选集,而老虎机能识别出对每位访客效果最强的组合。
在AWS上部署
Amazon SageMaker AI 是一项支持完整模型生命周期的人工智能模型开发服务。它是我们的端到端流水线背后的主要AWS服务,提供统一工具中的模型训练、批量处理、版本控制和监控。我们采用批量架构有两个原因:选择问题的离线特性(反馈在数天内累积),以及观察到访客选择行为的转变速度不足以需要实时模型更新。计划的SageMaker AI处理作业会读取上一周期的反馈,更新模型,并为下一周期生成新的推荐。
架构概览
我们每周运行一次SageMaker AI批量作业,从Amazon Simple Storage Service(Amazon S3)读取客户结果,更新老虎机模型,并将每个客户的推荐写入低延迟的键值存储。从周周期开始提供保守的基准。当模型表现出稳定的提升效果后,增加频率是直接的。审批反馈可能滞后数天,会被纳入后续批次。
图2:包含Amazon S3模型状态和键值服务的端到端批量老虎机架构
- 数据收集。客户印象和结果(开始、提交、审批)在会话结束时被记录,并作为观察数据流入Amazon S3。
- 模型更新与推理。Amazon SageMaker AI 处理作业运行 Python 入口点。它从 Amazon S3 加载最新的模型状态,自动发现最新日期的模型前缀,因此无需在每次运行之间重新配置。随后,它将数据拆分为反馈行和推理行,基于反馈数据对模型进行增量更新,并对所有潜在用户进行评分以选择一个臂。我们使用处理作业,因为我们的工作负载是一个自包含的步骤,既更新模型又进行评分,且需要自定义的 S3 输入输出。训练作业或批量转换作业都无法很好地映射到这种模式。
- 持久化与输出。作业将更新后的模型状态写回 Amazon S3(以新的带日期的路径存储,这提供了内置的版本历史和简单的回滚功能),同时保存观察结果和臂内容。每个客户的个性化推荐(每个客户映射到其选择的臂)会发布到低延迟键值存储(如 Amazon DynamoDB),用于支撑实时流量。
模型预热启动。我们从随机内容分配阶段对每个模型进行预热启动,这提供了无偏的数据,使老虎机能够初始化其信念而不会产生选择偏差,并从第一天起更高效地使用探索预算。
高效扩展推理。对大量潜在用户进行评分计算量大。两个优化措施使其控制在预算范围内:预先计算臂矩阵的逆(在批次内不会改变),以及将潜在用户集拆分为多个块,使用 Python 的 multiprocessing.Pool 并行处理。
页面的呈现方式。由于批量作业已经完成了大部分繁重工作,页面的呈现过程非常直接。个性化页面由低延迟键值存储(如 Amazon DynamoDB)提供,其中存储了每个客户的预计算推荐。当客户到达时,页面只需通过实体 ID 进行一次查询,即可渲染预计算臂的内容。没有实时模型推理。
对于需要实时评分的用例,其中上下文仅在请求时才可知,或者内容必须在会话中动态调整,Amazon SageMaker AI 实时推理端点是自然的选择,它通过低延迟 API 提供模型服务。
该设计还有一个值得强调的鲁棒性特性。如果访客没有推荐内容,页面会回退到默认的静态体验,因此没有客户的体验会比基准更差。这种回退机制限制了潜在损失,使渐进式部署更加安全。
学到的经验
在生产环境中部署此系统让我们学到了一些可以推广到其他用例的经验。
模型设计
当人群差异较大时,应分别训练。如果您的受众分为具有显著不同特征或转化率的群体,单个共享模型会让规模更大或噪声更多的群体主导学习内容。为每个群体单独训练一个模型,为每个模型分配其专属的特征集和臂空间,可以让每个受众的信号清晰地传递出来。
优化漏斗本身,而非依赖代理。最关键的设计决策是采用多目标优化。如果使用单阶段老虎机算法,我们可能会在上游指标上取得优势,但会导致下游决定商业价值的指标性能下降。部署前我们通过实证验证了这一点。所有仅针对漏斗单个阶段优化的策略,都会在其他环节产生至少一项负向提升。只有多目标优化方法能同时在三个阶段保持非负估计值。如果商业目标与首次点击存在多步距离,请将所有步骤编码到奖励函数中。
内容策略
选择算法仅解决了一半问题。内容库的质量同样关键。在我们的A/B测试中,某个用户群体在三个漏斗指标上均实现了正向提升,最终阶段目前达到高个位数百分比的相对提升。而另一个群体虽然模型探索了大部分选项,但未能找到优于静态页面的组合,所有提升均为负值,且审批回归结果具有统计显著性。这并非模型失效,充分探索可证明内容库中不存在优胜选项。
当老虎机广泛探索所有选项仍无法击败对照组(无老虎机的静态体验)时,应重新审视内容本身而非算法。这就是生成式内容流水线(如我们之前文章中提到的方案)的关键价值。它们能持续扩展和更新老虎机可选内容池,使模型更有可能找到成功组合。
建议将基准方案设为一个选项。将现有默认体验作为选项之一,意味着当没有个性化选项能击败默认方案时,UCB会自然选择默认方案,从而限制系统退化的幅度。
评估
离线评估和A/B测试回答不同问题。离线回放(在保留数据集上对比策略与随机选择)能回答"模型是否优于随机分配?",作为初步验证。但只有常规A/B测试(老虎机个性化方案对比静态基准)才能确定个性化是否优于现有体验。我们同时采用了两种方式:离线评估为上线提供了信心,而A/B测试给出了最终结论,包括发现某用户群体的内容库质量是限制性因素。
权重参数揭示了结果驱动因素。LinUCB学习到的θ向量具有直接可解释性。某个特征的高正权重意味着该特征表现突出的用户更可能在该选项上转化。几周后你可以询问"哪些信号区分了对该图片有响应的用户?"并获得可信洞察。这在不增加工具的情况下实现了内置可解释性,同时为内容策略提供直接输入。
运维
批量处理是合法的部署模式。运行老虎机不需要实时在线学习应用。每周执行一次读取反馈、更新精确模型、将推荐写入S3的处理任务,既可审计又资源高效,且适合延迟反馈场景。
结论
生成式AI打破了个性化内容生产的限制。剩下的挑战是决定向谁展示哪些内容,并从真实的客户反馈中学习答案。多臂老虎机正是为此而设计的。通过上下文多目标优化方案,您可以在优化整个转化漏斗的同时,根据个人行为进行个性化推荐。
该系统在AWS上操作简单。通过定时运行的SageMaker AI处理作业配合Amazon S3存储版本化模型状态,您可以实现增量学习、审计追踪和安全回退,而无需专门的实时工具。
如果生成式AI已经填充了您的内容库,那么上下文老虎机就是自然的优化层,可以识别每个用户哪种内容变体能产生最佳效果。本文系列介绍的两种技术是互补的。
要开始使用,请打开Amazon SageMaker AI控制台,查阅SageMaker AI开发者指南,克隆代码示例并打开其交互式笔记本自行运行老虎机算法,同时回顾我们之前关于在Amazon Bedrock上使用生成式AI进行个性化推荐的博文。
作者简介
'"`