Multi-GCCF:物尽其用
1 一点点引入
Multi-Graph convolution collaborative filtering(Multi-GCCF) 属于基于图神经网络的协同过滤算法。
协同过滤算法通常基于这样一个假设:相似的用户往往喜欢同样的item,而具有相似客户的item往往会得到相似的评分。所以,大多数协同过滤算法基于user-item二分网络做出推荐,但由于在实际场景中每个user所对应的item数量是有限的,这就会导致构造出的user-item二分网络非常稀疏。此时,使用图卷积等深度学习算法很难在有限特征信息的基础上生成一个表示能力较强的embedding。
Mutil-GCCF的作者通过考虑user-user的交互信息和item-item的交互信息来缓解这一问题。在二分网络中,节点的类型包括item和user。各节点的一阶邻居为不同类别的节点,而二阶邻居则是同类节点。虽然考虑二阶邻居可以将user-user与item-item的交互关系考虑进去,但作者希望显式地考虑将其考虑进去。于是,构建user-user网络和item-item网络对算法进行了改进。
此外, user节点和item节点的类型不同,在信息聚合阶段使用同样的参数聚合两类不同类型的节点信息是不够合理的。Multi-GCCF在更新节点embedding时使用了两套参数将这两类节点分别聚合和特征转换,考虑user节点与item节点的内在差异。
P.S. 小伙伴们看完有收获可以帮忙点个赞嘛,也给我一些动力 ^_ ^!
2 Multi-GCCF一瞥
Multi-GCCF主要分为以下三个部分:
- 基于user-item二分网络生成节点的embedding;
- 基于user-user网络与item-item网络生成embedding;
- 使用skip-connection将初始的节点特征与最终的节点embedding连接,以避免信息层层传递导致的信息丢失。
总体框架如下:
2.1 Bipartite Graph Convolutional neural networks
Bipar-GCN层包含forward sampling和backward aggregating两块。其中,forward sampling的作用在于防止节点度幂律分布带来的影响。在采样完模型1到 K K K层的邻居节点之后,采用GCN来聚合邻居信息。
假设为每个节点学习到的初始embedding为 e u e_u eu和 e v e_v ev(若初始的节点输入有特征信息,这个初始embedding可以使用MLP学习)。
第
k
k
k层目标user的embedding更新机制如下:
h
u
k
=
σ
(
W
u
k
[
h
u
k
−
1
;
h
N
(
u
)
k
−
1
]
)
,
h
u
0
=
e
u
{\bf h}_u^k=\sigma({\bf W}_u^k[{\bf h}_u^{k-1};{\bf h}^{k-1}_{N(u)}]), {\bf h}_u^0=e_u
huk=σ(Wuk[huk−1;hN(u)k−1]),hu0=eu
其中,
W
u
k
{\bf W}_u^k
Wuk为可学习的参数,
σ
\sigma
σ为tanh激活函数,
[
;
]
[;]
[;]为拼接操作。
h
N
(
u
)
k
−
1
{\bf h}^{k-1}_{N(u)}
hN(u)k−1的更新规则如下:
h
N
(
u
)
k
−
1
=
A
G
G
R
E
G
A
T
O
R
u
(
h
v
k
−
1
,
v
∈
N
(
u
)
)
h^{k-1}_{N(u)}={\bf AGGREGATOR}_u({\bf h}_v^{k-1},v \in N(u))
hN(u)k−1=AGGREGATORu(hvk−1,v∈N(u))
A G G R E G A T O R u = σ ( M E A N ( { h v k − 1 Q u k } ) , v ∈ N ( u ) ) ) {\bf AGGREGATOR}_u=\sigma({\bf MEAN(\{h}_v^{k-1}{\bf Q}_u^k\}),v \in N(u))) AGGREGATORu=σ(MEAN({hvk−1Quk}),v∈N(u)))
Q u k {\bf Q}_u^k Quk为第 k k k层user聚合权重矩阵。
同样地,第
k
k
k层目标item的embedding更新机制如下:
h
v
k
=
σ
(
W
v
k
[
h
v
k
−
1
;
h
N
(
v
)
k
−
1
]
)
,
h
v
0
=
e
v
{\bf h}_v^k=\sigma({\bf W}_v^k[{\bf h}_v^{k-1};{\bf h}^{k-1}_{N(v)}]), {\bf h}_v^0=e_v
hvk=σ(Wvk[hvk−1;hN(v)k−1]),hv0=ev
h N ( v ) k − 1 = A G G R E G A T O R v ( h u k − 1 , v ∈ N ( v ) ) h^{k-1}_{N(v)}={\bf AGGREGATOR}_v({\bf h}_u^{k-1},v \in N(v)) hN(v)k−1=AGGREGATORv(huk−1,v∈N(v))
A G G R E G A T O R v = σ ( M E A N ( { h u k − 1 Q v k } ) , u ∈ N ( v ) ) ) {\bf AGGREGATOR}_v=\sigma({\bf MEAN(\{h}_u^{k-1}{\bf Q}_v^k\}),u \in N(v))) AGGREGATORv=σ(MEAN({huk−1Qvk}),u∈N(v)))
整体示意图如下:
由上面的公式和示意图可以看出,Multi-GCCF对于user和item的embedding生成是分开的,使用了两组不同的权重。这一操作也就是文中提到的,考虑user节点和item节点的内在差异。
这里对于初始embedding的生成可以深入探讨一下。比如,若没有拿到user和item的特征,使用one-hot作为编码是否可行?根据LightGCN的实验,是否可以将非线性激活和线性特征转换去除?还是说可以用LightGCN做出来的第一层embedding作为Multi-GCCF的初始embedding,能否有效?有兴趣的小伙伴可以相互交流一下~
不了解LightGCN的小伙伴可以看一下: LightGCN不相信非线性激活与特征转换。
2.2 Multi-Graph Encoding
构建user-user网络与item-item网络的目的是为了缓解user-item二分网络的信息不充足,其原因在于大多数用户对应的item数量是有限的,数据会比较稀疏,所以通过构建这两个网络来补充信息。
具体的user-user网络与item-item网络的构建方式为:计算rating/click矩阵行或列的余弦相似性,并根据相似性建立节点之间的连边,其中,相似性阈值的确定是要使得网络的平均度为10。
有了网络之后,节点的embedding生成规则如下:
z
u
=
σ
(
∑
i
∈
N
′
(
u
)
e
i
M
u
)
;
z
v
=
σ
(
∑
j
∈
N
′
(
v
)
e
j
M
u
)
z_u=\sigma(\sum_{i \in N'(u)}e_i{\bf M}_u);z_v=\sigma(\sum_{j \in N'(v)}e_j{\bf M}_u)
zu=σ(i∈N′(u)∑eiMu);zv=σ(j∈N′(v)∑ejMu)
其中,
M
u
{\bf M}_u
Mu和
M
v
{\bf M}_v
Mv为可学习参数,
N
′
(
u
)
N'(u)
N′(u)和
N
′
(
v
)
N'(v)
N′(v)为节点
u
u
u与节点
v
v
v的一阶邻居节点。
得到了MGE层的输出后,将其与Bipar-GCN层的embedding拼接。
2.3 Skip-connection
由于节点的初始特征在经过多层非线性激活和特征转换之后,其在embedding中的信息有所流失,作者为了在节点表示中保留节点的初始特征,利用一个全连接层对节点初始特征进行转化得到了一个制定维度的embedding与Bipar-GCN层和MGE层的embedding进行连接。
2.4 关于如何拼接
如前面提到的,Multi-GCCF会生成三种类型的embedding:
- Bipar-GCN层生成的embedding;
- MGE层生成的embedding;
- Skip connection部分基于全连接生成的embedding。
那么如何将这三种embedding进行拼接呢?文章中的作者尝试了element-wise sum、concatenation以及Attention,具体如下:
2.5 损失函数
Multi-GCCF所用的损失函数为BPR损失,基本思想是最大化正样本和负样本之间的差距,即用户会购买的商品与用户不会购买的商品之间的概率差距越大越好,具体公式如下:
L
B
P
R
=
∑
u
,
i
,
j
∈
O
−
l
o
g
σ
(
e
u
∗
e
i
∗
−
e
u
∗
e
j
∗
)
+
λ
∣
∣
Θ
∣
∣
2
2
+
β
(
∣
∣
e
u
∗
∣
∣
2
2
+
∣
∣
e
i
∗
∣
∣
2
2
+
∣
∣
e
j
∗
∣
∣
2
2
)
L_{BPR}=\sum_{u,i,j \in O} -log\sigma(e^*_ue^*_i - e^*_ue^*_j)+\lambda||\Theta||_2^2+\beta(||e^*_u||_2^2+||e^*_i||_2^2+||e^*_j||_2^2)
LBPR=u,i,j∈O∑−logσ(eu∗ei∗−eu∗ej∗)+λ∣∣Θ∣∣22+β(∣∣eu∗∣∣22+∣∣ei∗∣∣22+∣∣ej∗∣∣22)
其中,
O
=
{
(
u
,
i
,
j
)
∣
(
u
,
i
)
∈
R
+
,
(
u
,
j
)
∈
R
−
}
O=\{(u,i,j)|(u,i) \in {\bf R}^+, (u,j)\in {\bf R}^-\}
O={(u,i,j)∣(u,i)∈R+,(u,j)∈R−},
R
+
{\bf R}^+
R+与
R
−
{\bf R}^-
R−为采样得到的正样本和负样本,
Θ
\Theta
Θ为模型的参数。
3 效果如何
首先是和baseline对比了一下Recall和NDCG,见下表
由表可知,几乎在所有数据集中,Multi-GCCF的性能都是最好的。
然后测试了Multi-GCCF个组件的贡献,结果如下:
由上表可以看出,三个组成部分都是可以带来性能增益的。
最后,测试了上文提到的不同的embedding拼接方式带来的性能:
由表可知,element-wise sum是一个比较合适的选择。
4 总结
Multi-GCCF给我个人带来的启发有以下几点:
- 当二分网络比较稀疏时,建网是一条可行的路径。此外,skip connection可以帮助我们保留住初始的特征。个人认为Multi-GCCF性能好的原因在于他做了三种不同的embedding,以使得最终的embedding具有较强的表示能力。但各部分embedding如何生成其实还有优化的空间,比如,使用不同的方法考虑user和item节点的差异。
- 文中没有提到过Multi-GCCF的效率,我认为这是一个有待考量的方面。如何提升其效率应该也是一个比较有意思的问题。