最近做了个项目,在进行客诉场景的处理时候,前后有三个大版本的迭代。
1、离线批量预测模型
2、实时预测模型
3、离线未决案件预测
4、未决更新实时预测:TODO
本文主要介绍从离线批量预测模型升级到实时预测模型踩过的坑。
想要实现实时的风险预测,这就意味着特征需要进行实时处理。
如果有实时数仓那还比较庆幸,如果没有的话,那就有点悲催了,从头趟一遍发现坑有点深啊,比那啥海沟还要深,没错就是挂在嘴边,又叫不出名字的马里亚纳海沟。
不过经过梳理特征处理可以分成几个主要的模块,有一定的先后顺序。
所以整体方案如下:
1、离线加工特征,确定好每个特征的主键,进行模型训练,数据在odps中等同于hive平台
2、拆分出哪些是实时特征,哪些是离线特征(具体根据自己的业务情况来拆分关键时间点)
1)投保基础特征
2)投保后报案前的交互统计特征
3)实时计算特征
4)实时离线融合(简单的直接拼接特征,复杂点就是实时+离线特征加工出新的特征)
3、上面的1和2都可以通过离线的方式进行特征加工,2可能涉及到实时的数据,要么简化,要么趟坑
4、实时特征加工:采用flinksql作为数据处理中心,结构化数据+sql,相比纯python要简单
5、实时特征+离线特征融合
6、第5步的特征入库,方便回测,结果检验。
7、结果通过flink sink将数据写入rds,然后通过kafka触发预测模型
实时特征目前时效性没有要求很高,采用kafka进行消息传递,flinksql进行离线实时特征的融合,
实时模型通过微服务发布实例提供预测服务,定时消费卡夫卡的数据,进行结果预测。
数量链路:前端业务系统数据写入kafka->flinksql解析+维表查询(特征入库)->kafka->机器学习模型定时拉取最新消息->预测结果入库。
如果说特征简单点,这个模型就上线了,然后就用了,正常情况模型效果和离线也不会差到哪里去,模型效果回测没啥大的差异。
但是一旦特征复杂一些,模型效果回测不理想,你会进行线上数据对比,发现离线数据和实时数据差异有点大啊。
来来来小板凳排起了,罗列下存在的问题点:
1、上面讲到的每个特征对应的主键,你可要用心了,离线和实时要一致,不然发现可能发现哪哪不对(能自己写的自己来写)。
2、上面离线特征加工的时候,重要的时间节点别忘记了加限制,比如报案时间,结案时间,具体视业务情况而定,防止数据泄露
3、离线任务调度依赖太多,11点才出来结果。。。数据出来之后,覆盖更新的时候,还有实时数据过来,查询离线特征,此时数据也会导致不一致,采用update机制而不是truncate insert会更好些,可以采用贴源数据,或者是ods层数据进行加工,提升整体任务的调动优先级
4、ods-edw-cdm-adm任何一层的数据都可能和实时数据(开发通过业务系统数据查询拼接在一起通过kafka消息传过来的)不一致,目前想到两种方案:第一种方式在现有的数据基础上进行落库,前提是模型效果可以接受,然后积累数据专门重新训练一个针对实时版本的模型,第二种方式就是,同系统开发一起校验底层数据逻辑,逐一排查
5、为了简单起见,相对静态的标签通过离线加工,导致的差异,比如为了简单起见,进行关键时间节点假定的,比如假定明天会结案,假定明天会加V等,加工新特征依赖这些重要的时间节点。
6、如果特征包含当天的实时数据,比如历史报案次数,当天多条实时数据进来的这就更坑了,难道自己在维护一个当天的数据状态表,在通过查询拼接,但是上面的主键怎么办?
7、实时特征和离线特征计算出的特征,数据有差异,查一次难受一次,一定要把所有的特征入库(离线+实时+融合特征),离线模型也同样如此,后面专门写一篇文章讲讲实时特征可能遇到的坑,传送门:flinksql做近实时特征处理的坑_mtj66的博客,交流WX:SpringBreeze1104-CSDN博客。
8、模型训练的时候默认值填充和实时flinksql的默认值不一致,典型的操作离线特征空值为做处理,直接进行训练了,而实时特征由于存储或者传输的介质不一样,导致默认值有差异。
9、flinksql做特征处理时候,如果修改处理逻辑的时候有个坑,当时为了优化内存,加了时间窗口,watermark定义为kafka消息时间,这时候就不能指定范围消费kafka数据了,采用process time作为watermark参考时间,这时候容易产生数据堵塞,处理超时的情况,数据就会丢失,就需要增加窗口的延迟时间也就是等待时间,总之还是kafka消息逻辑太复杂导致的,简单的场景也不用太担心这个延迟。
假如你想把上面罗列的问题都解决掉,如果特征就那么几个还能忍忍,如果几十上百个字段,想理清楚,烦都烦死了,更别说彻底解决掉了。
重点来了:如何排查模型效果差异比较大的原因
1、评估实时模型效果,可以用真实的数据进行回测,也可以和离线模型进行对比,前提是离线模型是可靠的没有数据泄露等问题
2、直接对比数据,统计实时特征和离线特征的差异度,挨个排查解决。
3、如果数据还有微小的差异,但是模型效果差异很大,把不一致的特征找出来,然后逐个遍历这些特征,把离线模型的特征赋值给实时特征,然后对实时数据进行预测,观察离线模型的概率值和实时模型的概率值差异,找出概率值变化较大的特征值。
例如:
-- # pi_issue_age offline: 51.0 realtime: 51
-- # pi_last_complaint_interval offline: nan realtime: 0
-- ('pi_issue_age', 0.07448517860766668),
-- ('pi_last_complaint_interval', 0.014720293662137543),
pi_last_complaint_interval离线默认值是nan,而实时是默认填充0,某一列微小的差异就导致模型预测出来的风险概率值差异很大|0.0744-0.0147|。
上述问题重新走一遍,基本上就能解决99%的问题了,不信的话回测线上结果进行效果验证。
总结:
说是实时方案不如说是踩坑指南,整个过程自己从头到尾主导,且做好规划,考虑清楚再具体落地实施,特征比较少,而且没有那么多复杂的特征,能少踩很多坑。如果你是接手的项目,或者是有其他人同时参与的话,有些问题点没有沟通清楚,那你准备好吧,天坑来了。