“清点技能库”,看看我们已有的知识储备有哪些
特征工程、模型离线训练、模型服务、推荐服务器逻辑这四大部分的技能点。
1. 模型特征工程
特征工程是所有机器学习项目的起点,咱们的推荐模型也不例外。为了训练推荐模型,我们需要准备好模型所需的样本和特征。此外,在进行模型线上推断的时候,推荐服务器也需要线上实时拼装好包含了用户特征、物品特征、场景特征的特征向量,发送给推荐模型进行实时推断。
2. 模型离线训练
具体实践的时候,我们在 TensorFlow 平台上实现了 Embedding MLP、Wide&Deep、NeuralCF、双塔模型、DeepFM 等几种不同的深度推荐模型,它们中的任何一个都可以支持“猜你喜欢”的排序功能。
3. 模型服务
在离线训练好模型之后,为了让模型在线上发挥作用,做出实时的推荐排序,我们需要通过模型服务的模块把推荐模型部署上线(13课)
4. 推荐服务器内部逻辑实现
模型服务虽然可以做到“猜你喜欢”中电影的排序,但要进行排序,仍然需要做大量的准备工作,比如候选集的获取,召回层的构建,特征的获取和拼装等等。这些推荐逻辑都是在推荐服务器内部实现的。推荐服务器就像推荐系统的线上的心脏,是所有线上模块的核心。
“猜你喜欢”推荐功能的技术架构
排序层 +TensorFlow Serving 的实现
整个的排序过程可以分为三个部分:
准备线上推断所需的特征,拼接成 JSON 格式的特征样本;
把所有候选物品的特征样本批量发送给 TensorFlow Serving API;
根据 TensorFlow Serving API 返回的推断得分进行排序,生成推荐列表。
第一步的实现重点在于特征样本的拼接
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));
}
}
第二步的重点在于如何建立起 TensorFlow Serving API
在 NeuralCF 的 TensorFlow 实现中,我们已经把训练好的模型保存在了 model 这个结构中,接下来需要调用 tf.keras.models.save_model 这一函数来把模型序列化。
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 总是会找到版本号最大的模型文件进行载入
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]...
]
}
详细的过程你也可以参考 com.wzhe.sparrowrecsys.online.recprocess.RecForYouProcess 中全部排序层的代码