【王喆-推荐系统】复习篇-Sparrow的个性化推荐功能

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 为了训练推荐模型,需要准备好模型所需的样本和特征。在进行模型线上推断的时候,推荐服务器也需要线上实时拼装好包含了用户特征、物品特征、场景特征的特征向量,发送给推荐模型进行实时推断。

一、清点技能库

“猜你喜欢”功能几乎会用到所有的推荐系统模块(如离线的特征工程、模型训练以及线上的模型服务和推荐逻辑的实现)。


image.png

1.1 模型特征工程

为了训练推荐模型,需要准备好模型所需的样本和特征。在进行模型线上推断的时候,推荐服务器也需要线上实时拼装好包含了用户特征、物品特征、场景特征的特征向量,发送给推荐模型进行实时推断。


之前通过 Spark 处理好了 TensorFlow 训练所需的训练样本,并把 Spark 处理好的特征插入了 Redis 特征数据库,供线上推断使用。


1.2 模型离线训练

为了在线上做出尽量准确或者说推荐效果尽量好的排序,需要在离线训练好排序所用的推荐模型。虽然之前学的深度推荐模型的结构各不相同,但它们的输入、输出都是一致的,输入是由不同特征组成的特征向量,输出是一个分数,这个分数的高低代表了这组特征对应的用户对物品的喜好程度。


Embedding MLP、Wide&Deep、NeuralCF、双塔模型、DeepFM 等几种不同的深度推荐模型,它们中的任何一个都可以支持“猜你喜欢”的排序功能。


其他模型的上线方法与 NeuralCF 几乎一致。唯一的区别是,对于不同的模型来说,它们在模型服务的部分需要载入不同的模型文件,并且在线上预估的部分也要传入模型相应的输入特征。


1.3 模型服务

推荐系统中连接线上环境和线下环境的纽带——模型服务和特征数据库。

在离线训练好模型后,为了让模型在线上发挥功能(做出实时的推荐排序),我们通过【模型服务】模块将推荐模型部署上线,和之前一样使用tensorflow serving。


1.4 推荐服务器内部逻辑实现

模型服务虽然可以做到“猜你喜欢”中电影的排序,但要进行排序,仍然需要做大量的准备工作,比如候选集的获取,召回层的构建,特征的获取和拼装等等。这些推荐逻辑都是在推荐服务器内部实现的。推荐服务器就像推荐系统的线上的心脏,是所有线上模块的核心。


这次关注之前没提到的特征的拼装,以及从推荐服务器内部请求模型服务 API 的方法。


二、"猜你喜欢"推荐功能的技术架构


image.png

图1 “猜你喜欢”功能的技术架构图

2.1 数据和模型部分

左上角是我们使用的数据集 MovieLens,它经过 Spark 的处理之后,会生成两部分数据,分别从两个出口出去:

(1)特征部分会存入 Redis 供线上推断时推荐服务器使用,

(2)样本部分则提供给 TensorFlow 训练模型。


2.2 模型服务

TensorFlow 完成模型训练之后,会导出模型文件,然后模型文件会载入到 TensorFlow Serving 中,接着TensorFlow Serving 会对外开放模型服务 API,供推荐服务器调用。


2.3 推荐服务器部分

在这部分里,基于 MovieLens 数据集生成的候选电影集合会依次经过候选物品获取、召回层、排序层这三步,最终生成“猜你喜欢”的电影推荐列表,然后返回给前端,前端利用 HTML 和 JavaScript 把它们展示给用户。


整个过程中,除了排序层和 TensorFlow Serving 的实现,其他部分在之前的实战中实现过。所以这次重点讲解推荐服务器排序层和 TensorFlow Serving 的实现(第三大点)。


三、排序层 +TensorFlow Serving 的实现

在推荐服务器中,经过召回层后,得到的几百量级的候选物品集,丢到排序层。在业界的实际应用中,往往交由评估效果最好的深度推荐模型来处理。


整个的排序过程可以分为三个部分:


准备线上推断所需的特征,拼接成 JSON 格式的特征样本;

把所有候选物品的特征样本批量发送给 TensorFlow Serving API;

根据 TensorFlow Serving API 返回的推断得分进行排序,生成推荐列表。

3.1 特征样本的拼接

首先,第一步的实现重点在于特征样本的拼接。


因为实践例子里,选用了 NeuralCF 作为排序模型,而 NerualCF 所需的特征只有 userId 和 itemId ,所以特征是比较好准备的。

如何拼接特征形成模型推断所需的样本:

代码参考:com.wzhe.sparrowrecsys.online.recprocess.RecForYouProcess

/**
 * call TenserFlow serving to get the NeuralCF model inference result
 * @param user              input user
 * @param candidates        candidate movies
 * @param candidateScoreMap save prediction score into the score map
 */
public static void callNeuralCFTFServing(User user, List<Movie> candidates, HashMap<Movie, Double> candidateScoreMap){
    if (null == user || null == candidates || candidates.size() == 0){
        return;
    }
    //保存所有样本的JSON数组
    JSONArray instances = new JSONArray();
    for (Movie m : candidates){
        JSONObject instance = new JSONObject();
        //为每个样本添加特征,userId和movieId
        instance.put("userId", user.getUserId());
        instance.put("movieId", m.getMovieId());
        instances.put(instance);
    }
    JSONObject instancesRoot = new JSONObject();
    instancesRoot.put("instances", instances);
    //请求TensorFlow Serving API
    String predictionScores = asyncSinglePostRequest("http://localhost:8501/v1/models/recmodel:predict", instancesRoot.toString());
    //获取返回预估值
    JSONObject predictionsObject = new JSONObject(predictionScores);
    JSONArray scores = predictionsObject.getJSONArray("predictions");
    //将预估值加入返回的map
    for (int i = 0 ; i < candidates.size(); i++){
        candidateScoreMap.put(candidates.get(i), scores.getJSONArray(i).getDouble(0));
    }
}

在代码中:


先把 userId 和 movieId 加入了 JSON 格式的样本中,然后再把样本加入到 Json 数组中。

接下来,我们又以 http post 请求的形式把这些 JSON 样本发送给 TensorFlow Serving 的 API,进行批量预估。

在收到预估得分后,保存在候选集 map 中,供排序层进行排序。

3.2 建立起 TensorFlow Serving API

第二步的重点在于如何建立起 TensorFlow Serving API


通过之前的模型服务部分,搭建起一个测试模型的 API 了。想要搭建起我们自己的 TensorFlow Serving API,只需要把之前载入的测试模型文件换成我们自己的模型文件就可以了。这里以 NerualCF 模型为例,看一看模型文件是如何被导出和导入的。


(1)模型的导出

首先是模型的导出。在 NeuralCF 的 TensorFlow 实现中,我们已经把训练好的模型保存在了 model 这个结构中,接下来需要调用 tf.keras.models.save_model 这一函数来把模型序列化。


下面的代码中,这一函数需要传入的参数有要保存的 model 结构,保存的路径,还有是否覆盖路径 overwrite 等等。


注意保存路径。可以看到在保存路径中加上了一个模型版本号 002,这对于 TensorFlow Serving 是很重要的,因为 TensorFlow Serving 总是会找到版本号最大的模型文件进行载入,这样做就保证了我们每次载入的都是最新训练的模型。详细代码参考 NeuralCF.py。

tf.keras.models.save_model(
    model,
  "file:///Users/zhewang/Workspace/SparrowRecSys/src/main/resources/webroot/modeldata/neuralcf/002",
    overwrite=True,
    include_optimizer=True,
    save_format=None,
    signatures=None,
    options=None
)

(2)模型的导入

其次是模型的导入,导入命令就是 TensorFlow Serving API 的启动命令,我们直接看下面命令中的参数。

docker run -t --rm -p 8501:8501     -v "/Users/zhewang/Workspace/SparrowRecSys/src/main/resources/webroot/modeldata/neuralcf:/models/recmodel"     -e MODEL_NAME=recmodel     tensorflow/serving &

这里面最重要的参数,就是指定载入模型的路径和预估 url,而载入路径就是我们刚才保存模型的路径:/Users/zhewang/Workspace/SparrowRecSys/src/main/resources/webroot/modeldata/neuralcf。但是在这里,我们没有加模型的版本号。这是为什么呢?因为版本号是供 TensorFlow Serving 查找最新模型用的,TensorFlow Serving 在模型路径上会自动找到版本号最大的模型载入,因此不可以在载入路径上再加上版本号。


除此之外,冒号后的部分“/models/recmodel”指的是 TensorFlow Serving API 在这个模型上的具体 url,刚才我们是通过请求 http://localhost:8501/v1/models/recmodel:predict 获取模型预估值的,请求连接中的 models/recmodel就是在这里设定的。


在正确执行上面的命令后,就可以在 Docker 上运行起 TensorFlow Serving 的 API 了。


3.3 获取返回得分和排序

最后,我们来看第三步的实现重点:获取返回得分和排序。


先来看一下 TensorFlow Serving API 的返回得分格式。它的返回值也是一个 JSON 数组的格式,数组中每一项对应着之前发送过去的候选电影样本,所以我们只要把返回的预估值赋给相应的样本,然后按照预估值排序就可以了。


参考 com.wzhe.sparrowrecsys.online.recprocess.RecForYouProcess 中全部排序层的代码。

{
    "predictions": [[0.824034274], [0.86393261], [0.921346784], [0.957705915], [0.875154734], [0.905113697], [0.831545711], [0.926080644], [0.898158073]...
    ]
}

如果已经正确建立起了 Redis 和 TensorFlow Serving API 服务,并且已经分别导入了特征数据和模型文件,我们就可以启动 Sparrow Recsys Server,查看“猜你喜欢”的结果了。用户 ID 为 6 的用户在 NerualCF 模型下的推荐结果(http://localhost:6010/user.html?id=6&model=nerualcf),注意通过在连接中设置 model 变量为 nerualcf,来决定产生结果的模型。


四、思维导图

4.1 基础模型


image.png

4.2 进阶模型


image.png


4.3 前沿模型


image.png

五、作业

推荐系统的特征预处理是一项很重要的工作,比如一些连续特征的归一化,分桶等等。那么这些预处理的过程,我们应该放在线上部分的哪里完成呢?是在 Tensorflow Serving 的部分,还是在推荐服务器内部,还是在离线部分完成?你有什么好的想法吗?


【答】推荐服务器内部专门开发特征加工模块,进行一些人工的处理。比如点击率特征,实际上“点击”会包含多种点击行为,各种行为如何融合,需要灵活配置。既不能放在离线存(更新不便),也不能放在tf serving里(逻辑多了太慢)

1、tf serving只负责简单的模型运算;

2、离线redis等负责通用特征数据的存储;

3、推荐系统服务器进行数据加工


线上服务篇的task2:

:image.png


六、课后答疑

(1)Sparrow项目代码中新增了pyspark推荐系统的工程实现部分,对于大数据量的特征工程处理,选择用scala还是python版的spark实现有没有什么建议?


【答】现实工作中建议最好还是用scala来维护,毕竟是spark原生支持的语言,真正的大数据工程师一般会使用scala。但是也不反对python来维护,跟其他python项目在一起维护会方便些。


spark+tf 正常算法工程师主要会这两个。实时计算和推荐引擎应该有其他的同事负责。如果这几个部分还没拆分开的话,可能你们还没有达到必须要用推荐的时候,可以将实时计算给忽略。都去做的话,就什么也不会精通,也只有在小公司里了。个人(ID:范思思)最近一段时间面试的结论,仅供参考。你可以什么都学过一点,但一定要有一个十分精通的技术,作为下一步发展的目标


(2)特征处理这部分,应该是离线计算好得到每个特征的map数据,在推荐服务器内部加载这些map数据,直接将原始特征映射成深度学习需要的向量,将得到的向量送入Tensorflow Serving得到推荐结果

如果在Tensorflow Serving做特征预处理的工作,会导致推荐服务的响应时间边长


【答】最好是可以在推荐服务器内部把特征都准备好,处理好。tf serving只做inference,不承担太多特征预处理压力。


(3)现在边缘计算或端智能,多大程度解决了用户特征更新的问题,端智能的应用前景如何?

【答】王喆大佬说看好边缘计算的发展,一直是近两年看好的方向。至于多大程度解决了特征更新的问题,觉得他们会一直共存。边缘计算永远也替代不了服务器端的特征更新设施。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
机器学习/深度学习 搜索推荐 算法
深度学习推荐系统架构、Sparrow RecSys项目及深度学习基础知识
深度学习推荐系统架构、Sparrow RecSys项目及深度学习基础知识
|
机器学习/深度学习 搜索推荐 算法
【王喆-推荐系统】模型篇-(task5)wide&deep模型
Wide&Deep是工业界中有巨大影响力的模型,如果直接翻译成中文是宽和深的模型,其模型结构如下所示:wide和deep让模型兼具逻辑回归和深度神经网络的特点。
851 0
【王喆-推荐系统】模型篇-(task5)wide&deep模型
|
机器学习/深度学习 搜索推荐 测试技术
【王喆-推荐系统】评估篇-(task2)推荐模型评估指标
准确率 (Accuracy) 是指分类正确的样本占总样本个数的比例。
944 0
【王喆-推荐系统】评估篇-(task2)推荐模型评估指标
|
机器学习/深度学习 存储 分布式计算
【王喆-推荐系统】线上服务篇-(task5)部署离线模型
(1)业界主流的模型服务方法有 4 种,分别是预存推荐结果或 Embeding 结果、预训练 Embeding+ 轻量级线上模型、利用 PMML 转换和部署模型以及 TensorFlow Serving。
773 0
【王喆-推荐系统】线上服务篇-(task5)部署离线模型
|
机器学习/深度学习 存储 开发框架
推荐系统[八]算法实践总结V1:淘宝逛逛and阿里飞猪个性化推荐:召回算法实践总结【冷启动召回、复购召回、用户行为召回等算法实战】
推荐系统[八]算法实践总结V1:淘宝逛逛and阿里飞猪个性化推荐:召回算法实践总结【冷启动召回、复购召回、用户行为召回等算法实战】
推荐系统[八]算法实践总结V1:淘宝逛逛and阿里飞猪个性化推荐:召回算法实践总结【冷启动召回、复购召回、用户行为召回等算法实战】
|
搜索推荐 算法 Python
使用Python3配合协同过滤算法(base on user,基于人)构建一套简单的精准推荐系统(个性化推荐)
个性化推荐可谓风生水起,Youtube,Netflix,甚至于Pornhub,这些在互联网上叱咤风云的流媒体大鳄无一不靠推荐系统吸引流量变现,一些电商系统也纷纷利用精准推荐来获利,比如Amzon和Shopfiy等等,精准推荐用事实告诉我们,流媒体和商品不仅仅以内容的传播,它还能是一种交流沟通的方式。
使用Python3配合协同过滤算法(base on user,基于人)构建一套简单的精准推荐系统(个性化推荐)
|
存储 SQL 机器学习/深度学习
【王喆-推荐系统】评估篇-(task5)Replay和Interleaving评估
A/B测试时流量不够用,需要排队进行自己的测试,拖慢实验的新思路和迭代优化模型的进度。 如何选择这么多种离线评估和在线评估测试方法。
301 0
【王喆-推荐系统】评估篇-(task5)Replay和Interleaving评估
|
消息中间件 机器学习/深度学习 缓存
【王喆-推荐系统】前沿篇-(task3)流处理平台Flink:实时推荐
ex:小明在刷抖音的足球视频,接着会继续推荐出相关视频,如果推荐系统没有实时抓住用户的兴趣点,推荐大妈广场舞的视频,小明可能会对该产品失去兴趣哈哈。
418 0
【王喆-推荐系统】前沿篇-(task3)流处理平台Flink:实时推荐
|
机器学习/深度学习 存储 自然语言处理
【王喆-推荐系统】特征工程篇-(task3)Embedding基础
(1)Word2vec 的研究中提出的模型结构、目标函数、负采样方法、负采样中的目标函数在后续的研究中被重复使用并被屡次优化。掌握 Word2vec 中的每一个细节成了研究 Embedding 的基础。
367 0
【王喆-推荐系统】特征工程篇-(task3)Embedding基础
|
机器学习/深度学习 分布式计算 搜索推荐
【王喆-推荐系统】开篇词
在所有业界巨头的推荐引擎都由深度学习驱动的今天,作为一名推荐系统从业者,我们不应该止步于: (1)不能满足于继续使用协同过滤、矩阵分解这类传统方法,而应该加深对深度学习模型的理解;加强对大数据平台的熟悉程度,培养结合业务和模型的技术直觉,提高我们整体的技术格局。
313 0
【王喆-推荐系统】开篇词