场景&解决的问题
本文提出的方法解决了天猫主页的个性化推荐(占天猫流量的约50%)中的召回部分。
在天猫的个性化推荐场景中,无论是召回还是排序阶段,最重要的都是为用户兴趣建模。然而建模用户兴趣存在问题:一个用户可能对多种物品感兴趣。
现有的推荐算法采取过多种方法来对用户兴趣建模。基于协同过滤的方法用用户历史行为或隐性因子来表示用户兴趣,这种方法的局限性在于稀疏性和计算困难。深度学习方法通常将用户兴趣表示为一个低维度的embedding,然而这种方法中,embedding的维度可能会成为表达用户各种兴趣的瓶颈。DIN在表示用户兴趣时引入了attention,然而由于计算复杂性,这种方法只能用在排序阶段。
本文提出的MIND模型关注点在于在排序阶段为用户的兴趣多样性建模。我们设计了一个多兴趣抽取层,利用动态路由来将用户的历史聚合为用户的embedding表达。这一动态路由可以看做是一种soft clustering,将用户历史聚合成一些簇。这样对于一个用户,MIND就可以输出多个向量来表达用户的多种兴趣。
问题形式化
推荐系统召回阶段的目标就是从一个巨大的物品池
I
I
I中为每个用户
u
∈
U
u \in U
u∈U召回一千级别的物品,并且每个物品都与用户兴趣相关。为达成这一目标,推荐系统生成的历史数据被收集下来来构建召回模型。其中的每个样本可以表示为一个三元组
(
I
u
,
P
u
,
F
i
)
(I_u, P_u, F_i)
(Iu,Pu,Fi),其中
I
u
I_u
Iu表示用户
u
u
u交互过的物品,
P
u
P_u
Pu表示用户的基础画像。
F
i
F_i
Fi表示目标物品的特征。
MIND的核心任务就是学习一个映射关系,将原始特征与用户表示映射起来:
V
u
=
f
u
s
e
r
(
I
u
,
P
u
)
V_u = f_{user}(I_u, P_u)
Vu=fuser(Iu,Pu)
其中
V
u
=
(
v
u
1
,
.
.
.
,
v
u
K
)
∈
R
d
∗
K
V_u = (v_u^1, ..., v_u^K) \in R^{d *K}
Vu=(vu1,...,vuK)∈Rd∗K表示用户向量。
K
K
K为向量个数。若
K
=
1
K=1
K=1,那么就像youtube DNN一样只用一个向量表示用户。目标物品
i
i
i则用以下embedding表示:
e
i
=
f
i
t
e
m
(
F
i
)
e_i = f_{item}(F_i)
ei=fitem(Fi)
这个函数的具体形式将在后面说明。
在得到用户和物品的embedding后,topN的物品根据以下分数进行召回:
f
s
c
o
r
e
(
V
u
,
e
i
)
=
m
a
x
1
≤
k
≤
K
e
i
T
v
u
k
f_{score}(V_u, e_i) = max_{1 \leq k \leq K}e_i^Tv_u^k
fscore(Vu,ei)=max1≤k≤KeiTvuk
embedding&pooling层
如上图所示,MIND的输入由三部分组成:用户属性,用户行为和目标物品。每个部分都有一些类别id特征,对于这些特征我们进行embedding。对于用户属性embedding,我们直接将其拼接起来;对于物品的id和属性embedding,我们对它们进行平均池化,最后,用户行为直接用组成用户行为的物品embedding集合来表示。
多兴趣抽取层
我们认为将用户兴趣表示为一个embedding可能是限制用户兴趣多样性的一个瓶颈,因为我们必须将用户的所有兴趣压缩进一个embedding,于是就会导致召回阶段不能够精确地召回物品。因此我们用多个向量分别来表示用户的兴趣。为学习这一表示,我们利用聚类方法来将用户的历史行为聚成多个簇。这一设计是受到了近期提出的动态路由的启发。
动态路由
我们简短地介绍一下动态路由:假设我们有两层胶囊网络,分别为低级胶囊和高级胶囊。动态路由的目标就是通过低级胶囊的值来迭代地计算高级胶囊的值。在每次迭代中,给出低级胶囊和对应的向量
c
i
l
∈
R
N
l
∗
1
,
i
∈
{
1
,
.
.
.
,
m
}
c_i^l\in R^{N_l * 1 }, i \in \{1, ..., m\}
cil∈RNl∗1,i∈{1,...,m},以及高级胶囊和对应的向量
c
j
h
∈
R
N
h
∗
1
,
j
∈
{
1
,
.
.
.
,
n
}
c_j^h\in R^{N_h * 1 }, j \in \{1, ..., n\}
cjh∈RNh∗1,j∈{1,...,n},路由的logit用下面方法计算:
b
i
j
=
(
c
j
h
)
T
S
i
j
c
i
l
b_{ij} = (c^h_j)^TS_{ij}c_i^l
bij=(cjh)TSijcil
其中
S
i
j
∈
R
N
h
∗
N
l
S_{ij} \in R^{N_h * N_l}
Sij∈RNh∗Nl表示需要被学习的双线性空间映射矩阵,m和n分别为高级胶囊和低级胶囊的数量。
有了这样的一个路由logits,高级胶囊的候选vector就可以由所有低级胶囊的加权和表示:
z
j
h
=
∑
i
=
1
m
w
i
j
S
i
j
c
i
l
z_j^h = \sum^m_{i=1}w_{ij}S_{ij}c_i^l
zjh=i=1∑mwijSijcil
其中
w
i
j
w_{ij}
wij表示连接低级胶囊和高级胶囊的权重,是由路由logits求softmax得到的:
w
i
j
=
e
x
p
b
i
j
∑
k
=
1
m
e
x
p
b
i
k
w_{ij} = \frac{exp b_{ij}}{\sum^m_{k=1}exp b_{ik}}
wij=∑k=1mexpbikexpbij
最后,一个非线性的squash函数用来得到高级胶囊:
c
j
h
=
s
q
u
a
s
h
(
z
j
h
)
=
∥
z
j
h
∥
2
1
+
∥
z
j
h
∥
2
z
j
h
∥
z
j
h
∥
c_j^h = squash(z_j^h) = \frac{\parallel z_j^h \parallel ^2}{1 + \parallel z_j^h \parallel^2} \frac{ z_j^h}{\parallel z_j^h \parallel}
cjh=squash(zjh)=1+∥zjh∥2∥zjh∥2∥zjh∥zjh
b
i
j
b_{ij}
bij的值被初始化为0,路由过程通常重复三次以使得胶囊值收敛,当路由结束后,高级胶囊的值就可以输入下一层。
B2I动态路由
我们可以把胶囊理解成一个由多个向量组成的神经元,每个向量可以表达实体的不同属性。我们对动态路由做了三个改动,以使之适用于用户兴趣的表示。
- 共享双线性映射矩阵。原始的动态路由每对高级-低级胶囊都有一个双线性映射矩阵,而我们对所有高级-低级胶囊共享同一个矩阵。我们这样做的原因一方面是用户的行为是变长的,我们希望固定的映射矩阵能够增强模型的泛化能力;另一方面,我们希望兴趣胶囊能够全部位于同一向量空间。于是路由逻辑可以表示为: b i j = u j T S e i b_{ij} = u_j^TSe_i bij=ujTSei其中 e i e_i ei表示用户行为对应的物品i的embedding, u j u_j uj表示兴趣胶囊j的embedding
- 路由逻辑的随机初始化。由于共享双线映射矩阵S,将路由logit初始化为0会导致初始兴趣胶囊完全一致,然后后续的迭代便会陷入一个循环:不同的兴趣胶囊参数始终是完全相同的。为避免这种情况,我们用从高斯分布中采样的随机矩阵来进行初始化。这一做法与k-means算法相似。
- 动态兴趣数量。由于不同用户的兴趣胶囊数目不同,我们引入了一个启发式的规则来为不同的用户调整兴趣胶囊的数目K:用户u的K值由下式计算:
K u ′ = m a x ( 1 , m i n ( K , l o g 2 ( ∣ I u ∣ ) ) ) K'_u = max(1, min(K, log_2(|I_u|))) Ku′=max(1,min(K,log2(∣Iu∣)))
这一策略对于那些兴趣点较少的用户来说,既可以节约计算的时间,也可以节约内存。
下图列出了整个动态路由算法的流程。
label aware attention
通过多兴趣抽取层我们生成了多个兴趣胶囊。不同的兴趣胶囊表示了用户兴趣的不同方面,相关的兴趣胶囊被用来评估用户对特定物品的兴趣。于是在训练期间我们设计了一个label-aware的attention层,attention是基于缩放点积的。特别地,对于一个目标item,我们计算出每个兴趣胶囊与它的相容性(?)然后将兴趣胶囊加权求和作为用户向量。在label-aware attention中,label(目标item)是query,兴趣胶囊是key和value。输出的用户向量由下式计算:
v
u
=
A
t
t
e
n
t
i
o
n
(
e
i
,
V
u
,
V
u
)
=
V
u
s
o
f
t
m
a
x
(
(
V
u
T
e
i
)
p
)
v_u = Attention(e_i, V_u, V_u) = V_u softmax((V_u^Te_i)^p)
vu=Attention(ei,Vu,Vu)=Vusoftmax((VuTei)p)
其中p是个可调的参数,p越大,点击较大的值就会有更大的权重。当p趋近于正无穷时,上式就变成了一个hard attention,也就是只采用点击最大的value而无视其他所有value。我们的实验表明hard attention能够加速收敛。
训练&线上服务
得到用户向量之后,用户u与物品i交互的概率就可以得到:
P
r
(
i
∣
u
)
=
P
r
(
e
i
∣
v
u
)
=
e
x
p
(
v
u
e
i
)
∑
j
∈
I
e
x
p
(
v
u
T
e
j
)
Pr(i|u) = Pr(e_i | v_u) = \frac{exp(v_u e_i)}{\sum_{j \in I} exp(v_u^Te_j)}
Pr(i∣u)=Pr(ei∣vu)=∑j∈Iexp(vuTej)exp(vuei)
于是整体的目标函数就是:
L
=
∑
(
u
,
i
)
∈
D
l
o
g
P
r
(
i
∣
u
)
L = \sum _{(u, i) \in D} logPr(i|u)
L=(u,i)∈D∑logPr(i∣u)
其中D是包含用户和物品交互的训练集全集。由于物品的数量是十亿规模,我们在计算softmax的时候进行了采样。在训练的时候用了Adam优化器。
训练完成后,MIND网络会用来进行用户向量的生成。为一个用户生成多个兴趣向量后,用这些向量召回top N的item到推荐系统的下一步。
实验
数据集
- Amazon Books,过滤掉被点击少于10次的item和点击少于10次的user
- Tmall Data,过滤掉被少于600人点击的item
评估指标
我们通过预测用户下一个交互的物品来评估模型准确性:将用户和item交互数据按19:1的比例随机分为训练集和测试集,对测试集里的用户,用当前item前的item序列作为用户行为,得到:
H
i
t
R
a
t
e
@
N
=
∑
(
u
,
i
)
∈
D
t
e
s
t
I
(
t
a
r
g
e
t
出
现
在
t
o
p
N
)
∣
D
t
e
s
t
∣
HitRate@N = \frac{\sum_{(u, i) \in D_{test}} I(target出现在top N)}{|D_{test}|}
HitRate@N=∣Dtest∣∑(u,i)∈DtestI(target出现在topN)
对比的方法
- WALS:加权ALS,经典的基于矩阵分解的user召回方法
- YouTube DNN:具体见我上一篇笔记
- MaxMF:通过非线性隐式矩阵分解来为多种用户兴趣建模
线上实验
我们在天猫主页上进行了为期一周的实验,对照组是基于item的CF和youtubeDNN,三种召回的top 1000结果输入同一个排序模型。实验结果显示MIND的效果优于其他两种,CTR相比基于item的CF上涨约2%。
TBC.