《深度学习推荐系统实战》 学习笔记 3月Day 29

306 阅读5分钟

23| 实战:如何用深度学习模型实现Sparrow RecSys的个性化推荐功能?

1. 模型特征工程

在“模型实战准备二”这一讲,我们就通过 Spark 处理好了 TensorFlow 训练所需的训练样本,并把 Spark 处理好的特征插入了 Redis 特征数据库,供线上推断使用。不熟悉这部分内容的同学,最好再复习一下相关内容,把这把武器装进自己的技能库。

2. 模型离线训练

为了使在线推荐尽可能准确,需要训练一个推荐模型,其中介绍了一些常用的深度推荐模型,它们的输入是特征向量,输出是用户对物品的喜好程度。实践中,可以使用 TensorFlow 实现这些模型,通过离线和在线评估来挑选最佳模型。作者以 NeuralCF 模型为例,实现了“猜你喜欢”的功能,并指出其他模型的上线方法与 NeuralCF 类似,需要载入不同的模型文件,并传入相应的特征输入。

3. 模型服务

模型服务在推荐系统中的作用,它是连接线上和线下环境的纽带,在离线训练好模型后,需要通过模型服务模块将推荐模型部署上线,以实现实时推荐排序。作者提到了几种主流的模型服务方法,包括“预存推荐结果”、“预训练 Embedding+轻量级线上模型”、“利用 PMML 转换和部署模型”以及“TensorFlow Serving”,由于本篇文章中的深度学习模型都是基于 TensorFlow 训练的,因此作者采用 TensorFlow Serving 作为模型服务的方式。

4. 推荐服务器内部逻辑实现

实现推荐系统中的“猜你喜欢”功能,不仅需要进行模型服务,还需要进行大量的准备工作,如获取候选集、构建召回层、获取和拼装特征等推荐逻辑。作者称推荐服务器为推荐系统的线上心脏,是所有线上模块的核心所在。在之前的“相似电影”功能中,已经实现了整套推荐逻辑,重点关注特征拼装和从推荐服务器内部请求模型服务的方法。最后,作者表示准备好了自己的技能库,准备打造“猜你喜欢”的推荐功能。

“猜你喜欢”推荐功能的技术架构

image.png 推荐系统涉及到的数据和模型部分以及推荐服务器部分。数据集经过 Spark 处理后,会生成特征部分存入 Redis,样本部分供 TensorFlow 训练使用。TensorFlow 训练出模型后,模型文件会导出并载入到 TensorFlow Serving 中,供推荐服务器调用。推荐服务器部分基于数据集生成候选电影集合,经过候选物品获取、召回层、排序层三步最终生成推荐列表,前端利用 HTML 和 JavaScript 展示给用户。作者表示计划在本篇文章中重点介绍推荐服务器排序层和 TensorFlow Serving 的实现。

排序层 +TensorFlow Serving 的实现

image.png

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

/**
 * 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));
    }
}

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

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
)

其次是模型的导入,导入命令非常简单就是 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 &

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


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

小结

今天我们通过实现“猜你喜欢”功能串联起了我们之前所有学过的知识。希望在你看到推荐结果的时候,有种“武功大成,驾轻就熟”的感觉。要知道,这里面所有的代码都是你曾经学习过的,这里面每个结果都是你通过自己的所学生成的。希望你能在这里为自己鼓掌,这是一个不小的里程碑。下面我们再重点总结一下今天实践用到的技术。首先,我们利用 Spark 对 MovieLens 原始数据进行了处理,生成了训练样本和特征,样本供 TensorFlow 进行模型训练,特征存入 Redis 供线上推断使用。在 TensorFlow 平台上,我们以 NeuralCF 模型为例,训练并导出了 NeuralCF 的模型文件。然后使用 TensorFlow Serving 载入模型文件,建立线上模型服务 API。推荐服务器的排序层从 Redis 中取出用户特征和物品特征,组装好 JSON 格式的特征数据,发送给 TensorFlow Serving API,再根据返回的预估分数进行排序,最终生成“猜你喜欢”的推荐列表。虽然我们实现了猜你喜欢的功能,但是课程进行到这里你一定会有一个疑问:我们的推荐结果到底是好还是坏呢?我们总不能总是人肉去查看结果好坏吧,这样效率又低,又不准确。没错,推荐系统的效果评估是有一套非常完整的评估体系的,别着急,从下一篇的模型评估篇开始,我们就会系统性地讲解推荐系统的评估方法,期待继续与你同行。

image.png image.png