一:综述
在通用推荐系统中,如何找到用户所需,可以被拆解为两部分,也就是matching 和 ranking,matching的好坏是能在全集中找到用户所需的候选,而ranking做的好坏直接决定用户触达所需内容/商品/商户的成本,可以减少用户的额外操作(比如翻页,下滑等)。ranking的核心问题就是点击率预估(pctr)。
随着DeepLearning技术的日渐成熟,越来越多的公司在pctr问题上,采用deep model取代浅层模型来进行任务落地。很多公司纷纷发表了paper,其中就有google/facebook等世界top互联网公司,本文所叙述的model离线训练思想源自于阅读谷歌公司在2016年6月24日发表的论文Wide & Deep Learning for Recommender Systems[引用1],如果在后续文章讲解中不能尽解此论文之奥妙,请各位看官大神指出。而在工程落地上同样采用了tensorflow体系中的成熟grpc框架tensorflow serving。谷歌敢于开源出引领业界的paper,代码,框架,系统,让天下码农共同学习。其格局之高令人敬佩。
作者在尝试将论文中思想实践到作者所致力于开发的短视频推荐系统rank部分,提高算法性能的过程中,发现网上对这方面的文章不是很多,作者也曾遇到一个问题翻遍stackoverflow,而不得解的苦恼,也曾遇到技术达人写的github而豁然开朗的愉悦。作者希望分享出一份包含离线模型训练,在线server选型一级如何构建的小资料,让致力于实战的算法朋友们规避我曾经走过的弯路,从而少走一些弯路。请记住,闭门造车永远不能推动技术的革新。多学习多share才是王道。
二:概要 1.实战之deep model离线训练与评估。
2.dnn model server提供技术方案一:基于thrift的rpc(python)。
3.dnn model server提供技术方案二:基于grpc的tf serving。
4.推荐系统sever对dnn model server的使用。
5.线上小流量实验效果分析。
三:正文(以及概要部分的介绍顺序)
该算法从读paper开始到上线完成截止,开发耗时,3周零4天(单人)。其中1.部分耗时一周,2.部分耗时一周后由于性能不符合要求改用3. 34两部分耗时一周零一天,最后三天用于线上server部署,添加负载均衡等。对于一名有一定经验的机器学习算法工程师来说,第一部分是最简单的,准备放在最后讲,优先讲2,3,4工程实践部分。所以本文主要讲概要第2部分,dnn model server 提供技术方案一:基于thrift的rpc。
基于引用1论文的model 训练方法被封装在了tensorflow的contrib.learn api中,属于tensorflow的高级api请参考https://www.tensorflow.org/api_docs/python/tf/contrib/learn,所以在这里我们的线上推荐系统(java)不能直接load,加载好的训练模型,java目前对tensorflow的支持仅限于低级别api,生态不是做的十分出色。在离线训练完模型后,根据这个情况,只能采用model server的方式,java client 调用这个model server,来完成打分排序。好处就是服务之间完全解耦,而坏处就是增加一层通信,会带来耗时的开销。关于apache thrift rpc框架的基本介绍,这里不做过多介绍。
我们希望搭建的流程图是如上图所示的,但是就在我代码全部写完,server搭建完成以为可以close这个项目的时候,发现自己还是太年轻了,下文详细叙述。我们参考tensor 官网(详细可以参见https://www.tensorflow.org/tutorials/wide_and_deep)给出的代码搭建model。代码截图如下:
然后类似于sklearn的方式,进行model.fit(train_data),进行model的训练,这个时候model 就已经存在上截图代码的model_dir里面了。在这个时候我们经期时就想一个问题,如果load这个model到内存,如果能有其它的那些开源平台那么简单粗暴就好了,在像加载低阶api训练出的model一样,尝试了几次后发现事与愿违,查询了一些资料后发现,tf高阶api的model load与低阶是完全不同的。心灰意冷之际,随便去stackoverflow,搜这个问题,发现有人说model.fit后,下一次只需要按上图代码构建model,而直接调用model.predict 就可以了,model会自动check model_dir里已经训练好的文件。在训练完model评估效果的时候,果然可以这样用。又在自己高兴不已,按图1搭建完server,测试性能的时候发现500个视频的单次打分,和2000个基本一样,耗时在800ms+,完全不可以接受,这个时候意识到,可能model.predict 函数是每次都去加载model,而不是图2,构建model的时候就已经加载入内存,这完全是一个令人沮丧而且不可以接受的消息。
所以我就详细的阅读了/python2.7/site-packages/tensorflow/contrib/learn/python/learn/estimators/estimator.py里面关于predict的实现,打出了耗时,期望自己能够改一下,每次都load model的这部分耗时,立时1.5天后宣告失败。这个时候我已经觉着自己这个项目无法在online部分上线了。就在又心情跌入谷底时。突然又看到了一些希望。预知后事如何,且看part2分析。
参考
引用1:Wide & Deep Learning for Recommender Systems(谷歌论文)
完成于20170825,如转载请注明出处