目录
分布式机器学习系统
- 百万日活 - 通常单机
- 千万日活 - 单机凑活
- 超过千万 - 单机通常搞不定,需要分布式
随机坐标 VS 随机梯度
随机梯度用的比较多,也更加稳定,收敛性好。
同步异步:在收敛性和速度取折衷
实时化技术升级
- 新item上线怎么办
- 拿到实时的item的曝光和点击数据(实时特征)
- 这一时间段的人群分布和上一时间段不一样怎么办
- 让模型能够快速学习并且表现出,基于一个时间段的特定用户行为,(模型参数可能会有较大的变化)
- 没有任何数据的新场景上线怎么办
- 利用相关商品的数据做冷启动模型上线保证业务效果
- 找一个相似的场景借鉴过来
客户端 VS 服务端
- 客户端:例如手机App;服务端:通常感受不到,server
- 客户端可以传给服务端统计特征,实时特征(用户session行为)和用户embedding,目前主要采用这一种
- 服务端可以传给客户端特征,在客户端进行模型训练
模型的演化历史
- 离线打分:模型离线训练,对所有用户打分,放在hbase等待被调用
- 离线训练,在线打分:模型T + 1离线训练,在线TF serving,通过hbase查询用户特征,对请求的用户打分
- 离线训练,在线打分,增量更新:模型T+1离线训练,每天只拿增量数据更新,隔断时间全量更新,在线TF serving,通过hbase查询用户特征,对请求的用户打分
- 近线训练,在线打分:模型T+h离线训练,在线TF serving,通过hbase查询用户特征,对请求的用户打分
- 在线训练,在线打分:模型T+s在线实时流训练,在线TF serving,通过hbase查询用户特征,对请求的用户打分
在线学习
- 实时数据流(特征+label),样本拼接,label Agg(聚合)
- 模型训练,优化器,validation,样本回流
- 在线部署,serving
实时数据流
离线样本
离线数据主要来源于hive,样本产生逻辑包括
- 依据特征快照(算法当时查询到的特征,模拟打分现场)或者独立特征表(离线特征)获得特征
- 依据数据中间层清洗出label口径
- 依据样本周期join特征和label
实时特征
流处理框架:Spark Streaming,flink:能够进行一些简单的统计类特征的计算,比如一个物品在该时间窗口内的曝光次数,点击次数
离线特征快照:HDFS to HBase
离线的时候,一般依赖离线的数据中间层;在线则是依赖在线的数据中间层
- 埋点层
- 中间层
- 业务层
- 维表
在线的一些问题
- 过拟合:算子层做一些优化,会倾向与前一段时间的特征,不那么泛化
- 模型的size会越来越大,会影响线上服务,有时会进行特征裁剪,ftrl极大优化数据的稀疏性
- T+s的抖动问题:确实会抖动的很厉害,线上会有一些机制来防止
- 控制模型更新:auc ,达不到某个阈值不更新
- 监控特征,监控特征与前面更新的情况,不让其与前段时间的差别特别夸张
- 更底层的,算子上控制
- 线上多做监控
数据的消费和反压
流数据的消费可以认为是一个管道. 每一个节点都在消费上一个节点产出的数据, 只有当所有的数据, 流速一致的时候, 才会正常.
如果有的节点发放速度过快, 消费速度过慢, 则会形成反压; 反 之, 则是资源浪费. 并发度的调节, 至关重要.
label 聚合
时间窗口
对于 ctr 或者 cvr 的估计, 我们在离线一般是使用确定的口径消费. 在线, 我们则需要时间窗口的概念(时间窗口的大小:正样本在该窗口的被点击占比能达到整个正样本的70-80%那么这个时间窗口就比较合适了,不需要在增加了,时间窗口加大也会对内存产生压力,毕竟通常聚合都是在内存上操作的).
在线 union 的逻辑,还需要再看一下1:10
通过一个 HashMap, 时间戳和主键. 另有一个 Queue, 存时间戳. 还有一个 hbase 后端, 存储主键和具体 Row.每次检测时间戳是否过期, 过期则取出, 负样本下发.正样本直接下发.
直接采样,可以理解为时间窗口为0
根本不等,无论正负样本都直接用,极大的降低了内存的压力,问题是label不太准确,在线训练【1、实时性;2、正样本加权来修正,由于正样本被当成负样本的情况相较于时间窗口占比更多,所以权重也可以相应加大】
回撤和补偿
如果在时间窗口中没有点击, 那么我们怎么去减少影响?
- 回撤机制: 对于已经下发的负样本撤回, 或者进行修正,不太好做,下发即训练
- 补偿机制: 对于已经下发的负样本后面来的正样本, 重新下发, 并且对于此类样本补偿权重(例如将其权重加大到5),尽量抵消之前错误当成负样本训练对梯度的影响。
采样方式
- 维持一定的正负样本的比例,实现:负样本维护一个池子,每来一个正样本就从池子里按先前设定的比例随机抽取负样本
- 重要性采样:
样本拼接
离线如何做样本拼接? 我们通过 Join, Left Join 等.
在线的 join 机制比较复杂, 一般只能用 Join(双流join,join不上就先等着暂时不下发), 不用 Left Join(join 不上,不等直接下发). 这也是为什么用 label union 的原因.
流式计算和消息队列本质上差不太多
在线模型训练
增量训练和冷启动
在线学习有两种模型的载入方式:从0载入和从已经训练好的模型载入。
每一个batch积累数据,然后进行增量训练。树模型不太适合在线学习,因为树模型计算增益、信息熵等都是用全量数据做的,在线学习的数据不断的进行更新迭代,这个时间的最优分裂点未必是下一个时间段最优的,即这个分裂点不一定是全局可用的,此时若想要改变分裂点,则树从头到尾都要发生变化,和重新训练模型没区别;深度学习的batch训练方法很合适。
模型的稀疏性
在线学习的稀疏性特征
模型体积和占用内存
若使用SGD的方式进行模型更新,相比batch的方式,容易产生大量的小权重的特征,这就增大了模型部署和更新的难度。
Lasso、GroupLasso、SparseGroupLasso(Lasso和GroupLasso结合起来)
模型的局部更新
降低训练效率低的部分的更新频率,提高训练效率高的部分的跟新频率
案例
- GBDT+LR:天级别更新GBDT,在线训练LR
- Embedding:天级别更新Embedding,在线训练其他部分;Embedding部分参数比较多【字典长度*Embedding维度】;embedding需要用全量数据构图。
在线学习:实时性和精度的取舍
样本回流机制
离线训练,我们经常在数据量比较小的时候,会跑去多个epoch的模型,而在线由于是数据流作业没数据过去了就没了,无法进行第二次训练。
为此我们实现了样本回流机制,在模型训练中,定义什么样的样本可以回流;在外部,对于需要回流的样本写入实时刘里面,在实时数据流里面,进行选择。
validation机制
前向计算,后向求导。在计算完求导前做validation评估auc;
优点:
- 能拿到更快速的数据
- 不需要分裂出单独的样本做validation
- 不会有样本泄漏(因为这一批样本只参与了计算,还没参与梯度更新,参数还是之前的参数)
缺点:
- auc是状态性auc;b1->auc1->b2->auc...->bn->aucn;因为静态导出,此时导出的不是bn的结果,而是他之前的auc的结果,这边还需要看一下。
paramterServe看李沐大神的paper
FTRL