目录
什么是 Embedding
Embedding
- 形式上讲,Embedding 就是用一个低维稠密的向量 “表示” 一个对象。Embedding 向量能够表达相应对象的某些特征,同时向量之间的距离反映了对象之间的相似性
- 例如, 如果对电影进行 Embedding, 那么 Embedding(复仇者联盟) 和 Embedding(钢铁侠) 在 Embedding 向量空间内两点之间的距离就应该很近,而 Embedding(复仇者联盟) 和 Embedding(乱世佳人) 的距离会相对远
- 同理,如果在电商领域对商品进行 Embedding, 那么 Embedding(键盘) 和 Embedding(鼠标) 的向量距离应该比较近,而 Embedding(键盘) 和 Embedding(帽子) 的距离会相对远
Embedding 技术对于深度学习推荐系统的重要性
- (1) 推荐场景中大量使用 one-hot 编码对类别、 i d id id 型特征进行编码,导致样本特征向量极度稀疏,因此几乎所有深度学习推荐模型都会由 Embedding 层负责将高维稀疏特征向量转换成低维稠密特征向量
- (2) Embedding 本身就是极其重要的特征向量。相比 MF 等传统方法产生的特征向量,Embedding 的表达能力更强,特别是 Graph Embedding 技术被提出后,Embedding 几乎可以引入任何信息进行编码,使其本身就包含大量有价值的信息。在此基础上,Embedding 向量往往会与其他推荐系统特征连接后一同输入后续深度学习网络进行训练
- (3) Embedding 对物品、用户相似度的计算是常用的推荐系统召回层技术。在局部敏感哈希 (Locality-Sensitive Hashing) 等快速最近邻搜索技术应用于推荐系统后,Embedding 更适用于对海量备选物品进行快速 “初筛”,过滤出几百到几千量级的物品交由深度学习网络进行 “精排”
Item2vec – Word2vec 在推荐系统领域的推广
- 如果从 Embedding 的角度看待矩阵分解模型,则用户隐向量和物品隐向量就是一种用户 Embedding 向量和物品 Embedding 向量
- 由于 Word2vec 的流行,越来越多的 Embedding 方法可以被直接用于物品 Embedding 向量的生成,而用户 Embedding 向量则更多通过行为历史中的物品 Embedding 平均或者聚类得到。利用用户向量和物品向量的相似性,可以直接在推荐系统的召回层快速得到候选集合,或在排序层直接用于最终推荐列表的排序。正是基于这样的技术背景,微软于 2016 年提出了计算物品 Embedding 向量的方法 Item2vec
Item2vec 的基本原理
- 相比 Word2vec 利用 “词序列” 生成词 Embedding。Item2vec 利用的 “物品序列” 是由特定用户的浏览、购买等行为产生的历史行为记录序列。假设一个长度为
K
K
K 的用户历史记录为
w
1
,
.
.
.
,
w
K
w_1,...,w_K
w1,...,wK,类比 Word2vec (Skip-gram), Item2vec 的优化目标为
1 K ∑ i = 1 K ∑ j ≠ i K log p ( w j ∣ w i ) \frac{1}{K}\sum_{i=1}^K\sum_{j\neq i}^K\log p(w_j\mid w_i) K1i=1∑Kj=i∑Klogp(wj∣wi)可见,Item2vec 与 Word2vec 唯一的不同在于,Item2vec 摒弃了时间窗口的概念,认为序列中任意两个物品都相关 (假设给定物品集中的物品都是相似的),因此在 Item2vec 的目标函数中可以看到,其是两两物品的对数概率的和,而不仅是时间窗口内物品的对数概率之和 - 在优化目标定义好之后,Item2vec 剩余的训练过程和最终物品 Embedding 的产生过程都与 Skip-gram 完全一致
“广义” 的 Item2vec
- 广义上讲,任何能够生成物品向量的方法都可以称为 Item2vec。典型的例子是曾在百度、Facebook 等公司成功应用的双塔模型
在广告场景下的双塔模型中,广告侧的模型结构实现的其实就是对物品进行 Embedding 的过程。下面将广告侧的模型结构称为 “物品塔”。那么,“ 物品塔” 起到的作用本质上是接收物品相关的特征向量,经过物品塔内的多层神经网络结构,最终生成一个多维的稠密 Embedding 向量
Item2vec 方法的特点和局限性
- Item2vec 作为 Word2vec 模型的推广,理论上可以利用任何序列型数据生成物品的 Embedding 向量, 这大大拓展了 Word2vec 的应用场景。广义上的 Item2vec 模型其实是物品向量化方法的统称,它可以利用不同的深度学习网络结构对物品特征进行 Embedding 化
- Item2vec 方法也有其局限性,因为只能利用序列型数据,所以 Item2Vec 在处理互联网场景下大量的网络化数据时往往显得捉襟见肘,这就是 Graph Embedding 技术出现的动因
Graph Embedding – 引入更多结构信息的图嵌入技术
图结构
- Item2vec 是建立在 “序列” 样本 (e.g. 用户行为序列) 的基础上的。而在互联网场景下,数据对象之间更多呈现的是图结构。典型的场景是由用户行为数据生成的物品关系图,以及由属性和实体组成的知识图谱 (Knowledge Graph)
- 在面对图结构时,传统的序列 Embedding 方法就显得力不从心了。在这样的背景下,Graph Embedding 成了新的研究方向,并逐渐在深度学习推荐系统领域流行起来
Graph Embedding
- Graph Embedding 是一种对图结构中的节点进行 Embedding 编码的方法。最终生成的节点 Embedding 向量一般包含图的结构信息及附近节点的局部相似性信息
- 下面就介绍几种主流的 Graph Embedding 方法和它们之间的区别与联系
DeepWalk – 基础的 Graph Embedding 方法
- DeepWalk 的主要思想是在由物品组成的图结构上进行随机游走,产生大量物品序列,然后将这些物品序列作为训练样本输入 Word2vec 进行训练,得到物品的 Embedding。因此,DeepWalk 可以被看作连接序列 Embedding 和 Graph Embedding 的过渡方法
- (1) 图 (a) 是原始的用户行为序列
- (2) 图 (b) 基于这些用户行为序列构建了物品关系图。可以看出,物品 A A A 和 B B B 之间的边产生的原因是用户 U 1 U_1 U1 先后购买了物品 A A A 和物品 B B B。如果后续产生了多条相同的有向边,则有向边的权重被加强
- (3) 图 (
c
c
c) 采用随机游走的方式随机选择起始点,重新产生物品序列。随机游走的跳转概率为
其中 ε \varepsilon ε 是物品关系图中所有边的集合, N + ( v i ) N_+(v_i) N+(vi) 是节点 v i v_i vi 所有的出边集合, M i j M_{ij} Mij 是节点 v i v_i vi 到节点 v j v_j vj 边的权重
- (4) 将这些物品序列输入图 (d) 所示的 Word2vec 模型中,生成最终的物品 Embedding 向量
Node2vec – 同质性和结构性的权衡
- Node2vec 通过调整随机游走权重的方法使 Graph Embedding 的结果更倾向于体现网络的同质性 (homophily) 或结构性 (structural equivalence)
- “同质性” 指的是距离相近节点的 Embedding 应尽量近似。为了表达 “同质性”,需要让随机游走的过程更倾向于 DFS, 因为 DFS 更有可能通过多次跳转,游走到远方的节点上,但无论怎样,DFS 的游走更大概率会在一个大的集团内部进行,这就使得一个集团或者社区内部的节点的 Embedding 更为相似,从而更多地表达网络的 “同质性”
- “结构性” 指的是结构上相似的节点的 Embedding 应尽量近似。例如下图中节点
U
U
U 和节点
s
6
s_6
s6 都是各自局域网络的中心节点,结构上相似,其 Embedding 的表达也应该近似。为了使 Graph Embedding 的结果能够表达网络的 “结构性”,在随机游走的过程中,需要让游走的过程更倾向于 BFS , 因为 BFS 会更多地在当前节点的邻域中游走遍历,相当于对当前节点周边的网络结构进行一次 “微观扫描”。当前节点是 “局部中心节点”,还是 “边缘节点”,或是 “连接性节点”,其生成的序列包含的节点数量和顺序必然是不同的,从而让最终的 Embedding 抓取到更多结构性信息
- 网络的同质性和结构性在推荐系统中可以被很直观的解释。同质性相同的物品很可能是同品类、同属性,或者经常被一同购买的商品,而结构性相同的物品则是各品类的爆款、各品类的最佳凑单商品等拥有类似趋势或者结构性属性的商品。毫无疑问,二者在推荐系统中都是非常重要的特征表达。由于 Node2vec 的发掘不同图特征的能力,甚至可以把不同 Node2vec 生成的偏向 “结构性” 的 Embedding 结果和偏向 “同质性” 的 Embedding 结果共同输人后续的深度学习网络,以保留物品的不同图特征信息
控制 BFS 和 DFS 的倾向性
- Node2vec 重新定义了节点间的跳转概率。下图所示为 Node2vec 算法已经从节点
t
t
t 跳转到了节点
v
v
v,并正在估计从节点
v
v
v 跳转到周围各点的跳转概率
从节点 v v v 跳转到下一个节点 x x x 的概率为
π v x = α p q ( t , x ) ⋅ w v x \pi_{vx}=\alpha_{pq}(t,x)\cdot w_{vx} πvx=αpq(t,x)⋅wvx其中 w v x w_{vx} wvx 是边的权重, α p q ( t , x ) \alpha_{pq}(t,x) αpq(t,x) 的定义为
其中 d t x d_{tx} dtx 表示节点 t t t 和节点 x x x 之间的最短距离,只可能在 { 0 , 1 , 2 } \{0,1,2\} {0,1,2} 中取值。可见,参数 p p p 和 q q q 共同控制着随机游走的倾向性
- 参数 p p p 被称为返回参数 (return parameter),它控制着随机游走时返回上一个节点的概率,将 p p p 设为一个较大的值 ( > max ( q , 1 ) >\max(q,1) >max(q,1)) 可以较少地在连续两步内采样到同一个节点,这有助于鼓励采样的探索性以及避免采样的 2-hop redundancy。而将 p p p 设为一个较小的值 ( < min ( q , 1 ) <\min(q,1) <min(q,1)) 会使游走时经常会回到上一个节点,从而使游走过程局限在起点附近。因此, p p p 越小,Node2vec 就更注重表达网络的结构性
- 参数 q q q 被称为进出参数 (in-out parameter),它用来区分 “inward” 和 “outward” 节点。如果 q > 1 q>1 q>1,那么随机游走就倾向于选择靠近 t t t 的节点,也更接近 BFS。如果 q < 1 q<1 q<1,那么随机游走就倾向于选择远离 t t t 的节点,也更接近 DFS。因此, q q q 越小,Node2vec 就更注重表达网络的同质性
实验结果
- Node2vec 这种灵活表达同质性和结构性的特点也得到了实验的证实,通过调整参数
p
p
p 和
q
q
q 产生了不同的 Embedding 结果。上面的图就是 Node2vec 更注重同质性的体现,可以看到距离相近的节点颜色更为接近,下面的图则更注重体现结构性,其中结构特点相近的节点的颜色更为接近
EGES – 阿里巴巴的综合性 Graph Embedding 方法
- EGES (Enhanced Graph Embedding with Side Information) 的基本思想是在 DeepWalk 生成的 Graph Embedding 基础上引入补充信息 (side information)
冷启动问题
- 单纯使用用户行为生成的物品相关图,固然可以生成物品的 Embedding,但是如果遇到新加入的物品,或者没有过多互动信息的 “长尾” 物品,则推荐系统将出现严重的冷启动问题
补充信息 Embedding 向量
- 为了使 “冷启动” 的商品获得 “合理” 的初始 Embedding, 阿里巴巴团队通过引入更多补充信息来丰富 Embedding 信息的来源,从而使没有历史行为记录的商品获得较合理的初始 Embedding
- 生成 Graph Embedding 的第一步是生成物品关系图,通过用户行为序列可以生成物品关系图,也可以利用 “相同属性” “相同类别” 等信息建立物品之间的边,生成基于内容的知识图谱。而基于知识图谱生成的物品向量可以被称为补充信息 Embedding 向量。当然,根据补充信息类别的不同,可以有多个补充信息 Embedding 向量
融合一个物品的多个 Embedding 向量
- 最简单的方法是加入平均池化层,将不同 Embedding 平均起来
- 为了防止简单的平均池化导致有效 Embedding 信息的丢失,阿里巴巴在引入注意力机制,对每个 Embedding 加上了权重
a
i
a_i
ai,然后将加权平均后的 Embedding 向量输入 softmax 层,通过梯度反向传播求得每个 Embedding 的权重
a
i
a_i
ai (在实际的模型中,阿里巴巴采用了
e
a
i
e^{a_i}
eai 而不是
a
i
a_i
ai 作为相应 Embedding 的权重,主要原因有二:一是避免权重为 0; 二是因为在梯度下降过程中有良好的数学性质)
LINE: Large-scale Information Network Embedding
SDNE: Structural Deep Network Embedding
Embedding 与深度学习推荐系统的结合
深度学习网络中的 Embedding 层
- 高维稀疏特征向量天然不适合多层复杂神经网络的训练,因此如果使用深度学习模型处理高维稀疏特征向量,几乎都会在输入层到全连接层之间加入 Embedding 层,完成高维稀疏特征向量到低维稠密特征向量的转换
端到端训练 v.s. 预训练
- 将 Embedding 层与整个深度学习网络整合后一同进行训练是理论上最优的选择,因为上层梯度可以直接反向传播到输入层,模型整体是自洽的。但这样做的缺点是显而易见的,Embedding 层输入向量的维度往往很大,导致整个Embedding 层的参数数量巨大,因此 Embedding 层的加入会拖慢整个神经网络的收敛速度。正因如此,很多工程上要求快速更新的深度学习推荐系统放弃了 Embedding 层的端到端训练,用预训练 Embedding 层的方式替代
Embedding 的预训练方法
- 作为预训练的 Embedding 特征向量,与其他特征向量连接后,一同输入深度学习网络进行训练
- 随着 Graph Embedding 技术的发展,Embedding 本身的表达能力进一步增强,而且能够将各类补充信息全部融入 Embedding 中,使 Embedding 成为非常有价值的推荐系统特征。通常,Graph Embedding 的训练过程只能独立于推荐模型进行,这使得 Embedding 预训练成为在深度学习推荐系统领域更受青睐的 Embedding 训练方法
- 诚然,将 Embedding 过程与深度神经网络的训练过程割裂会损失一定的信息,但训练过程的独立也带来了训练灵活性的提升。举例来说, 物品或用户的 Embedding 是比较稳定的 (因为用户的兴趣、物品的属性不可能在几天内发生巨大的变化),Embedding 的训练频率其实不需要很高,甚至可以降低到周的级别,但上层神经网络为了尽快抓住最新的数据整体趋势信息,往往需要高频训练甚至实时训练。使用不同的训练频率更新 Embedding 模型和神经网络模型,是训练开销和模型效果二者之间权衡后的最优方案
Embedding 作为推荐系统召回层的方法
- 通过计算用户和物品的 Embedding 相似度,Embedding 可以直接作为推荐系统的召回层或者召回策略之一
例子:YouTube 推荐系统召回层
- 上图是 YouTube 推荐系统召回层模型的结构图。其中模型的输入层特征全部都是用户相关特征,从左至右依次是用户观看历史视频的 Embedding 向量、用户搜索词 Embedding 向量、用户地理属性特征 Embedding 向量、用户 (样本) 年龄、性别相关特征
- 模型的输出层是 softmax 层,该模型本质上是一个多分类模型,预测目标是用户观看了哪个视频,因此 softmax 层的输入是经过三层 ReLU 全连接层生成的用户 Embedding, 再经过一个 Embedding 层后输出用户观看每一个视频的概率分布,该 Embedding 层的每一行即为视频 Embedding。也就是说,给定用户
U
U
U 和上下文
C
C
C,在
t
t
t 时刻观看视频
i
i
i 的概率为
P ( w t = i ∣ U , C ) = e v i T u ∑ v j ∈ V e v j T u P(w_t=i\mid U,C)=\frac{e^{v_i^Tu}}{\sum_{v_j\in V}e^{v_j^Tu}} P(wt=i∣U,C)=∑vj∈VevjTueviTu - 训练方法:通过负采样的方式在全体候选集分布中抽取负类,然后通过重要性加权对抽样进行校正。通过模型的离线训练,可以最终得到每个用户的 Embedding 和视频的 Embedding
- 召回层:在模型部署过程中,没有必要部署整个深度神经网络来完成从原始特征向量到最终输出的预测过程,只需要将用户 Embedding 和物品 Embedding 存储到线上内存数据库。对于每个用户 Embedding,与所有视频 Embedding 进行内积运算,取 T o p N Top\ N Top N 的视频作为召回的候选集合
缺陷
- 在整体候选集动辄达到几百万量级的互联网场景下,即使是遍历内积运算这种 O ( n ) O(n) O(n) 级别的操作,也会消耗大量计算时间,导致线上推断过程的延迟。那么工程上有没有针对相似 Embedding 的快速索引方法,能够更快地召回候选集合呢? 答案在下一节揭晓
局部敏感哈希 – 让 Embedding 插上翅膀的快速搜索方法
- Embedding 最重要的用法之一是作为推荐系统的召回层,解决相似物品的召回问题。在实际工程中, 能否应用 Embedding 的关键就在于能否使用 Embedding 技术 “快速” 处理几十万甚至上百万候选集, 避免增大整个推荐系统的响应延迟
“快速” Embedding 最近邻搜索
传统的 Embedding 相似度计算
- 传统的 Embedding 相似度的计算方法是 Embedding 向量间的内积运算,这就意味着为了筛选某个用户的候选物品,需要对候选集合中的所有物品进行遍历。在 k k k 维的 Embedding 空间中,物品总数为 n n n,那么遍历计算用户和物品向量相似度的时间复杂度是 O ( k n ) O(kn) O(kn)。在物品总数 n n n 动辄达到几百万量级的推荐系统中,这样的时间复杂度是承受不了的,会导致线上模型服务过程的巨大延迟
KNN?
- 换一个角度思考这个问题。由于用户和物品的 Embedding 同处于一个向量空间内,所以召回与用户向量最相似的物品 Embedding 向量的过程其实是一个在向量空间内搜索最近邻的过程。如果能够找到高维空间快速搜索最近邻点的方法,那么相似 Embedding 的快速搜索问题就迎刃而解了
k d kd kd 树
- 通过建立 k d kd kd 树索引结构进行最近邻搜索是常用的快速最近邻搜索方法,时间复杂度可以降低到 O ( log 2 n ) O(\log_2n) O(log2n)。但一方面, k d kd kd 树的结构较复杂,而且在进行最近邻搜索时往往还要进行回溯,确保最近邻的结果,导致搜索过程较复杂;另一方面, O ( log 2 n ) O(\log_2n) O(log2n) 的时间复杂度并不是完全理想的状态
- 那么,有没有时间复杂度更低,操作更简便的方法呢? 下面就介绍在推荐系统工程实践上主流的快速 Embedding 向量最近邻搜索方法局部敏感哈希
局部敏感哈希 (Locality Sensitive Hashing, LSH)
基本原理
- 局部敏感哈希的基本思想是让相邻的点落入同一个 “桶”,这样在进行最近邻搜索时,仅需要在一个桶内,或相邻的几个桶内的元素中进行搜索即可。如果保持每个桶中的元素个数在一个常数附近,就可以把最近邻搜索的时间复杂度降低到常数级别
- 那么,如何构建局部敏感哈希中的 “桶” 呢?下面先以基于欧式距离的最近邻搜索为例,解释构建局部敏感哈希 “桶” 的过程
基于欧式距离的最近邻搜索
- 由下图可知,在欧式空间中,将高维空间的点映射到低维空间,原本相近的点在低维空间中肯定依然相近,但原本远离的点则有一定概率变成相近的点
- 利用低维空间可以保留高维空间相近距离关系的性质,就可以构造局部敏感哈希 “桶”。下面我们直接将高维 Embedding 向量映射到一维空间上。假设一维空间的基向量为
x
x
x,则高维 Embedding 向量
v
v
v 在一维空间的投影
v
^
\hat v
v^ 为
v
⋅
x
x
⋅
x
x
\frac{v\cdot x}{x\cdot x}x
x⋅xv⋅xx,因此
∣
v
^
∣
=
v
⋅
x
∣
x
∣
|\hat v|=\frac{v\cdot x}{|x|}
∣v^∣=∣x∣v⋅x。由于我们关注的本来就是相对距离大小,因此可以省略系数
1
∣
x
∣
\frac{1}{|x|}
∣x∣1,直接用内积操作将
v
v
v 映射到一维空间:
h ( v ) = v ⋅ x h(v)=v\cdot x h(v)=v⋅x因此,可以使用上述哈希函数 h ( v ) h(v) h(v) 进行分桶:
h x , b ( v ) = ⌊ v ⋅ x + b w ⌋ h^{x,b}(v)=\left\lfloor\frac{v\cdot x+b}{w}\right\rfloor hx,b(v)=⌊wv⋅x+b⌋其中, w w w 是分桶宽度, b b b 是 0 到 w w w 间的一个均匀分布随机变量,避免分桶边界固化
基于余弦相似度的最近邻搜索
- 以上是欧式空间中内积操作的局部敏感哈希使用方法,如果将余弦相似度作为距离标准,应该采用什么方式进行分桶呢?余弦相似度衡量的是两个向量间夹角的大小,夹角小的向量即为 “近邻”,因此可以使用固定间隔的超平面将向量空间分割成不同哈希桶
基于其他距离度量的最近邻搜索
- 当然,距离的定义方法远不止 “欧氏距离” 和 “余弦相似度” 两种,还包括 “曼哈顿距离” “切
比雪夫距离” “汉明距离” 等,局部敏感哈希的方法也随距离定义的不同有所不同。但局部敏感哈希通过分桶方式保留部分距离信息,大规模降低近邻点候选集的本质思想是通用的
多桶策略
多个哈希函数同时进行分桶
- 映射操作损失了部分距离信息,如果仅采用一个哈希函数进行分桶,则必然存在相近点误判的情况。有效的解决方法是采用 m m m 个哈希函数同时进行分桶。同时掉进 m m m 个哈希函数的同一个桶的两点,是相似点的概率将大大增加。通过分桶找到相邻点的候选集合后,就可以在有限的候选集合中通过遍历找到目标点真正的 K K K 近邻
多桶策略
- 采用多个哈希函数进行分桶,存在一个待解决的问题: 到底是通过 “与” (And) 操作还是 “或” (Or) 操作生成最终的候选集
- 如果通过 “与” 操作 (“点 A A A 和点 B B B 在哈希函数 1 的同一桶中” 并且 “点 A A A 和点 B B B 在哈希函数 2 的同一桶中”) 生成候选集,那么候选集中近邻点的准确率将提高,候选集的规模减小使需要遍历计算的量降低,减少了整体的计算开销,但有可能会漏掉一些近邻点 (比如分桶边界附近的点)
- 如果通过 “或” 操作 (“点 A A A 和点 B B B 在哈希函数 1 的同一桶中” 或者 “点 A A A 和点 B B B 在哈希函数 2 的同一桶中”) 生成候选集,那么候选集中近邻点的召回率提高,但候选集的规模变大,计算开销升高
- 到底使用几个哈希函数,是用 “与” 操作还是 “或” 操作来生成近邻点的候选集,需要在准确率和召回率之间权衡,才能得出结论
总结 – 深度学习推荐系统的核心操作
参考文献
- 《深度学习推荐系统》(王喆)