1. 这不是教科书,是我在广告系统一线踩坑三年攒下的算法笔记
“广告推荐算法”这六个字,听起来像高校实验室里的论文课题,但实际在业务现场,它就是每天凌晨三点还在跑的AB测试、是运营拍着桌子问“为什么CTR又掉了0.2%”、是产品经理拿着竞品截图说“人家首页信息流广告点击率比我们高17%”。我从2020年加入某头部电商广告平台起,就再没把“推荐算法”当一个纯技术名词——它是一套精密咬合的齿轮组:上游要接得住千万级QPS的实时用户行为流,中游得扛得住毫秒级响应的在线打分压力,下游还得让广告主看得懂、信得过、愿意持续投钱。这本笔记里没有公式推导的优雅闭环,只有我把模型部署到线上后,发现特征延迟导致预估偏差、排查出Redis缓存穿透引发服务雪崩、为绕过某SDK埋点漏报硬生生重写了三版日志解析逻辑的真实记录。关键词“广告推荐算法”和“学习笔记”背后,其实是两个现实命题:第一,怎么让算法真正驱动商业结果,而不是只在离线AUC上漂亮;第二,怎么把散落在工程日志、AB实验报告、运营复盘会里的碎片经验,沉淀成可复用、可传承、可快速上手的实操路径。如果你刚从机器学习课程毕业,正对着LR、FM、DeepFM代码发懵;或者你是转岗来的后端工程师,第一次被要求看懂广告位eCPM排序逻辑;又或者你已是资深算法工程师,但团队新人总在特征一致性上反复踩坑——这本笔记就是为你写的。它不讲“什么是协同过滤”,而是告诉你为什么在广告场景下,Item-CF必须配合曝光归一化才能用,否则冷启动广告的预估分会被热品严重稀释;它不罗列“主流模型架构”,而是拆解为什么我们在双塔DNN基础上强制加入交叉层,只因广告主预算约束下,用户对价格敏感度与品类兴趣存在强耦合,纯向量内积无法建模这种非线性关系。所有内容都来自真实业务压测、灰度发布和故障复盘,每一段结论背后都有对应的数据看板截图编号、线上服务TraceID和回滚时间点。现在,我们直接进入实战。
2. 广告推荐算法的本质:不是预测点击,而是优化商业目标的决策引擎
2.1 为什么传统推荐范式在广告场景会失效?
很多刚接触广告算法的同学,会下意识把“广告推荐”等同于“商品推荐”或“视频推荐”。这是最危险的认知偏差。我见过三个典型翻车案例:
- 某次新模型上线,离线AUC提升0.015,线上CTR却下降0.8%。复盘发现,模型过度拟合了“用户点击高曝光广告”的历史行为,而忽略了广告主调价后,同一广告在不同时间段的转化价值差异。简单说,模型学会了“点贵的”,但没学会“点值的”。
- 另一个团队用GraphSAGE做用户兴趣建模,图节点包含用户、商品、广告主三类实体。上线后发现长尾广告主的新品曝光量暴跌。根因是图采样时未加权,导致小广告主节点被大广告主邻居淹没,其新品特征在聚合过程中被均值化抹平。
- 最致命的一次:用多任务学习同时优化CTR和CVR,离线指标全优,但线上GMV反降。审计日志发现,模型为提升CVR预估准确率,主动压低了高客单价、低转化率广告的排序分——这些广告虽转化率低,但单次成交GMV是平均值的3.2倍,模型却把它当成“低质流量”过滤了。
这些失败指向同一个底层逻辑:广告推荐不是纯粹的“用户-物品匹配”,而是“用户-广告-商业约束”三方博弈的实时决策过程。它的目标函数天然包含多重冲突项:
- 短期目标:最大化当前请求的eCPM(有效千次展示收益),公式为
eCPM = bid × pCTR × pCVR × (1 - discount_factor),其中discount_factor反映广告主预算消耗速度; - 长期目标:保障广告主ROI(投入产出比)不低于阈值,否则广告主会撤资;
- 平台目标:维持生态健康,避免劣质广告挤占优质广告位,需引入质量分、反作弊因子等约束项;
- 用户体验目标:控制广告密度、频次、相关性,防止用户流失。
提示:当你看到任何广告算法方案时,先问自己三个问题:这个方案是否显式建模了bid(出价)变量?是否考虑了广告主预算的动态衰减?是否对低频长尾广告做了特殊保护机制?如果答案是否定的,那它大概率只是个“看起来很美”的学术玩具。
2.2 广告推荐系统的四层架构:从数据到决策的完整链路
广告推荐不是单个模型,而是一套分层决策流水线。我在实际项目中将其划分为四个物理层级,每一层都承担不可替代的职能:
第一层:召回层(Recall Layer)—— 海量候选池的粗筛
核心任务:从百万级广告库中,10ms内筛选出1000~5000个与当前请求相关的候选广告。常用策略包括:
- 向量召回:用双塔DNN生成用户向量和广告向量,通过ANN(近似最近邻)检索。关键细节:用户向量必须融合实时行为(如最近3分钟点击序列),而非仅用静态画像;广告向量需注入预算剩余率、历史CTR衰减斜率等动态信号。
- 规则召回:基于业务强约束的硬过滤,例如“排除已曝光超3次的广告”、“仅召回预算剩余>500元的广告主旗下商品”。这部分常被忽略,但实测能减少30%无效计算。
- 协同过滤召回:改进版Item-CF,计算时对每个用户-广告交互加权:
weight = log(1 + exposure_time) × (1 + click_flag),避免单纯用点击数导致长尾广告永远无法进入召回池。
第二层:粗排层(Rough Ranking Layer)—— 快速打分与截断
核心任务:对召回层输出的候选集,用轻量模型进行初步打分,截断至200~500个广告。这里的关键是速度与精度的平衡点。我们曾对比三种方案:
- 方案A:直接用精排模型的简化版(去掉交叉层、减少隐层维度)。结果:RT(响应时间)达标,但AUC下降0.02,线上CTR损失明显;
- 方案B:用GBDT+LR组合,特征工程复杂但RT稳定。结果:AUC保持95%以上,但特征更新延迟导致新广告冷启动期预估偏差达40%;
- 方案C:蒸馏模型——用精排模型作为Teacher,训练一个结构更简的Student模型。最终选择方案C,因为其RT比精排低6倍,AUC损失仅0.003,且支持分钟级特征热更新。
第三层:精排层(Fine Ranking Layer)—— 商业目标导向的终极打分
核心任务:对粗排后的候选集,用复杂模型输出最终eCPM预估分。这里必须明确:精排模型的输出不是pCTR,而是经过商业逻辑校准的eCPM。我们的标准流程是:
- 模型输出原始pCTR和pCVR;
- 乘以广告主实时bid(从Redis缓存读取,TTL=30s);
- 乘以预算衰减系数(公式:
decay_factor = 1 - (spent_budget / total_budget)^2,二次方体现预算耗尽时的陡峭衰减); - 加入质量分修正项(基于广告素材清晰度、落地页加载速度、历史违规记录计算);
- 输出最终eCPM。
这个过程不能封装在模型内部,必须暴露给下游调控——因为运营需要根据eCPM分布调整流量分配策略。
第四层:竞价与调控层(Auction & Control Layer)—— 实时决策的最后防线
核心任务:执行广义第二价格拍卖(GSP),并叠加平台级调控策略。常见操作包括:
- 流量分桶调控:将用户按LTV(生命周期价值)分桶,高价值用户流量池中,强制提升品牌广告占比;
- 预算兜底机制:当某广告主预算即将耗尽时,自动触发“保量投放”模式,降低其eCPM计算中的discount_factor权重;
- 反作弊熔断:监测到某广告点击率异常飙升(如1分钟内CTR>15%),立即暂停该广告,并启动人工审核流程。
这四层不是线性管道,而是存在反馈闭环:精排层的bad case会反哺召回层的负样本构造;调控层的熔断事件会触发粗排模型的在线微调。理解这个架构,比死记硬背某个模型公式重要十倍。
2.3 广告场景特有的三大技术挑战与破局思路
挑战一:特征时效性与数据延迟的永恒矛盾
广告决策依赖实时行为,但数据链路存在天然延迟:用户点击→客户端埋点→日志上报→Kafka→Flink实时计算→特征写入Redis→模型读取。我们实测端到端延迟在800ms~2.3s之间波动。这意味着:当用户刚点击完某商品,模型可能还在用3秒前的行为序列做决策。
破局方案:
- 特征版本化:为每个特征字段增加
version_timestamp,模型加载时自动过滤掉延迟超1.5s的特征; - 延迟补偿建模:在模型输入中显式加入
delay_seconds特征,让模型学习“延迟对预估的影响规律”。实测显示,加入该特征后,延迟1.2s内的预估偏差降低37%; - 客户端预计算:在APP端集成轻量模型,对用户本次会话行为做本地预估,结果随埋点一同上报,作为服务端模型的辅助特征。
挑战二:冷启动广告的“零曝光陷阱”
新上架广告在72小时内无曝光,导致特征缺失、模型无法预估。传统做法是用广告主历史平均CTR填充,但误差极大——同一广告主的不同商品,CTR可相差10倍。
破局方案:
- 跨广告主迁移学习:构建广告主相似度图谱(基于行业、客单价、用户画像重合度),对新广告,取Top3相似广告主的历史CTR加权平均作为初始值;
- 素材级特征泛化:提取广告图片的CLIP视觉特征、文案的BERT语义特征,即使无历史曝光,也能通过相似素材的CTR进行迁移;
- 强制探索机制:对新广告,在召回层设置独立通道,按固定比例(如5%)强制曝光,收集初始反馈。关键细节:探索流量必须来自高潜力用户(LTV>均值1.5倍),避免浪费低价值流量。
挑战三:多目标优化的帕累托前沿撕裂
CTR、CVR、GMV、ROI、用户体验指标之间存在强冲突。单纯加权求和会导致“指标幻觉”——比如提高权重让CTR好看,但GMV实际下滑。
破局方案:
- 分层目标建模:将目标分解为“基础目标”(如CTR必须>0.5%)、“约束目标”(如ROI≥2.0)、“优化目标”(如GMV最大化)。模型训练时,基础目标用交叉熵损失,约束目标用带松弛因子的Hinge Loss,优化目标用加权回归损失;
- 动态权重调度:根据大盘健康度(如广告主留存率、用户投诉率)实时调整各目标权重。当投诉率>0.3%时,自动提升用户体验指标权重30%;
- 帕累托前沿采样:在线服务时,对每个请求生成5组不同权重的eCPM结果,从中选取Pareto最优解(即不存在另一组结果在所有指标上都优于它)。
这些挑战没有银弹解法,只有在一次次线上事故中迭代出的务实方案。记住:广告算法工程师的核心能力,不是调参,而是定义问题边界、设计容错机制、在商业约束下寻找最优解。
3. 从零搭建广告推荐Pipeline:我的实操步骤与避坑清单
3.1 环境准备与数据基建:90%的失败源于此
很多人一上来就想跑通DeepFM,结果卡在数据接入环节三天。我建议把70%精力花在基建上。以下是我在三个项目中验证过的最小可行基建栈:
数据源接入:
- 用户行为日志:必须包含
user_id、item_id、ad_id、event_type(click/impression)、timestamp、position(广告位序号)、context(设备类型、网络状态、地理位置)。特别注意:ad_id必须全局唯一,不能是广告主自定义ID,否则跨广告主归因失效; - 广告主侧数据:
ad_id、bid_price、budget_total、budget_spent、creative_type(图片/视频/文字)、landing_page_speed(首屏加载毫秒数)。这些数据需通过API每日同步,且必须有幂等性校验; - 用户画像:基础属性(年龄、性别、城市等级)用离线ETL,兴趣标签(如“数码爱好者”、“母婴人群”)必须支持实时更新(Flink CDC监听MySQL binlog)。
特征存储选型:
- 实时特征:Redis Cluster(分片数≥32),Key设计为
feature:{ad_id}:{timestamp_floor},Value为JSON字符串。实测单集群支撑20万QPS,延迟<5ms; - 离线特征:Hive分区表,按
dt(日期)和hour(小时)二级分区。关键技巧:对高频访问特征(如用户历史CTR),单独建宽表并启用ORC格式+ZSTD压缩,查询提速3倍; - 向量特征:FAISS索引文件存OSS,内存中加载。注意:FAISS不支持动态增删,需每日凌晨重建索引。
注意:千万别用MySQL存实时特征!我们曾因MySQL连接池耗尽导致整个召回服务超时,故障持续47分钟。Redis的原子性操作和内存特性,是实时场景的刚需。
模型训练框架:
- 推荐TensorFlow 2.x(非PyTorch),原因:TF Serving对模型版本管理、热加载、AB测试支持更成熟;
- 特征处理统一用TF Transform,确保训练与推理特征逻辑完全一致;
- 分布式训练用Horovod,但必须关闭NCCL的
NCCL_ASYNC_ERROR_HANDLING,否则GPU通信异常时进程不退出,导致训练卡死。
这套基建看似枯燥,但它决定了后续所有工作的稳定性。我见过太多团队,模型效果不错,但因Redis缓存击穿导致服务雪崩,最终被业务方否决。基建不是成本,是护城河。
3.2 特征工程:广告场景下必须死磕的12个核心特征
特征决定算法的上限。在广告场景,以下12类特征缺一不可,且每个都有独特构造逻辑:
| 特征类别 | 典型字段 | 构造要点 | 业务意义 |
|---|---|---|---|
| 用户实时行为 | last_5min_click_count,last_1h_impression_div_click | 时间窗口必须动态:对新用户用15分钟,老用户用2小时;除法特征需加平滑项(+0.1)防除零 | 反映即时兴趣强度与广告接受度 |
| 广告动态状态 | budget_remaining_ratio,bid_change_rate_24h | 预算剩余率用max(0, (total-budget)/total),避免负值;出价变化率用滑动窗口标准差 | 预判广告主投放激进程度 |
| 位置上下文 | position_ctr_bias,page_type_ad_density | 位置CTR偏差=该位置历史CTR/大盘CTR;页面广告密度=当前页广告数/总卡片数 | 校正位置偏置与信息流疲劳效应 |
| 创意质量信号 | image_clarity_score,video_play_rate_3s | 图片清晰度用OpenCV计算Laplacian方差;视频3秒播放率需剔除网络异常用户 | 过滤低质素材,提升用户体验 |
| 用户-广告交叉 | user_ad_category_match,ad_user_ltv_ratio | 类目匹配度=用户历史点击类目与广告类目的Jaccard相似度;LTV比=广告主LTV/用户LTV | 衡量供需匹配深度 |
| 时间周期特征 | is_weekend,hour_sin/hour_cos | 周末标识必须结合用户所在时区;小时特征用sin/cos编码,避免0点与23点距离失真 | 捕捉用户行为周期性 |
避坑重点:
- 绝对不要用“用户总点击数”这类全局统计特征:它会让模型认为“点击多的用户一定喜欢广告”,而忽略用户点击的是竞品还是自家广告;
- 所有比率类特征必须加平滑:如
click_count/(impression_count+10),分母加10是经验值,对应10次曝光的先验; - 交叉特征要带业务解释:比如
user_age_bucket × ad_price_level,不能只写age_price_interaction,否则后期无法归因。
我坚持一个原则:每个特征上线前,必须回答三个问题:这个特征如何影响商业目标?它的数据源是否可靠?它的延迟是否可控?答不上来,就砍掉。
3.3 模型选型与训练:从LR到ESMM的渐进式演进路径
别迷信SOTA模型。我的经验是:用最简单的模型解决80%的问题,再用复杂模型攻坚20%的瓶颈。以下是我在不同阶段的选型逻辑:
阶段一:基线模型(上线周期≤3天)
- 模型:Logistic Regression + 人工特征交叉
- 特征:用户基础属性×广告类目、历史CTR×预算剩余率、位置偏差×时间周期
- 优势:可解释性强,AB测试归因清晰;训练快,支持小时级迭代;
- 关键配置:使用FTRL优化器(适合稀疏特征),L1正则系数设为0.001(保留关键交叉项)。
- 效果:通常能达到精排baseline的75%效果,但RT仅为其1/10。
阶段二:进阶模型(上线周期≤2周)
- 模型:Wide&Deep(WDL)
- Wide部分:承接LR的所有有效特征,重点加入“用户-广告-位置”三阶交叉;
- Deep部分:Embedding层用Adagrad优化,隐层结构
[128,64,32],激活函数用Swish(比ReLU在广告场景提升0.002 AUC); - 训练技巧:负采样比例设为1:3(1正例:3负例),负样本必须来自同一召回池,否则引入偏差。
- 效果:AUC提升0.012,线上CTR+1.8%,但RT增加至80ms。
阶段三:高阶模型(上线周期≥1月)
- 模型:ESMM(Entire Space Multi-Task Model)
- 架构:共享底层Embedding,上层分两支:CTR分支(sigmoid输出)和CTCVR分支(
pCTR × pCVR联合建模); - 关键创新:引入
auxiliary_loss(辅助损失),用CTR任务监督CVR分支的中间表示,缓解样本稀疏; - 训练数据:必须用全曝光日志(含未点击样本),不能只用点击样本,否则CVR分支学不到真实分布。
- 效果:GMV提升3.2%,但模型体积增大5倍,需专用GPU节点部署。
避坑清单:
- 不要在WDL中用BatchNorm:广告特征极度稀疏,BN统计量不稳定,会导致训练震荡;
- ESMM的CTCVR分支必须用
sigmoid而非softmax:因为它是二分类任务,softmax会强制概率和为1,破坏pCTR × pCVR的物理意义; - 所有模型必须做特征重要性分析:用SHAP值排序,若业务强相关特征(如
bid_price)重要性排名低于10%,说明模型存在严重偏差,需检查数据泄露。
模型不是越深越好,而是越贴近业务约束越好。我见过用Transformer做精排的团队,AUC很漂亮,但因为序列长度限制,只能处理用户最近50次行为,漏掉了关键的长周期兴趣信号,最终被业务方弃用。
3.4 模型部署与AB测试:让算法真正产生商业价值
模型上线不是终点,而是商业验证的起点。我的部署流程严格遵循“灰度-分流-监控-决策”四步:
灰度发布:
- 第一阶段:1%流量,仅限内部员工账号,验证基础功能;
- 第二阶段:5%流量,按用户ID哈希分流,重点监控RT和错误率;
- 第三阶段:20%流量,按地域分桶(如华东区),观察区域级指标变化。
AB测试设计:
- 对照组(A):旧模型;实验组(B):新模型;
- 必须设置第三组(C):随机对照组(Random Control),即完全随机排序。这是检验“模型是否真有效”的黄金标准——如果B组比A组好,但比C组差,说明旧模型本身就有问题;
- 核心指标:CTR、CVR、eCPM、GMV、用户停留时长、广告投诉率。其中投诉率必须纳入,否则会鼓励“诱导点击”类劣质广告。
实时监控看板:
- 基础层:RT P95<80ms、错误率<0.01%、特征缺失率<0.5%;
- 业务层:各广告主ROI分布、新广告72小时曝光量、高价值用户广告点击率;
- 异常检测:用EWMA(指数加权移动平均)算法,当CTR连续10分钟偏离基线2个标准差,自动触发告警。
决策机制:
- 数据决策:新模型需同时满足①CTR提升≥0.5%且②GMV提升≥1.0%且③投诉率不升,才可全量;
- 业务决策:若新模型导致某KA广告主ROI连续2天<1.8,立即降级,无论其他指标多好;
- 回滚机制:一键切换模型版本,回滚时间<3分钟。我们要求每次上线前,必须演练三次回滚流程。
提示:AB测试最常犯的错误是“只看整体指标,忽略分层效果”。曾有个模型整体CTR+2%,但女性用户CTR-5%,原因是模型过度拟合了男性用户的数码类广告偏好。务必按用户属性、广告类目、时间段做多维下钻分析。
4. 真实故障复盘:那些让你彻夜难眠的线上Bug与解决方案
4.1 故障一:Redis缓存穿透引发的雪崩式超时
现象:某日凌晨2点,精排服务RT从45ms飙升至2.3s,错误率突破15%,大量请求超时。
排查过程:
- Step1:查看监控,发现Redis CPU使用率100%,但QPS未明显增长;
- Step2:抓取Redis慢日志,发现大量
GET feature:ad_123456789:1712345678命令,key中ad_123456789是无效广告ID; - Step3:检查上游,发现广告主API同步故障,导致10万条无效广告ID写入特征库;
- Step4:确认缓存未设空值(null)过期时间,导致每次请求都穿透到DB。
根因:缓存设计缺陷——对不存在的key,未写入empty占位符。
解决方案:
- 缓存空值:对查询返回null的key,写入
empty值,TTL设为30分钟(短于正常特征TTL); - 布隆过滤器前置:在Redis前加一层布隆过滤器,拦截99.9%的无效key查询;
- 熔断降级:当Redis错误率>5%时,自动切换至本地缓存(Caffeine),容忍部分特征缺失。
教训:缓存不是“有就行”,而是“有且健壮”。所有缓存方案必须回答:无效key怎么办?缓存击穿怎么办?缓存雪崩怎么办?
4.2 故障二:特征延迟导致的预估系统性偏差
现象:某次模型更新后,线上CTR稳定,但GMV意外下降3.7%。
排查过程:
- Step1:对比新旧模型离线AUC,差异仅0.001,排除模型问题;
- Step2:抽样分析bad case,发现高客单价广告预估分普遍偏低;
- Step3:追踪特征链路,发现
bid_price特征从Kafka到Redis存在1.8s延迟,而模型用的是1.2s前的bid; - Step4:计算偏差:当bid实际为10元,模型用8元计算,eCPM低估20%,导致排序靠后。
根因:特征时效性SLA未量化,监控缺失。
解决方案:
- 特征延迟监控:对每个关键特征,计算
now() - feature_update_timestamp,超过阈值(如1s)告警; - 延迟补偿:在模型输入中加入
bid_delay_seconds特征,并在训练数据中注入人工延迟样本(模拟1s/2s/3s延迟); - 动态降权:当
bid_delay_seconds > 1.5s,自动将该特征权重降至0.3。
教训:在实时系统中,“数据新鲜度”比“数据准确性”更致命。宁可要1秒前的正确数据,也不要3秒后的完美数据。
4.3 故障三:多目标优化中的指标幻觉
现象:新模型上线后,CTR提升2.1%,CVR提升1.5%,但广告主投诉量激增40%。
排查过程:
- Step1:查看投诉详情,87%投诉指向“诱导点击”广告(如“免费领iPhone”、“点击领红包”);
- Step2:分析模型输出,发现这类广告的pCTR预估分异常高,但pCVR极低;
- Step3:检查损失函数,发现CVR分支权重过高(0.7),导致模型为提升CVR指标,刻意压低高CTR低CVR广告的分数,反而让诱导类广告因高CTR获得高排序。
根因:多目标权重设置脱离业务约束,未引入用户体验惩罚项。
解决方案:
- 引入投诉率损失:新增分支预测“投诉概率”,损失函数中加入
lambda × BCELoss(complaint_pred, complaint_label); - 硬约束机制:对投诉率>5%的广告主,强制将其所有广告eCPM乘以0.5;
- 人工审核通道:当某广告投诉率单日超3%,自动进入人工审核队列,暂停投放。
教训:算法指标必须与业务风险挂钩。没有风控的优化,就是饮鸩止渴。
4.4 故障四:冷启动广告的“幽灵曝光”
现象:新广告上线后,后台显示曝光量1000次,但广告主报表中曝光量为0。
排查过程:
- Step1:核对数据源,发现广告主API返回的曝光日志格式有误(
ad_id字段名写成adid); - Step2:检查日志解析模块,发现未做字段名容错,直接丢弃整条日志;
- Step3:追溯发现,该模块上线已3个月,此前因广告主数量少未暴露问题。
根因:数据协议缺乏版本管理和容错机制。
解决方案:
- Schema Registry:所有日志格式注册到Confluent Schema Registry,变更需审批;
- 字段容错:解析时对缺失字段赋默认值(如
ad_id缺失则用adid替代),并记录warn日志; - 双写校验:关键日志同时写入Kafka和本地文件,定期比对一致性。
教训:数据链路的脆弱性,往往藏在最不起眼的字段名里。每一个外部依赖,都要当作潜在故障点来设计。
5. 给新手的三条血泪建议:少走五年弯路
我带过12个应届生,看着他们从对着Jupyter Notebook发呆,到能独立负责一个广告位的算法迭代。如果时光倒流,我会把这三条建议刻在他们工位上:
第一条:先搞懂业务,再谈算法
别急着跑通代码。花一周时间:
- 看完最近三个月的运营复盘会纪要,标记出所有被提及的“效果差”的广告位和原因;
- 跟销售同学一起拜访2个KA广告主,听他们吐槽“为什么我的广告总排在后面”;
- 自己当一天用户,在APP里刷100次信息流,记录哪些广告让你想点、哪些让你反感、哪些直接划走。
算法是解决问题的工具,不是炫技的舞台。你连问题在哪都不知道,模型再 fancy 也是空中楼阁。
第二条:把“可解释性”刻进DNA
每次上线新模型,必须能回答:
- 这个广告为什么排在这里?(用SHAP值定位TOP3影响特征)
- 如果广告主问“为什么我的出价没变,排名却掉了”,你能用实时特征值给出具体原因吗?
- 当指标异常时,你的归因路径是否能在5分钟内定位到具体特征或数据源?
在广告场景,不可解释的模型就是定时炸弹。业务方不会为“黑盒AUC提升0.01”买单,但会为“通过优化XX特征,让母婴类广告CTR提升12%”鼓掌。
第三条:拥抱“不完美”的工程现实
教科书里的理想世界:数据干净、延迟为零、算力无限。现实是:
- 30%的用户行为日志缺失,你要用插值和回填补上;
- Redis集群偶尔抖动,你要设计降级策略;
- 广告主明天就要上线活动,你只有8小时完成模型迭代。
真正的高手,不是写出最漂亮代码的人,而是能在资源约束下,用最务实方案达成商业目标的人。少些“应该怎样”,多些“现在能做什么”。
这本笔记会持续更新,不是因为技术有多炫,而是因为广告战场每天都在变——新广告形态出现、用户习惯迁移、平台规则调整。但底层逻辑不变:用数据说话,用结果证明,用敬畏心对待每一次曝光背后的用户信任。下次当你看到“广告推荐算法”这个词,希望你想到的不是公式,而是凌晨三点盯着监控看板时,那个为0.1%的CTR提升而雀跃的自己。