当前位置:网站首页>图神经网络用于推荐系统问题(IMP-GCN,LR-GCN)
图神经网络用于推荐系统问题(IMP-GCN,LR-GCN)
2022-07-25 11:08:00 【上杉翔二】
本篇文章follow一些Graph in Rec 的部分文章,以前博主整理过的系列可以见:

Interest-aware Message-Passing GCN for Recommendation
来自WWW2021的文章,探讨推荐系统中的过平滑问题。从何向南大佬的NGCF开始一直强调的就是高阶邻居的协作信号是可以学习良好的用户和项目嵌入。虽然GCN容易过平滑(即叠加更多层时,节点嵌入变得更加相似,最终无法区分,导致性能下降),也可以用一些方法来缓解如LightGCN和LR-GCN模型,但作者认为他们忽略了一个很重要的问题:用户的嵌入学习也可以涉及到与用户没有共同兴趣的高阶邻域用户。 所以多层图卷积会使不同兴趣的用户具有相似的嵌入性。
应对这一点,作者提出一种新的兴趣感知消息传递GCN (IMP-GCN),该模型将用户及其交互项分组到不同的子图中,在子图中进行高阶图卷积 。而这里的子图是由具有相似兴趣的用户及其交互项组成的。子图由无监督的子图生成模块生成,该模块集成了用户特征和图结构,以识别具有相似兴趣的用户,然后通过保留这些用户及其交互项来构造子图。为此,其可以过滤掉在高阶图卷积运算中的负信息传播,从而通过叠加更多的图卷积层来保持用户的唯一性。
模型图如上,简单来看就是一阶和多阶子图的融合,最后combination之后做预测。
- Interest-aware Message-passing Strategy。文章使用的传播都是LightGCN,因为它的有效性已经得到了很好的证明。 e u ( k + 1 ) = ∑ i s ∈ N u 1 ∣ N u ∣ ∣ N i ∣ e i s ( k ) e^{(k+1)}_u=\sum_{is \in N_u}\frac{1}{\sqrt{|N_u|}\sqrt{|N_i|}}e_{is}^{(k)} eu(k+1)=is∈Nu∑∣Nu∣∣Ni∣1eis(k) e i s ( k + 1 ) = ∑ u ∈ N i s 1 ∣ N i ∣ ∣ N u ∣ e u ( k ) e^{(k+1)}_{is}=\sum_{u \in N_i^s}\frac{1}{\sqrt{|N_i|}\sqrt{|N_u|}}e_{u}^{(k)} eis(k+1)=u∈Nis∑∣Ni∣∣Nu∣1eu(k)最后经过图卷积后item𝑖的最终表示是它在不同子图s中学习到的嵌入的组合: e i ( k ) = ∑ s ∈ S e i s ( k ) e^{(k)}_{i}=\sum_{s \in S} e_{is}^{(k)} ei(k)=s∈S∑eis(k)
- Layer Combination and Prediction。将每一层获得的嵌入结合起来,形成用户𝑢和项目𝑖的最终表示。
- Subgraph Generation Module。子图用于对具有共同兴趣的用户进行分组,所以这一任务很容易被抽象为为一个分类任务,即每个用户都被分类为一个组。具体地说,每个用户都由一个特征向量表示,此处融合ID(e0)和图传播后表示(e1)组成为以下: F u = σ ( W 1 ( e u ( 0 ) + e u ( 1 ) ) + b 1 ) F_u=\sigma(W_1(e^{(0)}_u+e^{(1)}_u)+b_1) Fu=σ(W1(eu(0)+eu(1))+b1)将获得的用户特征转换为具有2层神经网络去分类即可: U h = σ ( W 2 F u + b 2 ) U_h=\sigma(W_2F_u+b_2) Uh=σ(W2Fu+b2) U o = W 3 U h + b 3 U_o=W_3U_h+b_3 Uo=W3Uh+b3Uo即表示了用户所属的组/子图。值得注意的是,这里将用户分为不同的组是一种无监督的方法,不需要真实标签。此处博主个人的理解是,有相似embedding的用户将生成的预测向量,所以会被归类为同一组。
更多的细节可以参看原文和代码:
- paper:https://arxiv.org/abs/2102.10044
- code:https://github.com/liufancs/IMP_GCN

Revisiting Graph based Collaborative Filtering: A Linear Residual Graph Convolutional Network Approach
补一下前文说到的LR-GCN,来自AAAI2020。LR-GCN也始于两个问题:
- 对于用户和项嵌入,GCN遵循使用图卷积操作和非线性变换进行邻域聚合的两个步骤。虽然图的卷积操作对聚合邻域信息和建模高阶图结构是有效的,但在GCN中的非线性特征变换所引入的额外复杂性有必要吗?
- 目前大多数基于GCN的模型只能堆叠很少的层(例如,2层)。 事实上,存在过度平滑效应从而导致每个节点的高阶邻居往往无法区分。虽然作者任务随着叠加层的增加,平滑效应最初可以缓解CF的数据稀疏性,但更多层引入的过度平滑效应会忽略每个用户的独特性,最终会降低推荐性能。
针对这两个问题,作者提出残差图卷积方法重新研究了基于图的CF模型(Linear Residual Graph Convolutional Collaborative Filtering)。 模型图如上,其实解决方案已经十分的明显了,在每一步的传播中进行残差连接,并且没有非线性…
- 在特征传播步骤的每一层上,使用一个简单的线性嵌入传播,而没有任何非线性转换。 [ E k + 1 ] u = e u k + 1 = [ 1 d u e u k + ∑ j ∈ R u 1 d j × d u e j k ] W k [E^{k+1}]_u=e^{k+1}_u=[\frac{1}{d_u}e^k_u+\sum_{j \in R_u}\frac{1}{d_j \times d_u}e^k_j]W^k [Ek+1]u=euk+1=[du1euk+j∈Ru∑dj×du1ejk]Wk [ E k + 1 ] i = e i k + 1 = [ 1 d i e i k + ∑ u ∈ R i 1 d i × d u e u k ] W k [E^{k+1}]_i=e^{k+1}_i=[\frac{1}{d_i}e^k_i+\sum_{u \in R_i}\frac{1}{d_i \times d_u}e^k_u]W^k [Ek+1]i=eik+1=[di1eik+u∈Ri∑di×du1euk]Wk其中d是度,R是邻居。
- 为了预测用户对项目的偏好,提出了一种基于残余的网络结构来克服过平滑。 r u i k + 1 = r u i k + < e u k + 1 , e i k + 1 > r^{k+1}_{ui}=r^{k}_{ui}+<e^{k+1}_u,e^{k+1}_i> ruik+1=ruik+<euk+1,eik+1>
简要看看关键代码吧:
def forward(self, user, item_i, item_j):
#得到embedding
users_embedding=self.embed_user.weight
items_embedding=self.embed_item.weight
#直接开始gcn,这里直接实现上面的那个公式,1无非线性2残差也是在这里一起做的,先user,再item。
#然后尝试搭建多层的GCN。
gcn1_users_embedding = (torch.sparse.mm(self.user_item_matrix, items_embedding) + users_embedding.mul(self.d_i_train))#*2. #+ users_embedding
gcn1_items_embedding = (torch.sparse.mm(self.item_user_matrix, users_embedding) + items_embedding.mul(self.d_j_train))#*2. #+ items_embedding
gcn2_users_embedding = (torch.sparse.mm(self.user_item_matrix, gcn1_items_embedding) + gcn1_users_embedding.mul(self.d_i_train))#*2. + users_embedding
gcn2_items_embedding = (torch.sparse.mm(self.item_user_matrix, gcn1_users_embedding) + gcn1_items_embedding.mul(self.d_j_train))#*2. + items_embedding
gcn3_users_embedding = (torch.sparse.mm(self.user_item_matrix, gcn2_items_embedding) + gcn2_users_embedding.mul(self.d_i_train))#*2. + gcn1_users_embedding
gcn3_items_embedding = (torch.sparse.mm(self.item_user_matrix, gcn2_users_embedding) + gcn2_items_embedding.mul(self.d_j_train))#*2. + gcn1_items_embedding
# gcn4_users_embedding = (torch.sparse.mm(self.user_item_matrix, gcn3_items_embedding) + gcn3_users_embedding.mul(self.d_i_train))#*2. + gcn1_users_embedding
# gcn4_items_embedding = (torch.sparse.mm(self.item_user_matrix, gcn3_users_embedding) + gcn3_items_embedding.mul(self.d_j_train))#*2. + gcn1_items_embedding
gcn_users_embedding= torch.cat((users_embedding,gcn1_users_embedding,gcn2_users_embedding,gcn3_users_embedding),-1)#+gcn4_users_embedding
gcn_items_embedding= torch.cat((items_embedding,gcn1_items_embedding,gcn2_items_embedding,gcn3_items_embedding),-1)#+gcn4_items_embedding#
#然后实现bpr的loss计算,即先得到i和j
user = F.embedding(user,gcn_users_embedding)
item_i = F.embedding(item_i,gcn_items_embedding)
item_j = F.embedding(item_j,gcn_items_embedding)
# # pdb.set_trace()
prediction_i = (user * item_i).sum(dim=-1)
prediction_j = (user * item_j).sum(dim=-1)
#再相减,补上一个L2
# loss=-((rediction_i-prediction_j).sigmoid())**2#self.loss(prediction_i,prediction_j)#.sum()
l2_regulization = 0.01*(user**2+item_i**2+item_j**2).sum(dim=-1)
# l2_regulization = 0.01*((gcn1_users_embedding**2).sum(dim=-1).mean()+(gcn1_items_embedding**2).sum(dim=-1).mean())
loss2= -((prediction_i - prediction_j).sigmoid().log().mean())
# loss= loss2 + l2_regulization
loss= -((prediction_i - prediction_j)).sigmoid().log().mean() +l2_regulization.mean()
# pdb.set_trace()
return prediction_i, prediction_j,loss,loss2
更多的细节可以参看原文和代码:
- paper:https://arxiv.org/abs/2001.10167v1
- code:https://github.com/newlei/LR-GCCF
下一篇博文继续整理
边栏推荐
- Oracle parsing XML with the same name
- Risks in software testing phase
- Teach you how to configure S2E to UDP working mode through MCU
- Functions in JS
- 如何解决“W5500芯片在TCP_Client模式下,断电重启之后无法立即连接到服务器”的问题
- brpc源码解析(六)—— 基础类socket详解
- 油猴脚本链接
- flinksql client 连接kafka select * from table没有数据报错,如何解决?
- Reinforcement learning (IV)
- A beautiful gift for girls from programmers, H5 cube, beautiful, exquisite, HD
猜你喜欢

Management of software defects
![[USB device design] - composite device, dual hid high-speed (64BYTE and 1024byte)](/img/ce/534834c53c72a53fd62ff72a1d3b39.png)
[USB device design] - composite device, dual hid high-speed (64BYTE and 1024byte)

The most efficient note taking method in the world (change your old version of note taking method)

教你如何通过MCU配置S2E为TCP Client的工作模式

教你如何通过MCU将S2E配置为UDP的工作模式

Brpc source code analysis (VIII) -- detailed explanation of the basic class eventdispatcher

第一个C语言程序(从Hello World开始)

brpc源码解析(五)—— 基础类resource pool详解

【IMX6ULL笔记】--内核底层驱动初步探究

Learn NLP with Transformer (Chapter 1)
随机推荐
【mysql学习09】
How to solve the problem that "w5500 chip cannot connect to the server immediately after power failure and restart in tcp_client mode"
一文入门Redis
【USB设备设计】--复合设备,双HID高速(64Byte 和 1024Byte)
"Mqtt protocol explanation and Practice (access to onenet)" of wiznet w5500 series training activities
Small program of vegetable distribution in community
W5500通过上位机控制实现调节LED灯带的亮度
阿里云技术专家秦隆:可靠性保障必备——云上如何进行混沌工程
MySQL historical data supplement new data
Reflection reflection
Similarity matrix, diagonalization condition
SQL language (6)
【无标题】
已解决 Files‘ name is invalid or does not exist (1205)
php curl post Length Required 错误设置header头
Plot ==pyqt5
brpc源码解析(一)—— rpc服务添加以及服务器启动主要过程
Onenet platform control w5500 development board LED light
A beautiful gift for girls from programmers, H5 cube, beautiful, exquisite, HD
brpc源码解析(六)—— 基础类socket详解