LightGCN召回算法

GCN流程

第一步,构建用户点击商品记录表,按照city进行切分,(过滤掉不置信的交互数小于n的user)每个城市生成一个文件。文件格式为city,user_id,[(item_id)...].

第二步:读取某个city文件,对item_id和user_id进行编码,且得到编码后的数量(n_user和n_item)

第三步:构建adj:长宽为(n_user + n_item)矩阵,有交互的值为1,无交互为0

第四步:创建DGL:self.g = dgl.from_scipy(self.adj)

第五步:保存到本地文件:adj

模型结构:

class LightGCN(keras.Model):
    def __init__(self, user_vol, item_vol, dim):
        super(LightGCN, self).__init__()
        self.user_size = user_vol
        self.item_size = item_vol
        self.dim = dim
        self.gcn_layers = [GraphConv(dim, dim, norm='both') for i in range(3)]
        # 也就是三层GraphConv

call方法:

    def call(self, graph, training=False, method='full'):
        embedding = self.look_up_embedding(graph, method)   #全图节点进行Embedding:(1172,128)  user和item一共有1172个节点。
        out_embedding = embedding
        for layer in self.gcn_layers: 
            embedding = layer(graph, embedding) # 层图卷的输入是上个图卷积的输出
            out_embedding += embedding    #out_embedding = 全图节点Embedding + 3个图卷积层的输出
        return out_embedding, embedding

train方法:

def train(self, g, train_user, train_item, neg_size, i_weight, method='full'):  #
    with tf.device('/device:GPU:0'):
        embedding, _ = self(g, training=True, method=method)  # 调用call函数 (对图节点进行Embedding,并进行3次图卷积得到输出 )
        u_em = tf.nn.embedding_lookup(embedding, train_user)  # 全局图卷积后,再进行look_up
        i_em = tf.nn.embedding_lookup(embedding, train_item)
        u_em = tf.nn.l2_normalize(u_em, -1)  #l2 norm
        i_em = tf.nn.l2_normalize(i_em, -1)
        u_em = tf.reshape(u_em, (-1, neg_size, self.dim)) # 把n条张样本分成 m组每组neg_size个  u_em (batch,neg_size,128)
        i_em = tf.reshape(i_em, (-1, neg_size, self.dim)) # 把n条张样本分成 m组每组neg_size个  i_em (batch,neg_size,128)
        # 同行相乘s为其样本,i,j,j为正样本
        logits = tf.einsum("itd,isd->its", u_em, i_em) / 0.06 - i_weight  #(n,neg,neg)
        pos_logits = tf.linalg.diag_part(logits)  # (n,neg)
        loss = - tf.reduce_mean(pos_logits)
        loss += tf.reduce_mean(tf.math.log(tf.reduce_sum(tf.exp(logits), axis=-1)))
        l2_loss = tf.nn.l2_loss(self.embedding)
    return loss, loss + l2_loss * 2e-4

说明:

  • g:是DGLGraph对象,这里面记录着节点的级联关系。
  • train_user和train_item:均为长度为6680的list,train_user[i]与train_item[i]为正样本。
  • neg_size:167  负采样个数,注意 167是能整除6680。
  • i_weight:item权重 (40, 1, 167)。记录6680item各自的权重。
  • logits:shape是[40, 167, 167],记录的是每组中,当前向量与其他样本的向量点积得分。

解释:为什么logits中i,j,j就为正样本?

1、创建向量:

        假设向量维度dim:4,neg_size:2,样本个数为6.

        u_em:       i_em:

2、分组:

        每两个为一组,把6个样本分成了3组。

        u_em:    i_em:

3、计算 u的每个样本 与 i中对应组中的所有样本的相似度:得到

    logits:

        例如u中,组1的 [0.6, 0.3, 0.7, 0.4],依次与i的组1中两个向量[0.8, 0. , 0.9, 0.2]和[0.6, 0.3, 0.8, 0.2]的点积为 0.48+0+0.63+0.08 =1.19  和 0.36+0.09+0.56+0.08=1.09 但是,这两个得分,只有1.19是正样本。

4、计算loss

        正样本+batch随机负采样loss+l2_norm

说明:

  • 实现图卷积有两种方式:原生tf 或者 DGL。DGL的优势:计算接口更灵活、性能更好、生态更好。
     
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值