本次分享主要包括以下几个部分:
1. 业务背景;
2. 召回相关技术与实践;
3. 排序相关技术与实践;
4. 思考及未来规划。
1. 业务背景
底层页指在点击左侧双列 feed 流中点击一个视频(1 号)后继续滑动出现的视频(234 号)
在底层页推荐场景中除了需要考虑和主视频的相关性以外,还需要考虑上下文(用户对视频 234 的行为)。
底层页的整体框架如上图所示,当客户端发起推荐列表请求,服务端会依次做以下事情:
请求画像服务,得到描述用户兴趣的特征;
请求 Trigger,由若干个不同机制的 Trigger 分别得到不同的召回集;
合并召回结果,输入 rank 层做排序;
经过一些产品/业务策略的规则组成的曝光策略服务得到最终的视频 list,发给用户。
服务的底层,直接和线上服务打交道的,包括做向量相似度计算的 faiss,做缓存的 redis,做消息队列的 Hippo,还有一些数据分发服务。
再下面一层则是大数据计算平台 Hadoop,Spark,SparkStreaming,以及机器学习计算平台 Angel 和 Tensorflow。
2. 召回相关技术与实践
召回策略主要分为以下 4 个方向:
基于热门:在冷启动阶段,缺少用户行为的时候,用高质量视频做推荐;
基于属性:根据年龄,性别,地域等用户属性,不同属性的用户有不同的兴趣偏好;
基于内容: 根据视频的标题,标签,图片等等,找相似的视频;
基于行为:根据用户的点击/播放行为序列,建模计算相关的视频。
ICF 方法(基于物品的协同过滤)原理是比较两个视频观看过的用户列表,重合度越高则越相似。在计算协同过滤相似度时对原始公式做了以下优化:
考虑用户看两个视频相隔的时间,在分子上乘一个衰减系数,时间越长相关性越低;
考虑用户看视频的数量,在分母乘以衰减系数,对看大量视频的用户做降权;
不同的主 item 对应的其他 item 的 list 中分数的最大值可能差异很大,可以对每个主 item 做归一化处理。
表示学习的思路是类似 word2vec,为每个样本(通过 embedding)生成一个向量,再计算向量的相似度找到相似的样本。可以利用的数据例如视频封面,视频标题,视频标签和行为序列。
ImageEmbedding 召回因为样本比较少,做分类模型困难,所以采用预训练的方法。加载 Inception 模型,输入图像做前向计算,将 softmax 前的输出层取出来即可得到一个 embedding 向量,最后使用 faiss 找到最相似的向量,也就找到了最相似的图片。评估目前采用人工的方法,人工评估召回的 topN 图片中有几个是相似的。
Title/Tag Embedding 有两种方法:第一种是标准的 word2vec 模式,用自己的标题/标签数据训练一个词向量模型。这种方法的召回结果不太好,分析原因是数据量小。第二种是采用了公开词向量数据,这种用海量数据训练得到的预训练词向量模型,效果比第一种更好。
Network Embedding 召回也叫 Graph Embedding,有三种方式: 1. 矩阵分解: 效果不太好,用的比较少 2. 随机游走: 利用随机游走构造一些序列做 embedding 3.具体使用中最直接的方法是:把用户的播放列表当作 nlp 中的一个句子(每个视频作为一个单词)训练 word2vec。直接用 word2vec 会有一些问题,可以优化的方式包括:1. 对高低频的 item(视频)做过滤和降采样 2. 合理的划分 session(取多少天的数据)。
Network Embedding 常见的做法并不是先将样本直接构造成 skip-gram 的形式,而是先把行为序列构造成图的形式,然后针对每个节点进行随机游走,生成一些候选序列,再去做 Embedding 学习。这样做存在的问题 1:新的 item 缺少行为数据导致图稀疏,解决方案是将最近几个小时看的视频两两做全连接。问题 2 是热门视频:解决方案是对视频做聚类。
推荐系统的常规做法是分召回,排序两个阶段。原因是如果对全量数据(用户数*物品数)做排序,计算量可能太大,所以先用召回层减少候选集的大小。除非在某些特殊情况下,对全库做排序也许是可行的,如果物品的数量不是很大,比如只有几十/几百万,再把模型的特征减少。当候选池达到上亿甚至更多的时候就不可行了,尽管使用 embedding 方法可以近似选择全局最优,但是计算距离的方法比较单一。
高阶的方法是采用阿里提出的一种 tree-based deep match 的方法,核心的思想是要从全部候选池中找到用户感兴趣的 item,为了减少问题的规模,将候选集构建成树结构,只有叶子节点才是单个的 item,每个非叶子节点潜在表达了子孙 items。
第一步:将视频按照二级分类排序,使得相同二级类目的视频处在相邻的位置,所有视频组成一个 list。第二步:递归的将 list 一分为二得到左右子树,直到每个 list 只剩下一个或两个视频。这样就构建出了一个有层级结构的树。
将用户的历史行为序列和树中的目标节点做点积,经过深度神经网络之后得到用户对每个候选节点感兴趣的概率。
训练时正样本选择有播放行为的叶子结点和它的祖先。负样本有两种选择:(a)每层随机选择节点作为负样本,这样做的好处是结果的多样性好 (b)每层选择兄弟节点作为负样本,这样做的好处是和历史行为更匹配。完整的召回过程是自顶向下的依次对每个节点打分,选择 topk,遇到叶子节点就放入召回池,遇到非叶子节点就继续向下寻找。
树形结构的好处除了可以做全库检索,还会有更好的多样性。这样做更符合人脑的特点,人通常不会只对某一种类别的内容感兴趣,而是对不同的内容都或多或少的有兴趣。
最后总结一下:最初级的方法是基于统计的协同过滤系列,之后演化出进阶的 Embedding 系列之所以应用比较广很大程度上受益于 faiss 提高了向量相似度计算的效率,目前最前沿的是 TDM 这种全库查询的方式。
3. 排序相关技术与实践
接下来介绍排序模块,大致经历了 LR,Deep,Wide&Deep 三个阶段,其中 LR 模型暂时不做介绍。
深度模型目前采用了一种比较基础的架构。底层是 sparse feature id。接下来 embedding,每一列是一个 field,比如画像信息、上下文等等。然后 concat,经过全联接的隐藏层之后输出。DNN 模型的效果与 LR 相比没有很大提升,原因是低阶特征组合能力不足,但好处在对稀疏特征的表达能力有提升。
Wide&Deep 模型的 Wide 部分和 LR 的做法相同,所以克服了 DNN 模型的缺点,auc 相对 LR/DNN 有 1%的提升,不过依然依赖于人工做一些交叉特征。
Wide&DCN 模型是 2017 年谷歌提出来的,它的特点是加入了一个 cross 层做特征交叉,具体的交叉方式如公式所示:每一层的 Embedding 由上一层和第 0 层交叉,每一层中的每个元素的交叉由阶数确定,最终形成了多阶交叉的效果。离线 auc 和 W&D 相比提高 1%,而 DeepFM 和 W&D 相比提升不大。
最后在介绍一下工程方面的实践经验。排序的难点是要求实时,并且特征和样本的数量都很大。下面将会从样本数据,特征结构,离线训练,线上推断和模型调试五个方面分别介绍。
Tensorflow 有两种处理特征的方式:明文 vs 二进制(TFRecord)。明文的特点是可读性好,但是速度慢。二进制虽然速度快,但也存在一些问题,只支持三种格式的数据,而且 String 结构比较占用空间,解析速度也慢。
特征结构尝试过三种方式。第一种是明文形式,FeatureColumn 的速度非常慢,特征 ID 化方式比 FeatureColumn 快十倍,不论离线训练还是线上推断都是如此。后两种是特征 ID 的形式。
第一种是开放的特征 id,使用方便,只需要把特征做 hash,但缺点是 Tensorflow 底层 dense 结构无法支持。第二种是序列化特征 id,这种做法的缺点是序列化速度慢,好处是可以做特征预处理。
离线训练使用的是数据分布式模式,数据并行计算梯度。模型是集中式的,非分布式存储,每片数据计算的梯度使用同步方式更新模型。
线上推断有两种方式。一种是 TFServing,这种方式存在一些问题。因为加载模型和模型推断是采用同一个线程,所以在加载模型的时候会出现推断服务短暂阻塞,造成超时。TFServing 还会定时自动加载目录中的模型文件,如果模型有问题也会自动加载模型,这是我们不希望发生的。另外在模型加载初期会出现响应慢的现象,通常称为 WarmUp 问题。不过可以通过 BatchThread 提升计算效率。
还有一种方式是用 TensorflowAPI 进行推断,可以自行设置触发条件控制模型的加载,而不限制于一定要固定的时间间隔加载一次。另外还可以自行调用 session 函数进行并行推断。
在提高模型的训练效率方面,有不少可以尝试的优化点,比如 batchsize 的调整,Tensorflow 中 dataset api 中 cache 的使用,特征选择及 Embedding 调整,隐藏层个数及纬度的调整,样本降采样等等。使用 Tensorflow timeline 工具可以帮忙快速定位耗时函数,加速模型训练。
在提高模型的推断效率方面,可以优化线上特征数据拼接效率,及控制线程和 batch 之间的比例。
在提高效果方面,数据量越大越好,使用 tensorboard 关注实时 auc 和明文输出 bias/loss 等数据,尽早发现模型训练中的错误。
模型的演化过程大致经过了线性模型,非线性模型,兴趣模型这几个阶段。推荐和搜索业务的关注点是有一些不同的,推荐更关注对用户兴趣的描述,而搜索关注对 query 的理解。阿里的 DIN 和 DIEN 是大家公认对效果提升比较明显的。
4. 思考及未来规划
最后是一些思考和未来的规划。Embedding 方面计划讲将行为和内容融合到一起做 embedding,还有一种方式将用户行为构建成图,利用图卷积神经网络做 embedding 学习。另一方面是序列化数据的利用,用 LSTM/GRU 做序列化的 item 推荐,或者直接对序列化行为建模用户兴趣,这些方法时间复杂度高,工程挑战较大。利用 Bandit 算法去做用户兴趣探索是常用的一种做法,后续将会探索强化学习尤其深度强化学习在兴趣探索上的应用。
此外两个难点,一个是多任务学习,因为有的时候任务目标不仅仅是点击率,还需要提高停留时长等指标。另一个是多模态,把图片和视频数据如何用到召回中来。
作者介绍:
钱丁丁,腾讯高级研究员。Yoo 视频底层页视频排序技术负责人,带领团队从 0 到 1 搭建短视频排序技术体系,并实现了从浅层机器学习模型到深度模型的升级换代。毕业之后加入搜狗商业部门,负责无线搜索广告的排序算法工作。曾在腾讯网络媒体事业部,负责天天快报新闻推荐系统排序算法工作。
本文来自钱丁丁在 DataFun 社区的演讲,由 DataFun 编辑整理。
评论