序列召回基础+GRU4Rec论文阅读

news2025/1/14 10:11:38

1. 推荐系统简介

        推荐系统,即就是为当用户推荐一些他感兴趣的项目、商品、视频等等,当然在对于小的项目库中能进行很快的推荐,但是随着不断的增加,数据量剧增,这时候就需要我们进行分步骤进行推荐,这就把推荐系统细分为四个部分:召回、粗排、精排、重排

ef0663c812b549d99e6573e8a193472f.png

         (1)召回:待计算的候选集合大、计算速度快、模型简单、特征较少时,保证用户相关物品的召回率。

        (2)精排:获得精准的排序结果

        (3)重排:对排序的结果进行多样化考虑,提高用户的使用体验

1.1 推荐系统中的召回

        召回算法的核心:

算法结构简单

计算效率高

准确率不需要太高

每一种召回算法都会针对性解决某一类问题

        具体召回算法可以分为以下类别:

基于规则

基于协同过滤

向量召回

1.1.1 基于规则的召回算法

        基于项目item被点击的次数、购买的次数等等对项目进行召回,但是这种算法需要消耗极强的业务理解和极大的人力投入

1.1.2 基于协同过滤的召回算法

        (1)基于统计的协同过滤

                分为两种:

                基于User的协同过滤:相似的用户可能喜欢相同物品

                基于item的协同过滤:相似的物品可能被同个用户喜欢

        (2)基于MF的协同过滤

4d19da9306514851b7674aa0129c69af.png

                计算User-Item的交互概率 

1.1.3 基于向量召回的召回算法

        (1)核心:通过某种算法生产出Item的向量表征,然后通过向量的相似度来进行召回

        (2)序列召回:通过提取用户的序列特征来生产User的向量表征,然后将User的向量在全部的Item向量中进行召回

2. 基于GRU4Rec的基础序列召回

2.1 GRU

ba041f01abcc4b4f83318931efb2caaf.png

注意:序列中的每一个节点都是一个向量

2.1.1 通过RNN提取出输入序列的特征:

        (1)取出gif.latex?y%5En的向量表征作为序列的特征,这里可以认为gif.latex?y%5En包含了gif.latex?x%5E1%2C%20x%5E2%2C%20...%2C%20x%5En的所有信息,所有可以简单的认为gif.latex?y%5En的结果代表序列的表征。

        (2)对每一个时间步的特征输出做一个Mean Pooling,也就是对gif.latex?Y%20%3D%20%5By%5E1%2Cy%5E2%2C...%2Cy%5En%5D做均值处理,以此得到序列的表征。

2.1.2 GRU的计算逻辑

01da4d201211478c9689fc2e156111ed.png

3. 代码实践——基于Faiss的向量召回

        这里主要是对主要的模型网络层框架进行展示,其中代码来自百度飞浆课程——手把手教你读推荐论文:序列召回基础。

3.1 基础序列召回模型定义

class GRU4Rec(nn.Layer):
    def __init__(self, config):
        # 定义参数以及网络层的维度变换
        super(GRU4Rec, self).__init__()
        # 导入config
        self.config = config
        # embedding的维度 = 16
        self.embedding_dim = self.config['embedding_dim']
        # 最大长度max_length = 20
        self.max_length = self.config['max_length']
        # n_items = 15406
        self.n_items = self.config['n_items']
        # num_layers = 1
        self.num_layers = self.config['num_layers']
        
        # 项目过embedding:15406——>16
        self.item_emb = nn.Embedding(self.n_items, self.embedding_dim, padding_idx=0)
        # 过GRU
        self.gru = nn.GRU(
            # 输入层维度=16
            input_size=self.embedding_dim,
            # 隐藏层维度=16
            hidden_size=self.embedding_dim,
            # 网络层=1
            num_layers=self.num_layers,
            time_major=False,
        )
        # 损失函数
        self.loss_fun = nn.CrossEntropyLoss()
        # 对参数进行初始化
        self.reset_parameters()

    # 计算loss
    def calculate_loss(self,user_emb,pos_item):
        all_items = self.item_emb.weight
        # transpose()函数的作用就是调换数组的行列值的索引值,类似于求矩阵的转置
        scores = paddle.matmul(user_emb, all_items.transpose([1, 0]))
        return self.loss_fun(scores,pos_item)

    # 输出项目emb的权重
    def output_items(self):
        return self.item_emb.weight

    # 使用优化器对参数进行更新
    def reset_parameters(self, initializer=None):
        for weight in self.parameters():
            paddle.nn.initializer.KaimingNormal(weight)

    # 正向传播
    def forward(self, item_seq, mask, item, train=True):
        # 将项目过embedding
        seq_emb = self.item_emb(item_seq)
        # 过gru
        seq_emb,_ = self.gru(seq_emb)
        # 去最后一层隐藏层的输出作为user的embedding
        user_emb = seq_emb[:,-1,:] #取GRU输出的最后一个Hidden作为User的Embedding
        # 计算损失,对于不同的数据集传回不同
        if train:
            loss = self.calculate_loss(user_emb,item)
            output_dict = {
                'user_emb':user_emb,
                'loss':loss
            }
        else:
            output_dict = {
                'user_emb':user_emb
            }
        return output_dict

3.2  基于Faiss的向量召回

def get_predict(model, test_data, hidden_size, topN=20):

    item_embs = model.output_items().cpu().detach().numpy()
    item_embs = normalize(item_embs, norm='l2')
    gpu_index = faiss.IndexFlatIP(hidden_size)
    gpu_index.add(item_embs)
    
    test_gd = dict()
    preds = dict()
    
    user_id = 0

    for (item_seq, mask, targets) in tqdm(test_data):

        # 获取用户嵌入
        # 多兴趣模型,shape=(batch_size, num_interest, embedding_dim)
        # 其他模型,shape=(batch_size, embedding_dim)
        user_embs = model(item_seq,mask,None,train=False)['user_emb']
        user_embs = user_embs.cpu().detach().numpy()

        # 用内积来近邻搜索,实际是内积的值越大,向量越近(越相似)
        if len(user_embs.shape) == 2:  # 非多兴趣模型评估
            user_embs = normalize(user_embs, norm='l2').astype('float32')
            D, I = gpu_index.search(user_embs, topN)  # Inner Product近邻搜索,D为distance,I是index
#             D,I = faiss.knn(user_embs, item_embs, topN,metric=faiss.METRIC_INNER_PRODUCT)
            for i, iid_list in enumerate(targets):  # 每个用户的label列表,此处item_id为一个二维list,验证和测试是多label的
                test_gd[user_id] = iid_list
                preds[user_id] = I[i,:]
                user_id +=1
        else:  # 多兴趣模型评估
            ni = user_embs.shape[1]  # num_interest
            user_embs = np.reshape(user_embs,
                                   [-1, user_embs.shape[-1]])  # shape=(batch_size*num_interest, embedding_dim)
            user_embs = normalize(user_embs, norm='l2').astype('float32')
            D, I = gpu_index.search(user_embs, topN)  # Inner Product近邻搜索,D为distance,I是index
#             D,I = faiss.knn(user_embs, item_embs, topN,metric=faiss.METRIC_INNER_PRODUCT)
            for i, iid_list in enumerate(targets):  # 每个用户的label列表,此处item_id为一个二维list,验证和测试是多label的
                recall = 0
                dcg = 0.0
                item_list_set = []

                # 将num_interest个兴趣向量的所有topN近邻物品(num_interest*topN个物品)集合起来按照距离重新排序
                item_list = list(
                    zip(np.reshape(I[i * ni:(i + 1) * ni], -1), np.reshape(D[i * ni:(i + 1) * ni], -1)))
                item_list.sort(key=lambda x: x[1], reverse=True)  # 降序排序,内积越大,向量越近
                for j in range(len(item_list)):  # 按距离由近到远遍历推荐物品列表,最后选出最近的topN个物品作为最终的推荐物品
                    if item_list[j][0] not in item_list_set and item_list[j][0] != 0:
                        item_list_set.append(item_list[j][0])
                        if len(item_list_set) >= topN:
                            break
                test_gd[user_id] = iid_list
                preds[user_id] = item_list_set
                user_id +=1
    return test_gd, preds

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}

# 指标计算
def evaluate_model(model, test_loader, embedding_dim,topN=20):
    test_gd, preds = get_predict(model, test_loader, embedding_dim, topN=topN)
    return evaluate(preds, test_gd, topN=topN)

4. GRU4Rec论文阅读(SESSION-BASED RECOMMENDATIONS WITH RECURRENT NEURAL NETWORKS)

4.1 主要工作

        这篇论文主要是讲RNNs应用于推荐系统领域,并提出了一种基于RNN的基于会话的建议的方法,并为了考虑更加实际的方面,在经典的RNNs基础上进行了一定的修改,如:对排名损失函数进行一些修改。

We therefore propose an RNN-based approach for session-based recommendations. Our approach also considers practical aspects of the task and introduces several modififications to classic RNNs such as a ranking loss function that make it more viable for this specifific problem.Experimental results on two data-sets show marked improvements over widely
used approaches.

4.2 相关工作

        这里提到了推荐系统领域现有的两种占主要地位的方法——factor models和neighborhood methods。

4.2.1 factor models

        将推荐问题视为一个矩阵补全/重构问题,然后利用潜在因子向量来填充缺失的项。(未在基于会话的推荐中应用)

Factor models work by decomposing the sparse user-item interactions matrix to a set
of d dimensional vectors one for each item and user in the dataset. The recommendation problem is then treated as a matrix completion/reconstruction problem whereby the latent factor vectors are then used to fifill the missing entries by e.g. taking the dot product of the corresponding user–item latent factors.

4.2.2 neighborhood methods

        计算项目(或用户)之间的相似性。(在基于会话的建议中已被广泛应用)

 

neighborhood methods, which rely on computing similarities between items (or users) are based on co-occurrences of items in sessions (or user profifiles). Neighborhood methods have been used extensively in session-based recommendations.

4.3 RNNs模型公式

gif.latex?h_t%3Dg%28Wx_t+Uh_%7Bt-1%7D%29
gif.latex?h_t%3D%281-z_t%29h_%7Bt-1%7D+z_t%5Cwidehat%7Bh%7D_t

gif.latex?z_t%3D%5Csigma%20%28W_zx_t+U_zh_%7Bt-1%7D%29
gif.latex?%5Cwidehat%7Bh%7D_t%3Dtanh%28Wx_t+U%28r_t%5Codot%20h_%7Bt-1%7D%29%29

gif.latex?r_t%3D%5Csigma%20%28W_rx_t+U_rh_%7Bt-1%7D%29

4.4 网络的总体架构——CUSTOMIZING THE GRU MODEL

        基于上面介绍的两种方法存在的优点以及不足,论文提出了一个基于RNNs的会话推荐模型。

        (1)输入时进行one-hot编码;

        (2)过一层embedding层;

        (3)将过embedding后的结果输入到GRU网络层(输入的时候可以输出到更深层的GRU网络层);

        (4)输出经过一个前馈神经网络层。

463f1b3b49c54b73964edee48c5dabb0.png

 General architecture of the network. Processing of one event of the event stream at once.

        以下是本文对传统的RNNs进行的一些修改 

 4.4.1 SESSION-PARALLEL MINI-BATCHES

        为了更好的并行计算,论文采用了 mini-batch 的处理,即把不同的session拼接起来:

a26f6960cef541da938e3ccf0177c5eb.png

4.4.2 SAMPLING ON THE OUTPUT

        (1)根据项目的受欢迎程度的比例进行抽样。

        (2)基于流行度的抽样,因为一个项目出现在小批量的其他训练例子中的可能性与它的受欢迎程度成正比。

4.4.3 RANKING LOSS

        (1)BPR

gif.latex?L_s%3D-%5Cfrac%7B1%7D%7BN_s%7D%5Ccdot%20%5Csum_%7Bj%3D1%7D%5E%7BN_s%7Dlos%28%5Csigma%20%28%5Cwidehat%7Br%7D_%7Bs%2Ci%7D-%5Cwidehat%7Br_%7Bs%2Cj%7D%7D%29%29

        (2)TOP1

 gif.latex?L_s%3D%5Cfrac%7B1%7D%7BN_s%7D%5Ccdot%20%5Csum_%7Bj%3D1%7D%5E%7BN_s%7D%5Csigma%20%28%5Cwidehat%7Br%7D_%7Bs%2Cj%7D-%5Cwidehat%7Br%7D_%7Bs%2Ci%7D%29+%5Csigma%20%28%5Cwidehat%7Br%7D%5E2_%7Bs%2Cj%7D%29

 

 

飞桨AI Studio - 人工智能学习与实训社区 (baidu.com)​​​​​​

https://aistudio.baidu.com/aistudio/course/introduce/27783

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/19295.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring系列】- Bean生命周期底层原理

Bean生命周期底层原理 😄生命不息,写作不止 🔥 继续踏上学习之路,学之分享笔记 👊 总有一天我也能像各位大佬一样 🏆 一个有梦有戏的人 怒放吧德德 🌝分享学习心得,欢迎指正&#xf…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.6 SpringBoot 读写 Redis 的客户端

SpringBoot 【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.6 SpringBoot 读写 Redis 的客户端4.6.1 问题引入…

pytorch深度学习实战lesson21

第二十一课 卷积神经网络之池化层 卷积神经网络的一个重要概念就是池化层,一般是在卷积层之后。池化层对输入做降采样,常用的池化做法是对每个滤波器的输出求最大值,平均值,中位数等。下面我们和沐神详细学习一下池化层的原理与实…

第七章第三节:散列表(Hash Table)

文章目录教程1. 散列表(Hash Table)1.1 散列表的基本概念1.2 散列函数的构造方法1.2.1 除留佘数法1.2.2 直接定址法1.2.3 数字分析法1.2.4 平方取中法1.3 处理冲突的方法1.3.1 拉链法1.3.2 开放定址法1.3.2.1 线性探测法(常考)1.3.2.2 平方探测法1.3.2.3…

数据结构题目收录(十九)

1、在下图所示的平衡二叉树中插入关键字48后得到一棵新平衡二叉树,在新平衡二叉树中,关键字37所在结点的左、右子结点中保存的关键字分别是()。 A:13,48B:24,48C:24,53D:24,90 解析…

windows驱动开发环境搭建以及helloworld

文章目录前言编译环境-WDK的安装搭建测试驱动的虚拟机win11虚拟机win10虚拟机在测试机器上运行驱动上面驱动代码含义其他前言 参考:windows驱动开发环境搭建以及helloworld | qwertwwwe 搭建驱动环境–编写hello驱动–安装测试虚拟机–安装驱动 编译环境-WDK的安装…

web前端-第三次作业-按钮

<!DOCTYPE html> <!-- 2022/11/16 --> <html lang"ch"> <head><meta charset"UTF-8"><title>按钮</title><style>*{margin: 0;padding: 0;box-sizing: border-box;}body{display: flex;justify-content: …

AutoDWG DWG 转换 PDF 控制组件-ActiveX

AutoDWG DWG 到 PDF 控制组件&#xff0c;比以往任何时候都更快&#xff01; DWG2PDF-X &#xff0c;一个控制组件允许您直接将 dwg 转换为 pdf&#xff0c;dxf 和 dwf 直接转换为 pdf&#xff0c;不需要 AutoCAD。 主要特征&#xff1a; 支持 R2.5 到 2019 版本的 DWG、DXF 和…

关于Conversational QA 的一些调研

文章目录Paper1: Understanding User Satisfaction with Task-oriented Dialogue SystemsMotivation:Classification:Contributions:DatasetKnowledge:Paper2: Evaluating Mixed-initiative Conversational Search Systems via User SimulationMotivationClassification:Contri…

java计算机毕业设计ssm建设路小学读背兴趣任务管理系统

项目介绍 随着互联网技术的发展,计算机技术广泛应用在人们的生活中,逐渐成为日常工作、生活不可或缺的工具。目前,各种在线学习平台层出不穷。建设路小学读背兴趣任务繁重,如何快速的学习提高小学生的读背兴趣任务,是老师非常关注的问题。为小学读背兴趣任务开发必要的程序,能…

ES6 入门教程 13 Symbol 13.8 内置的 Symbol 值

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程13 Symbol13.8 内置的 Symbol 值13.8.1 Symbol.hasInstance13.8.2 Symbol.isConcatSpreadable13.8.3 Symbol.species13.8.4 …

Gillespie 随机模拟算法附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

Python最佳实践-构建自己的第三方库

移植自本人博客&#xff1a;Python最佳实践-构建自己的第三方库 Introduction 在写一个项目的时候需要用到发布订阅者模式&#xff08;又叫广播模式&#xff09;&#xff0c;于是就实现了一下&#xff0c;写完之后感觉可以封装成库&#xff0c;于是查阅了一下如何在python上开…

全自动采集软件-自动采集为原创发布工具

随着时代不停地发展。互联网无时不刻地出现在我们的生活中&#xff0c;大家也越来越注重效率&#xff0c;今天小编就给大家来分享一款全自动采集软件。只需要点几下鼠标就能轻松获取数据&#xff0c;不管是导出还是发布到网上。详细参考图片一、二、三、四&#xff01; 企业人员…

CanOpen协议的伺服驱动控制

一、CanOpen的基本介绍&#xff1a;1、基本介绍&#xff1a;CanOpen在CAN网络7层协议中&#xff0c;处于应用层。CANopen协议是在20世纪90年代末&#xff0c;由CIA组织CAN-in-Automation&#xff0c;&#xff08;http://www.can-cia.org &#xff09;在CAL&#xff08;CAN Appl…

信息论编码 | 霍尔曼编码设计MATLAB实现 两种方法 函数调用

姓名 班级 20电信 学号 2020 实验项目 实验三 霍尔曼编码 日期 2022.11 实验环境 联想电脑MATLAB R2018a版 实验内容与完成情况&#xff08;记录实验内容、操作步骤、实验结果等&#xff0c;包括系统输出的错误信息&#xff0c;以截图等方式记录实验结果&#xff09; …

吹爆,这份有思路有案例能落地的SpringCloud开发笔记

前言 SpringCloud想必每一位Java程序员都不会陌生&#xff0c;很多人一度把他称之为“微服务全家桶”&#xff0c;它通过简单的注解&#xff0c;就能快速地架构微服务&#xff0c;这也是SpringCloud的最大优势。但是最近有去面试过的朋友就会发现&#xff0c;现在面试你要是没…

【毕业设计】3-基于单片机的公交车智能播报到站运行位置指示系统(原理图+源码+论文)

【毕业设计】3-基于单片机的公交车智能播报到站运行位置指示系统&#xff08;原理图源码论文&#xff09; 文章目录【毕业设计】3-基于单片机的公交车智能播报到站运行位置指示系统&#xff08;原理图源码论文&#xff09;资料下载链接任务书设计说明书摘要设计框架架构设计说明…

一个基于NetCore模块化、多租户CMS系统

今天给大家推荐一个基于.NetCore开发的、支持多租户的开源CMS系统。 项目简介 这是一个基于ASP.NET Core 构建的、模块化和多租户应用程序框架&#xff0c;采用文档数据库&#xff0c;非常高性能&#xff0c;跨平台的系统。 该项目可用于企业网站、个人博客、产品介绍网站等…

【计算机毕业设计】基于netty的网关推送平台

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过…