Swiggy 如何用 350+ 个特征和多任务 MLP 预测客户终身价值

2026-09-02 34 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

客户终身价值(Customer Lifetime Value,LTV)决定了获客广告到底应该为一个新用户出价多少。Swiggy 的实践重点不只是训练一个更大的模型,而是把下单前可获得的 350 多个特征、Food 与 Instamart 两类业务,以及订单数这一辅助任务组合起来,构建内部预测 LTV(pLTV)模型,并将信号用于 Google Target ROAS 出价优化。

预测目标不止一个

单独预测未来收入,模型需要从大量稀疏行为中推断用户是否会继续下单、会下多少单,以及订单可能带来的价值。Swiggy 采用多任务 MLP,同时学习 pLTV 和订单数等目标。

订单数是一个很自然的辅助任务:它与长期价值直接相关,又比最终收入更容易从用户的早期行为中学习。摘要显示,引入订单数辅助任务后,模型参数量减少了 63%,同时预测表现得到改善。这说明多任务学习的价值不只是“多输出一个结果”,还可以通过共享表示减少重复参数,让主任务获得更稳定的行为信号。

可以把模型抽象成下面的结构:

350+ 个下单前特征
        |
   共享 MLP 表示
      /       \
 pLTV 回归头   订单数预测头

Food 和 Instamart 可以共享部分用户行为表示,同时保留业务相关的输出头或特征。实际拆分方式需要根据样本量、标签定义和业务差异验证,不能仅凭业务名称决定模型结构。

为什么强调“下单前”特征

LTV 模型用于获客时,预测只能使用广告曝光或转化决策之前已经知道的信息。把转化之后的订单金额、未来行为或人工生成的事后字段混入特征,会造成标签泄漏:离线指标可能变好,但线上出价会失真。

一组可实践的特征大致可以包括:

  • 用户历史访问、搜索、加购和转化行为的时间窗口统计。
  • 渠道、设备、地区、时间段等上下文信息。
  • Food 与 Instamart 的业务偏好及跨业务互动信号。
  • 最近一次活动距今时间、历史订单间隔、行为频率等时序特征。
  • 缺失标记、截断后的计数和经过校准的连续变量。

关键不在于简单堆到 350 个字段,而在于每个字段在预测时点是否可用、统计窗口是否固定、线上与离线计算是否一致。高维特征也会放大数据漂移和缺失率问题,因此应记录每个特征的生成时间、覆盖率和版本。

一个可运行的多任务 MLP 示例

下面的示例使用 PyTorch 生成一组模拟数据,演示共享 MLP、pLTV 回归头、订单数辅助头和联合损失。它不是 Swiggy 的生产实现,真实系统需要替换为经过时间切分的数据,并处理类别特征、样本权重、标签延迟和模型校准。

运行前安装依赖:

python -m pip install torch

将下面内容保存为 multitask_ltv.py 后运行:

import torch
from torch import nn

# 固定随机种子,便于复现实验
 torch.manual_seed(7)

n_samples, n_features = 4096, 350
x = torch.randn(n_samples, n_features)

# 模拟两个与用户行为相关的监督信号
latent = 0.8 * x[:, 0] - 0.4 * x[:, 1] + 0.2 * x[:, 2]
orders = torch.poisson(torch.exp((latent + 1.0).clamp(-2.0, 2.0)))
ltv = (orders * (12.0 + 3.0 * torch.sigmoid(x[:, 3]))
        + 0.5 * torch.randn(n_samples)).clamp_min(0.0)

class MultiTaskLTV(nn.Module):
    def __init__(self, input_dim):
        super().__init__()
        self.shared = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
        )
        self.ltv_head = nn.Linear(64, 1)
        self.orders_head = nn.Linear(64, 1)

    def forward(self, features):
        representation = self.shared(features)
        predicted_ltv = self.ltv_head(representation).squeeze(-1)
        predicted_orders = self.orders_head(representation).squeeze(-1)
        return predicted_ltv, predicted_orders

model = MultiTaskLTV(n_features)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
ltv_loss_fn = nn.SmoothL1Loss()
orders_loss_fn = nn.PoissonNLLLoss(log_input=False)

for step in range(500):
    predicted_ltv, predicted_orders = model(x)
    predicted_orders = predicted_orders.clamp_min(1e-5)

    # 主任务预测 LTV,辅助任务预测订单数
    loss_ltv = ltv_loss_fn(predicted_ltv, ltv)
    loss_orders = orders_loss_fn(predicted_orders, orders)
    loss = loss_ltv + 0.3 * loss_orders

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if step % 100 == 0:
        print(
            f"step={step:03d} total={loss.item():.4f} "
            f"ltv={loss_ltv.item():.4f} orders={loss_orders.item():.4f}"
        )

with torch.no_grad():
    sample_ltv, sample_orders = model(x[:3])
    print("predicted_ltv:", sample_ltv.tolist())
    print("predicted_orders:", sample_orders.tolist())

注意:代码中的 torch.manual_seed(7) 前面多了一个空格时会触发缩进错误。实际保存时应写成:

torch.manual_seed(7)

在生产训练中,可以把 0.3 作为可调的辅助任务权重,并用时间外验证集评估不同权重。订单数标签还可以使用 log1p 变换后的回归目标,具体取决于订单分布和线上决策需要。

pLTV 如何进入获客决策

预测信号的终点不是离线报表,而是广告出价。Swiggy 将 pLTV 与 Google Target ROAS bidding 结合,用于按预期长期价值优化客户获取。

可以这样理解这个闭环:

  1. 在用户转化前计算特征并预测 pLTV。
  2. 将预测价值作为转化价值信号传给广告投放系统。
  3. Target ROAS 根据价值与广告成本的关系调整竞价。
  4. 用后续真实订单和收入回流,重新评估预测偏差与投放增量。

实践中不能把 pLTV 直接当作真实收入而跳过校准。建议至少检查预测分桶后的实际 LTV、不同渠道的误差、Food 与 Instamart 的分业务误差,以及新老用户和地区之间的稳定性。若模型只学到“高活跃用户更有价值”,却没有带来增量获客,广告系统可能只是为原本就会转化的人提高出价。

落地清单

  • 明确预测窗口,例如未来 30 天、90 天或更长周期,并固定标签生成规则。
  • 只使用广告决策时点可获得的特征,建立防止标签泄漏的特征审计。
  • 以共享 MLP 加多个任务头作为基线,再比较单任务模型和更复杂结构。
  • 记录主任务与辅助任务的损失、分桶校准结果和跨业务表现。
  • 评估参数量、推理延迟、特征新鲜度和线上缺失率,而不只看离线误差。
  • 通过增量实验判断 pLTV 出价是否真正改善获客效率。

Swiggy 的案例给出的核心启发是:LTV 预测需要同时考虑特征可用性、行为辅助信号和广告系统接口。多任务学习可以让模型以更少参数学习更有用的用户表示,但最终价值仍要由时间外评估、校准和真实投放结果共同验证。


相关推荐