
1. 转化率预测里被忽视的金矿未点击样本做过推荐系统和广告排序的人都有一个共识转化率预测模型的上限往往不取决于模型结构有多花哨而取决于你手里那批样本用得够不够狠。大多数人把精力砸在特征工程和网络结构上却对未点击样本这个巨大的数据池视而不见这其实是一种极大的浪费。先把这个问题的背景说清楚。在典型的推荐或广告场景里用户行为可以粗略分成几层曝光、点击、转化。转化率预测要建模的是 P(转化 | 点击)也就是在已经点击的前提下用户最终完成下单、注册、付费等目标行为的概率。问题在于转化事件极其稀疏——曝光一百万次点击可能只有几万次真正转化的可能就几百次。如果只用有点击且有转化的正样本加上有点击但没转化的负样本去训练数据量小得可怜模型很容易过拟合泛化能力差。那未点击样本呢它们数量庞大占了曝光总量的绝大多数。传统做法是把它们直接丢掉理由很简单没点击自然没转化标签是确定的负样本没有信息量。但这个理由经不起推敲。未点击不等于不感兴趣更不等于不会转化。用户没点击可能是因为当时在忙、可能是位置太靠后没看到、可能是标题不够吸引人但商品本身是他需要的。如果把这些样本一律当成负样本硬塞进训练集反而会引入大量噪声把模型带偏。NISE 这篇工作切入的正是这个痛点用半监督学习的思路把未点击样本合理地利用起来而不是简单地丢弃或粗暴地当负样本。它要解决的核心问题是在转化标签极度稀疏的情况下如何借助海量未点击样本来提升转化率预测的精度。这套思路适合谁参考做推荐系统排序、广告 CTR/CVR 预估、电商个性化推荐的算法工程师以及任何面对正样本稀缺、无标签数据海量场景的从业者。下面我会把这条技术路线拆开讲清楚它为什么成立、怎么落地、以及实操中会踩哪些坑。2. 为什么未点击样本不能一丢了之2.1 转化率预测的样本困境到底有多严重要理解 NISE 的价值得先感受一下数据有多稀疏。假设一个电商推荐场景日曝光 5000 万次点击率 4%那么点击样本约 200 万点击后的转化率假设是 3%那么转化正样本只有 6 万条。用 6 万条正样本去训练一个深度模型参数量动辄几百万甚至上千万这中间的差距就是过拟合的温床。更麻烦的是转化行为还有明显的延迟。用户今天点击了商品可能三天后才下单。这意味着你训练时拿到的未转化标签有一部分其实是还没转化属于假负样本。这类样本如果被当成真负样本模型学到的就是错误的信号。而未点击样本里同样藏着大量潜在的转化用户只是他们连点击这一步都没完成。所以整个样本体系是这样的曝光样本海量但标签模糊点击样本中等但转化标签稀疏转化正样本极少但价值最高。传统监督学习只用了中间和最后两层把最大的一层浪费了。NISE 的思路就是把这最大的一层用半监督的方式盘活。2.2 把未点击当负样本模型会学到什么错误信号我见过不少团队图省事直接把未点击全部标成负样本和点击未转化的样本混在一起训练。短期看 AUC 好像还行因为负样本变多了模型更容易区分会转化和不会转化。但上线后往往发现模型对长尾商品和高潜力新品的排序能力明显下降。原因在于未点击样本里混杂着两类完全不同的用户一类是真的不感兴趣另一类是感兴趣但没被触达。把这两类都打成负样本模型会错误地认为这个用户对这个商品没兴趣从而在后续推荐中降低这类商品的曝光。久而久之推荐结果越来越窄陷入信息茧房。这就是假负样本带来的系统性偏差它不会在离线指标上立刻暴露却会在线上长期伤害用户体验。提示判断未点击样本能不能用关键不是有没有点击而是这个样本的标签置信度有多高。置信度低的样本要么加权、要么用半监督方式软处理绝不能一刀切。2.3 半监督学习为什么天然适配这个场景半监督学习的核心假设是无标签数据的分布本身携带信息。即使不知道每个未点击样本的真实标签只要知道它们在特征空间里的分布就能帮助模型更好地刻画决策边界。这在转化率预测里特别成立因为用户和商品的特征空间是连续的未点击样本恰好填补了正负样本之间的灰色地带。具体来说半监督学习有几条常见路线自训练用模型给无标签样本打伪标签再迭代、一致性正则对同一样本加不同扰动要求输出一致、对比学习拉近相似样本、推远不同样本。NISE 结合了其中的伪标签和一致性思路把未点击样本当作无标签数据用模型自身的预测作为软标签再通过多轮迭代逐步提升标签质量。这套逻辑之所以成立是因为转化率预测的决策边界本来就是渐变的不是非黑即白。3. NISE 的核心机制拆解3.1 从点击—转化两段式到统一建模传统 CVR 模型通常假设点击是转化的必要条件先做 CTR 预估再对点击样本做 CVR 预估。这种两段式有个隐患CTR 阶段的误差会传导到 CVR 阶段而且两段之间的样本选择偏差只对点击样本建模很难消除。NISE 的做法是把未点击样本纳入统一框架不再严格区分点击和未点击作为建模前提而是把转化看作一个受多因素影响的概率事件。模型输入的是曝光级别的样本输出的是转化概率点击行为作为其中一个中间信号参与建模。这样一来未点击样本不再是被排除的样本而是标签不确定的样本正好交给半监督机制处理。这个转变的意义在于它把样本选择偏差从结构性缺陷降级成了标签噪声问题。前者很难修后者可以用半监督和重加权来缓解。3.2 伪标签的生成与置信度过滤NISE 利用未点击样本的第一步是给它们生成伪标签。具体流程是先用有标签的点击样本训练一个初始模型然后用这个模型对未点击样本预测转化概率把概率较高的样本当作伪正样本概率较低的当作伪负样本。但这里有个关键细节不能全盘接受伪标签必须做置信度过滤。我的经验是设置一个双阈值区间比如预测概率大于 0.8 的才当伪正样本小于 0.2 的才当伪负样本中间 0.2 到 0.8 的样本暂时不参与训练或者只给很小的权重。这样做的理由是模型初期对未点击样本的预测本身就不准如果全用上错误会自我强化越训越偏。置信度过滤之后还要做类别平衡。未点击样本里伪负样本天然占多数如果直接混入会再次造成正负失衡。常见做法是对伪正样本做上采样或者对伪负样本做下采样让整体正负比维持在合理区间。3.3 一致性正则如何稳住训练过程光有伪标签还不够因为伪标签会随训练轮次变化容易导致训练不稳定。NISE 引入了一致性正则来稳住这个过程对同一个未点击样本施加两种不同的特征扰动比如随机丢弃部分特征、加轻微噪声要求模型对这两个版本的预测结果保持一致。这个机制的直觉很好理解如果一个样本的转化倾向是真实的那么轻微扰动不应该改变结论如果扰动后预测剧烈变化说明模型对这个样本本来就没把握它的伪标签不可信。一致性损失相当于给伪标签加了一道自检关卡把不稳定的样本自动降权。实操中一致性正则的权重需要仔细调。权重太大模型会过度关注无标签样本忽略有标签信号权重太小又起不到稳定作用。我一般从 0.1 开始试观察验证集上 CVR 的 AUC 和校准曲线再逐步调整。3.4 假负样本的识别与重加权前面提到未点击样本里混着假负样本点击样本里同样有延迟转化造成的假负样本。NISE 对这两类都做了处理核心手段是重加权对可能是假负的样本降低损失权重对确定的正负样本保持正常权重。识别假负样本有几个信号可以参考一是转化延迟分布如果某类商品的转化周期普遍较长那么近期点击未转化的样本大概率是假负二是用户活跃度活跃用户的未转化更可能是真未转化沉默用户的未转化更可能是假负三是模型预测概率预测转化概率高但标签为负的样本值得怀疑。把这些信号综合成一个置信度分数再映射成损失权重就能让模型在训练时心里有数不被假负样本带偏。这一步是 NISE 相比普通半监督方法更精细的地方也是它能在真实场景里跑出效果的关键。4. 落地实现的关键步骤与参数4.1 数据准备曝光样本的构造与特征对齐落地 NISE 的第一步是把数据从点击日志扩展到曝光日志。很多团队的数据管道只记录了点击事件未点击样本根本没落库这时候得先补数据采集。曝光日志需要包含用户 ID、商品 ID、曝光位置、曝光时间、上下文特征以及后续是否点击、是否转化的回传标签。特征对齐是个容易翻车的点。点击样本和未点击样本的特征来源可能不同比如点击样本有点击后停留时长这类行为特征未点击样本没有。如果直接混在一起训练模型会依赖这些只在点击样本里存在的特征导致对未点击样本的预测失真。解决办法是只用曝光时刻就能获取的特征把点击后行为特征单独作为一路输入或者干脆在未点击样本上做缺失填充并加一个缺失指示位。# 曝光样本构造的简化示意 def build_exposure_samples(click_log, exposure_log, conversion_log): # 以曝光日志为主表左连接点击和转化标签 df exposure_log.merge(click_log, on[user_id, item_id, exp_id], howleft) df df.merge(conversion_log, on[user_id, item_id, exp_id], howleft) # 未点击样本的点击后特征置空并标记缺失 df[is_clicked] df[click_time].notna().astype(int) df[is_converted] df[conversion_time].notna().astype(int) return df4.2 模型结构共享底层加双塔输出NISE 的模型结构一般采用共享底层加多任务输出的形式。底层是特征嵌入和几层全连接负责学习通用表示上层分出两个头一个预测点击概率一个预测转化概率。转化头的训练同时用到点击样本和未点击样本点击头只用于辅助。为什么要多任务因为点击和转化高度相关点击头的梯度能给底层表示提供额外监督相当于一种正则化。尤其是当转化正样本极少时点击信号能帮底层学到更稳的用户和商品表示。实测下来加点击辅助任务通常能让 CVR 的 AUC 提升 0.5 到 1 个百分点在稀疏场景下提升更明显。损失函数是加权和点击损失用全部曝光样本转化损失用点击样本加高置信度的未点击伪标签样本再叠加一致性正则项。三部分的权重需要联合调我通常让点击损失权重为 1转化损失权重为 1一致性项从 0.1 起调。4.3 训练流程预热、伪标签迭代、收敛判断训练不能一步到位得分成几个阶段预热阶段只用有标签的点击样本训练模型得到一个还不错的初始模型。这个阶段大概跑 3 到 5 个 epoch目标是让模型对点击样本的转化预测达到基本可用的水平。伪标签生成阶段用预热模型对未点击样本预测按双阈值筛选出高置信度的伪正、伪负样本。联合训练阶段把伪标签样本加入训练集开启一致性正则联合优化。每跑 1 到 2 个 epoch重新生成一次伪标签迭代 3 到 5 轮。收敛判断监控验证集上的 CVR AUC 和校准误差如 ECE。当 AUC 连续两轮不再提升或者伪标签的分布趋于稳定就可以停止。注意伪标签迭代不是越多越好。我踩过的坑是迭代到第 6、7 轮时模型开始过拟合伪标签里的噪声验证集指标反而下降。一般 3 到 5 轮是安全区间。4.4 评估指标别只看 AUC转化率预测的评估AUC 只是入门指标。真正上线要看的是校准质量和排序质量。校准质量用 ECE期望校准误差或可靠性曲线衡量因为 CVR 预估值会直接参与出价或排序打分如果预测 0.1 实际只有 0.02会导致出价虚高、亏损。排序质量除了 AUC还要看 GAUC按用户分组的 AUC和 Top-K 的转化密度。GAUC 能反映模型在单个用户内部的排序能力比全局 AUC 更贴近线上效果。Top-K 转化密度则直接对应把最好的位置给谁这个业务问题。指标含义关注场景AUC全局排序能力模型整体区分度GAUC用户内排序能力个性化推荐ECE预测校准误差出价、预算分配Top-K 转化密度头部位置的转化效率流量分配5. 实操中踩过的坑与应对5.1 伪标签置信度阈值设太松导致模型跑偏这是我最早踩的坑。一开始图省事把置信度阈值设成 0.5只要模型预测概率过半就收为伪正样本。结果第一轮迭代后验证集 AUC 掉了将近 2 个点。排查发现模型初期对未点击样本的预测普遍偏高大量真负样本被误收为伪正样本把决策边界往负样本方向推。后来改成双阈值 0.8/0.2并且对伪正样本做上采样、伪负样本做下采样指标才稳住。经验是阈值宁严勿松宁可少用一些未点击样本也不要引入错误标签。如果数据量实在不够可以先用较严的阈值跑几轮等模型变强后再逐步放宽。5.2 一致性正则权重过大压垮有标签信号一致性正则的权重是个敏感参数。我有一次把它设成 1.0想着多利用无标签数据总没错结果模型在点击样本上的拟合都变差了CVR 预测整体偏低。原因是无标签样本数量远大于有标签样本一致性损失在总损失里占了主导模型被带跑偏。正确的做法是让一致性项作为辅助权重控制在有标签损失的一个较小比例。我现在的习惯是从 0.05 开始每轮观察验证集指标逐步加到 0.2 左右一旦发现校准曲线变差就回调。5.3 未点击样本特征缺失引发的分布偏移未点击样本天然缺少点击后行为特征如果处理不当会造成训练集和线上服务时的特征分布不一致。我遇到过一次线上效果远差于离线的情况排查后发现是训练时未点击样本的停留时长特征被填了 0而线上服务时这个特征对点击用户是真实值模型学到的模式在线上对不上。解决办法有两个一是训练时对未点击样本的缺失特征加一个缺失指示位让模型显式知道这个特征不可用二是线上服务时对未点击路径也走同样的缺失填充逻辑保证一致性。这两步缺一不可。5.4 迭代轮次过多导致过拟合伪标签噪声伪标签迭代是把双刃剑。前几轮确实能提升指标但迭代到一定轮次后模型开始记住伪标签里的噪声验证集指标掉头向下。我做过一组对比实验迭代 3 轮时 AUC 最高5 轮持平7 轮明显下降。所以迭代轮次一定要配合早停。我的做法是每轮迭代后都在验证集上评估保存最优轮次的模型而不是用最后一轮的。另外每轮重新生成伪标签时可以适当提高置信度阈值让伪标签质量随模型变强而提升。6. 这套思路还能怎么扩展NISE 这套半监督利用未点击样本的框架本质上解决的是标签稀疏 无标签数据海量的问题这个模式在很多场景都能迁移。比如新用户冷启动新用户没有历史行为标签极少但他们的曝光样本是有的可以用同样的伪标签思路做冷启动 CVR 预估。再比如新品推荐新品转化数据稀疏但曝光充足也能套用。另一个扩展方向是把未点击样本的利用从转化预测延伸到多目标排序。现在的推荐系统往往同时优化点击、转化、停留时长、互动等多个目标未点击样本对每个目标都是无标签数据可以设计一个统一的多任务半监督框架让各目标共享无标签样本的表示学习。这样能进一步摊薄标注成本提升整体排序质量。还有一个值得尝试的点是把用户反馈的时序信息纳入半监督。用户的兴趣是随时间变化的一个未点击样本在曝光当时可能是负例但一周后用户可能就转化了。如果能建模这种延迟反馈把未来会转化的未点击样本提前识别出来对实时排序的价值会更大。这需要把时间维度的信息编码进伪标签生成过程是个有挑战但很有价值的方向。最后分享一个我在实际项目里的体会半监督方法的效果七分靠数据质量三分靠算法。未点击样本的采集是否完整、特征是否对齐、假负样本的识别是否准确这些数据层面的工作比调模型结构重要得多。我见过太多团队在模型上反复折腾却忽略了曝光日志根本没采全这个根本问题。把数据管道理顺再上 NISE 这类方法效果往往立竿见影。