计算广告技术:从CTR预估到智能出价系统
计算广告技术:从CTR预估到智能出价系统
互联网广告是一门被算法深度改造的生意。一次广告曝光背后,系统要在几十毫秒内完成召回、粗排、精排、出价一整套决策,直接决定平台的收入和广告主的 ROI。这套链路里积累的技术——大规模稀疏特征建模、在线学习、强化学习出价——对做推荐和搜推广的开发者都有参考价值。本文按广告系统的核心模块展开,聊聊 CTR 预估的模型演进和智能出价的实现思路。
广告系统的整体漏斗
工业广告系统普遍采用级联架构:先从上千万候选广告中召回几千条(召回),用轻量模型快速打到几百条(粗排),再用重型精排模型预估每个候选的 CTR/CVR,最后按 eCPM(expected Cost Per Mille)排序并结合出价策略决定最终曝光。
eCPM 的计算逻辑是广告排序的核心:CPC 计费下 eCPM = pCTR × bid × 1000。可以看到 CTR 预估的准确性直接决定排序质量——pCTR 高估 10%,平台就可能把钱浪费在没人点的广告上;低估则把好流量让给了对手。
CTR 预估:从 LR 到深度序列模型
CTR 预估的挑战在于特征极度稀疏(用户 ID、广告 ID、类目都是千万级维度的 one-hot)且组合特征决定效果。模型演进大致经历了四代:
- LR 时代:逻辑回归 + 人工特征工程,简单可控可在线学习,但组合特征全靠人肉构造,天花板明显;
- GBDT+LR:Facebook 2014 年的经典方案,用 GBDT 自动做特征组合和离散化,叶子节点编号喂给 LR,减少了手工特征的工作量;
- Wide & Deep / DeepFM:Wide 侧记忆、Deep 侧泛化。DeepFM 用 FM 层替代 Wide 侧的手工交叉,一阶二阶特征与深度网络共享 embedding,端到端训练,至今仍是很多团队的 baseline;
- 行为序列模型:DIN、DIEN、SIM 这一系,把用户历史点击序列引入模型,用注意力机制让候选广告去"查询"相关历史行为,捕捉兴趣的多样性和时序演化,是效果提升最显著的一代。
一个简化版 DeepFM 的核心结构如下:
import torch import torch.nn as nn class DeepFM(nn.Module): def __init__(self, field_dims, embed_dim=16, mlp_dims=(128, 64)): super().__init__() num_fields = len(field_dims) self.embedding = nn.ModuleList( [nn.Embedding(dim, embed_dim) for dim in field_dims] ) self.linear = nn.ModuleList( [nn.Embedding(dim, 1) for dim in field_dims] ) total_embed = num_fields * embed_dim self.mlp = nn.Sequential( nn.Linear(total_embed, mlp_dims[0]), nn.ReLU(), nn.Linear(mlp_dims[0], mlp_dims[1]), nn.ReLU(), nn.Linear(mlp_dims[1], 1), ) def forward(self, x): # x: (batch, num_fields) 每列是某个特征域的 id embeds = [emb(x[:, i]) for i, emb in enumerate(self.embedding)] embed_stack = torch.stack(embeds, dim=1) # (B, F, D) # FM 二阶项: 0.5 * ((sum(v))^2 - sum(v^2)) sum_square = embed_stack.sum(dim=1).pow(2) square_sum = embed_stack.pow(2).sum(dim=1) fm_term = 0.5 * (sum_square - square_sum).sum(dim=1, keepdim=True) linear_term = sum(lin(x[:, i]) for i, lin in enumerate(self.linear)) deep_term = self.mlp(embed_stack.view(x.size(0), -1)) return torch.sigmoid(linear_term + fm_term + deep_term)几代模型的对比可以总结为:
| 模型 | 特征组合能力 | 是否利用行为序列 | 训练成本 | 适用场景 | | --- | --- | --- | --- | --- | | LR | 依赖人工交叉 | 否 | 极低 | 冷启动、基线监控 | | GBDT+LR | 树模型自动组合 | 否 | 低 | 中小数据量 | | DeepFM | 二阶自动 + 深度高阶 | 否 | 中 | 通用精排 baseline | | DIN/SIM | 高阶 + 序列注意力 | 是 | 高 | 大流量、用户行为丰富 |
召回与粗排:漏斗上游的工程权衡
精排模型再强,候选集里没有好广告也白搭。召回侧常用多路策略:定向标签召回(年龄、地域、兴趣标签)、向量召回(双塔模型把用户和广告编码到同一向量空间,ANN 检索)、以及探索性召回(给新广告冷启动流量)。
粗排是夹在中间的妥协产物:双塔结构把用户塔和广告塔分开,广告向量可以离线预计算,在线只需算一次用户向量和内积,单次打分成本比精排低两个数量级。代价是双塔限制了特征交叉能力,所以近年的趋势是用知识蒸馏让粗排逼近精排——精排模型做 teacher,粗排做 student。
