虽然 per-weight 策略解决了该问题,但是它仍然表现不佳。主要原因是:虽然它对罕见特征的学习率控制较好,但是它对常见特征的学习率控制较差。它太快的降低了常见特征的学习率到一个很小的值,在算法收敛到最优点之前训练就过早终止了。
7.在线训练框架
(1)在线训练框架最重要的是为模型提供在线学习的标注样本。点击行为比较好标记,但是“不点击”行为难以标记。因为广告并没有一个“不点击”按钮来获取不点击的信息。因此,如果一个曝光在一个时间窗内未发生点击行为,则我们标记该次曝光是未点击的。之所以要设定一个时间窗,是因为广告曝光和用户点击之间存在时间差。
给定一个曝光,我们需要等待一段时间来确认它是否被用户点击。如果等待时间内收到了曝光的点击信息,则该曝光标记为正样本。如果等待时间内未收到曝光的点击信息,则该曝光标记为负样本。
等待的时长需要精心选择: 如果时间太长则实时训练数据延迟较大,数据 freshness 较差。 同时,为了存储更长时间的曝光数据内存代价也较高。 如果时间太短则因为没有等到点击信息回传,部分正样本被误判为负样本。这会导致实时样本集的经验 CTR 比真实 CTR 偏低。这种经验CTR 的偏差也可以检测并矫正。 因此,需要在数据的 freshness 和点击覆盖率(能匹配上曝光的点击的数量占总点击数量之比) 之间平衡。 通过挑选合适的时长,可以降低经验的 CTR 偏差到百分之1以下,同时内存代价也可以接受。
(2)Facebook 在线训练框架
a.用户浏览 Facebook 时向 Ranker 模块发送一个广告请求,请求中包含 request ID 。
b.Ranker 模块根据在线模型的预测结果,向用户返回一个广告,同时在曝光实时数据流中增加一条曝光日志。 如果用户点击广告,则前端打点系统上报点击事件,在后台点击实时数据流中增加一条点击日志。
c.通过 Oneline Joiner 模块实时获取最近一个时间窗的曝光、点击日志,并拼接样本特征来构造训练集。 d.Trainer 模块根据构造的训练集执行在线训练,训练好的模型部署到线上供 Ranker 模块使用。
这会形成一个数据闭环,使得模型能够捕捉到最新的数据分布。
(3)在线训练需要增加对实时训练数据的异常保护。
假设实时训练数据出现问题(如:前端打点上报出现异常、Online Joiner 工作异常等),导致大量的点击数据丢失。那么这批实时训练样本存在缺陷,它们的经验 CTR 非常低甚至为 0 。
如果模型去学习这样一批样本,则模型会被带偏:对任何测试样本,模型都会预测出非常低、甚至为零的点击率。 根据广告点击价值 eCPM = BID x pCTR,一旦预估点击率 pCTR 为零则广告的 eCPM 为零。那么这些广告几乎没有竞争力,竞争失败也就得不到曝光机会。
因此需要增加实时训练数据的异常检测机制。如:一旦检测到实时训练数据的分布突然改变,则自动断开在线训练流程。
8.优化技巧
(1)子树规模
在 GBDT-LR 模型中,子树的数量越大模型表现越好,但是计算代价、内存代价越高。 但是随着子树的增多,每增加一棵子树获得的效益是递减的。这就存在平衡:新增子树的代价和效益的平衡。
(2)特征数量
在 GBDT-LR 模型中,样本特征越大模型表现越好,但是计算代价、内存代价越高。 但是随着特征的增多,尤其是无效特征的增多,每增加一个特征获得的效益是递减的。这就存在平衡:新增特征的代价和效益的平衡。
为衡量特征数量的影响,我们首先对特征重要性进行排序,然后考察 topK 重要性特征的效果。 可以通过 Boosting Feature Importance 来衡量特征重要性。有三种度量方法(如 XGBoolst/LightGBM ): a.weight:特征在所有子树中作为分裂点的总次数; b.gain:特征在所有子树中作为分裂点带来的损失函数降低总数; c.cover:特征在所有子树中作为分裂点包含的总样本数
(3)降采样
Facebook 每天的广告曝光量非常大。即使是每个小时,数据样本也可能上亿。在线学习需要对样本进行采样来降低数据量,从而提升训练速度。
有两种降采样技术:
a.均匀降采样:所有样本都以同一个概率$p_{sample}$来随机采样。