机器学习算法线上部署方法

机器学习算法线上部署方法

本文由携程技术中心投递,ID:ctriptech。做者:潘鹏举,携程酒店研发BI经理,负责酒店服务相关的业务建模工做,主要研究方向是用机器学习实现业务流程自动化、系统智能化、效率最优化,专一于算法实践和应用。html

咱们常常会碰到一个问题:用了复杂的GBDT或者xgboost大大提高了模型效果,但是在上线的时候又犯难了,工程师说这个模型太复杂了,我无法上线,知足不了工程的要求,你帮我转换成LR吧,直接套用一个公式就行了,速度飞速,确定知足工程要求。这个时候你又屁颠屁颠用回了LR,从新训练了一下模型,内心默骂千百遍:工程能力真弱。前端

这些疑问,咱们之前碰到过,经过不断的摸索,试验出了不一样的复杂机器学习的上线方法,来知足不一样场景的需求。在这里把实践经验整理分享,但愿对你们有所帮助。(咱们的实践经验更可能是倾向于业务模型的上线流程,广告和推荐级别的部署请自行绕道)。java

首先在训练模型的工具上,通常三个模型训练工具,Spark、R、Python。这三种工具各有千秋,之后有时间,我写一下三种工具的使用心得。针对不一样的模型使用场景,为了知足不一样的线上应用的要求,会用不一样的上线方法。 


.python

1、总结来讲,大致会区分这三种场景,请你们对号入座,酌情使用

若是是实时的、小数据量的预测应用,则采用的SOA调用Rserve或者python-httpserve来进行应用;这种应用方式有个缺点是须要启用服务来进行预测,也就是须要跨环境,从Java跨到R或者Python环境。对于性能,基本上咱们用Rserver方式,针对一次1000条或者更少请求的预测,能够控制95%的结果在100ms内返回结果,100ms能够知足工程上的实践要求。更大的数据量,好比10000/次,100000/次的预测,咱们目前评估下来知足不了100ms的要求,建议分批进行调用或者采用多线程请求的方式来实现。linux

若是是实时、大数据量的预测应用,则会采用SOA,训练好的模型转换成PMML(关于如何转换,我在下面会详细描述),而后把模型封装成一个类,用Java调用这个类来预测。用这种方式的好处是SOA不依赖于任何环境,任何计算和开销都是在Java内部里面消耗掉了,因此这种工程级别应用速度很快、很稳定。用此种方法也是要提供两个东西,模型文件和预测主类;git

若是是Offline(离线)预测的,D+1天的预测,则能够不用考虑第一、2中方式,能够简单的使用Rscript x.R或者python x.py的方式来进行预测。使用这种方式须要一个调度工具,若是公司没有统一的调度工具,你用shell的crontab作定时调用就能够了。github

以上三种作法,都会用SOA里面进行数据处理和变换,只有部分变换会在提供的Function或者类进行处理,通常性都建议在SOA里面处理好,不然性能会变慢。redis

大概场景罗列完毕,简要介绍一下各不一样工具的线上应用的实现方式。 


.算法

2、如何转换PMML,并封装PMML

大部分模型均可以用PMML的方式实现,PMML的使用方法调用范例见:shell

jpmml的说明文档:GitHub - jpmml/jpmml-evaluator: Java Evaluator API for PMML; 
Java调用PMML的范例(PPJUtils/java/pmml at master · pjpan/PPJUtils · GitHub),此案例是咱们的工程师写的范例,你们能够根据此案例进行修改便可; 
Jpmml支持的转换语言,主流的机器学习语言都支持了,深度学习类除外; 
从下图能够看到,它支持R、python和spark、xgboost等模型的转换,用起来很是方便。

这里写图片描述 


.

3、接下来讲一下各个算法工具的工程实践

1.python模型上线:咱们目前使用了模型转换成PMML上线方法。

python-sklearn里面的模型都支持,也支持xgboost,而且PCA,归一化能够封装成preprocess转换成PMML,因此调用起来很方便; 
特别须要注意的是:缺失值的处理会影响到预测结果,你们能够能够看一下; 
用PMML方式预测,模型预测一条记录速度是1ms,能够用这个预测来预估一下根据你的数据量,总体的速度有多少。 
.

2.R模型上线-这块咱们用的多,能够用R model转换PMML的方式来实现。

这里我介绍另外一种的上线方式:Rserve。具体实现方式是:用SOA调用Rserve的方式去实现,咱们会在服务器上部署好R环境和安装好Rserve,而后用JAVA写好SOA接口,调用Rserve来进行预测;

java调用Rserve方式见网页连接:Rserve - Binary R server; 
centos的Rserve搭建方法见:centos -Rserve的搭建,这里详细描述了Rserve的搭建方式。 
Rserve方式能够批量预测,跟PMML的单个预测方式相比,在少数据量的时候,PMML速度更快,可是若是是1000一次一批的效率上看,Rserve的方式会更快;用Rserve上线的文件只须要提供两个:

模型结果文件(XX.Rdata); 
预测函数(Pred.R)。 
Rserve_1启动把模型结果(XX.Rdata)常驻内存。预测须要的输入Feature都在Java里定义好不一样的变量,而后你用Java访问Rserve_1,调用Pred.R进行预测,获取返回的List应用在线上。最后把相关的输入输出存成log进行数据核对。

Pred.R <- function(x1,x2,x3){ data <- cbind(x1,x2,x3) # feature engineering score <- predict(modelname, data, type = 'prob') return(list(score)) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

.

3.Spark模型上线-好处是脱离了环境,速度快。

Spark模型的上线就相对简单一些,咱们用Scala训练好模型(通常性咱们都用xgboost训练模型)而后写一个Java Class,直接在JAVA中先获取数据,数据处理,把处理好的数据存成一个数组,而后调用模型Class进行预测。模型文件也会提早load在内存里面,存在一个进程里面,而后咱们去调用这个进程来进行预测。因此速度蛮快的。

Spark模型上线,放在spark集群,不脱离spark环境,方便,须要本身打jar包; 
咱们这里目前尚未尝试过,有一篇博客写到了若是把spark模型导出PMML,而后提交到spark集群上来调用,你们能够参考一下:Spark加载PMML进行预测。 
4、只用Linux的Shell来调度模型的实现方法-简单粗暴

由于有些算法工程师想快速迭代,把模型模拟线上线看一下效果,因此针对离线预测的模型形式,还有一种最简单粗暴的方法,这种方法开发快速方便,具体作法以下:

写一下R的预测脚本,好比predict.R,是你的主预测的模型; 
而后用shell封装成xx.sh,好比predict.sh,shell里面调用模型,存储数据; 
predict.sh的写法以下:

# 数据导出 data_filename = xxx file_date = xxx result = xxx updatedt = xxx cd path hive -e "USE tmp_xxxdb;SELECT * FROM db.table1;" > ${data_filname}; # R脚本预测 Rscript path/predict.R $file_date if [ $? -ne 0 ] then echo "Running RScript Failure" fi # R预测的结果导入Hive表 list1="use tmp_htlbidb; load data local inpath 'path/$result' overwrite into table table2 partition(dt='${updatedt}');" hive -e "$list1"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

最后用Crontab来进行调度,很简单,如何设置crontab,度娘一下就行了。

>crontab -e ------------------------- ### 天天5点进行预测模型; 0 5 * * * sh predict.sh
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4



.

5、说完了部署上线,说一下模型数据流转的注意事项

区分offline和realtime数据,无论哪一种数据,咱们根据key和不一样的更新频次,把数据放在Redis里面去,设置不一样的key和不一样的过时时间; 大部分redis数据都会存放两个批次的数据,用来预防没法取到最新的数据,则用上一批次的数据来进行填充; 针对offline数据,用调度工具作好依赖,天天跑数据,并生成信号文件让redis来进行读取; 针对realtime数据,咱们区分两种类型,一种是历史+实时,好比最近30天的累计订单量,则咱们会作两步,第一部分是D+1以前的数据,存成A表,今天产生的实时数据,存储B表,A和B表表结构相同,时效性不一样;咱们分别把A表和B表的数据放在Redis上去,而后在SOA里面对这两部分数据实时进行计算; 模型的输入输出数据进行埋点,进行数据跟踪,一是用来校验数据,二来是用来监控API接口的稳定性,通常性咱们会用ES来进行log的查看和性能方面的监控; 任何接口都须要有容灾机制,若是接口超时,前端须要进行容灾,当即放弃接口调用数据,返回一个默认安全的数值,这点对于工程上很是重要。 以上就是咱们在模型部署的经验分享,欢迎你们来找我一块儿探讨相关工程上的最佳实践。

相关文章
相关标签/搜索