Datawhale组队学习课节3:手把手教你读推荐论文-SR-GNN

手把手教你读推荐论文-SR-GNN

论文理解,参考沈向洋论文十问

  1. 论文试图解决什么问题?
    序列推荐中,序列与序列之间相关性建模不足

  2. 这是否是一个新的问题?
    这不是一个新的问题,但是一种新的解决方案

  3. 这篇文章要验证一个什么科学假设?
    不同的序列之间存在着相关关系,可以更精确的生成商品表征

  4. 有哪些相关研究?如何归类?谁是这一课题在领域内值得关注的研究员?
    归类为序列推荐问题,Dietmar Jannach, Hongzhi Yin

  5. 论文中提到的解决方案之关键是什么?
    把浏览序列建模为序列图,利用门控图神经网络和注意力机制,同时建模长期偏好和当前兴趣

  6. 论文中的实验是如何设计的?
    控制embedding维度=100,将后续几天的会话设置为Yoochoose的测试集,将后续几周的会话设置为Diginetiva的测试集。

  7. 用于定量评估的数据集是什么?代码有没有开源?
    Yoochoose http://2015.recsyschallenge.com/challege.html 和Diginetiva http://cikm2016.cs.iupui.edu/cikm-cup ,有开源https://github.com/CRIPAC-DIG/SR-GNN

  8. 论文中的实验及结果有没有很好地支持需要验证的科学假设?
    有,文中的消融实验证明了同时建模长期偏好和当前兴趣可以带来增益

  9. 这篇论文到底有什么贡献?
    将图模型融入到序列推荐中,将会话的长期偏好和当前兴趣结合起来,从而更好地预测用户的下一步行动。

  10. 下一步呢?有什么工作可以继续深入?
    感觉仅靠时间来划分session不太合理,应该有一些更好的能表征用户兴趣转移的节点来划分比较合适

代码工程学习

主要是学习了GatedGNN

class GatedGNN(nn.Layer):
    #省略init
    def GNNCell(self, A, hidden):
    	#常规的 H =  AWX + B
        input_in = paddle.matmul(A[:, :, :A.shape[1]], self.linear_edge_in(hidden)) + self.b_iah
        input_out = paddle.matmul(A[:, :, A.shape[1]:], self.linear_edge_out(hidden)) + self.b_ioh
        # [batch_size, max_session_len, embedding_size * 2]
        # 这里融和不同方向的图表征,打比赛的时候看前排用过,应该比之间变成无向图效果会好。
        inputs = paddle.concat([input_in, input_out], 2)

        # gi.size equals to gh.size, shape of [batch_size, max_session_len, embedding_size * 3]
        # 这就是Gated模块
        # 下面两行其实等价于 Linear层
        gi = paddle.matmul(inputs, self.w_ih) + self.b_ih
        gh = paddle.matmul(hidden, self.w_hh) + self.b_hh
        # (batch_size, max_session_len, embedding_size)
        i_r, i_i, i_n = gi.chunk(3, 2)
        h_r, h_i, h_n = gh.chunk(3, 2)
        reset_gate = F.sigmoid(i_r + h_r)
        input_gate = F.sigmoid(i_i + h_i)
        new_gate = paddle.tanh(i_n + reset_gate * h_n)
        hy = (1 - input_gate) * hidden + input_gate * new_gate
        return hy

    def forward(self, A, hidden):
        for i in range(self.step):
            hidden = self.GNNCell(A, hidden)
        return hidden

评测细节:之前老是把recall和hitrate弄混,从这个代码来看,recall更多是针对item的,hitrate更多是以user为单位,这下分清了。

def evaluate(preds,test_gd, topN=50):
    total_recall = 0.0
    total_ndcg = 0.0
    total_hitrate = 0
    for user in test_gd.keys():
        recall = 0
        dcg = 0.0
        item_list = test_gd[user]
        for no, item_id in enumerate(item_list):
            if item_id in preds[user][:topN]:
                recall += 1
                dcg += 1.0 / math.log(no+2, 2)
            idcg = 0.0
            for no in range(recall):
                idcg += 1.0 / math.log(no+2, 2)
        total_recall += recall * 1.0 / len(item_list)
        if recall > 0:
            total_ndcg += dcg / idcg
            total_hitrate += 1
    total = len(test_gd)
    recall = total_recall / total
    ndcg = total_ndcg / total
    hitrate = total_hitrate * 1.0 / total
    return {f'recall@{topN}': recall, f'ndcg@{topN}': ndcg, f'hitrate@{topN}': hitrate}

你可能感兴趣的:(学习,深度学习)