论文笔记:多任务学习模型:渐进式分层提取(PLE)含pytorch实现

整理了RecSys2020 Progressive Layered Extraction : A Novel Multi-Task Learning Model for Personalized Recommendations)论文的阅读笔记

  • 背景
  • 模型
  • 代码

论文地址:PLE

背景

  多任务学习(multi-task learning,MTL):给定 m 个学习任务,这m个任务或它们的一个子集彼此相关但不完全相同。简单地说就是一个模型有多个输出对应多个任务的结果。
  多任务学习在推荐系统中已经有很多成功的应用。但是存在一些问题,文章的作者观察到了一个跷跷板现象,即一个任务的性能通常通过损害其他任务的性能来提高。当任务相关性复杂时,相应的单任务模型相比,多个任务无法同时提高。
  基于这一点,本文提出了一种渐进分层提取(PLE)模型。明确分离共享组件和特定任务组件,采用渐进式路由机制,逐步提取和分离更深层次的语义知识。

模型

  利用门结构和注意网络进行信息融合在之前的模型中已经很常见,比如MMoE,单层的MMoE如图:
在这里插入图片描述

  在这种模型中,没有任务特定的概念,所有的专家被所有的任务共享,PLE就是在MMoE的基础上修改的,在PLE中,明确地分离了任务公共参数和任务特定参数,以避免复杂任务相关性导致的参数冲突。单层的PLE(CGC模块)是这样的:
在这里插入图片描述  和MMoE的区别就很明显了,在MMoE中,所有的任务同时更新所有的专家网络,没有任务特定的概念,而在PLE中,明确分离了任务通用专家和特定任务专家,特定于任务的专家仅接受对应的任务tower梯度更新参数,而共享的专家则被多任务结果更新参数,这就使得不同类型 experts 可以专注于更高效地学习不同的知识且避免不必要的交互。另外,得益于门控网络动态地融合输入,CGC可以更灵活地在不同子任务之间找到平衡且更好地处理任务之间的冲突和样本相关性问题。
  对CGC模型进行扩展,就形成了具有多级门控网络和渐进式分离路由的广义PLE模型:在这里插入图片描述
  具体的CGC(Customized Gate Control)模型:在这里插入图片描述
  具体的PLE模型:在这里插入图片描述

代码

  由于博主不是做这个方向的,仅记录这篇文章的思想,就不推公式和实验了,PLE的代码似乎没有公开,但是在网上找了一个可用的pytorch版本,稍微调试一下就可用了,代码修改自博客【推荐系统多任务学习 MTL】PLE论文精读笔记(含代码实现)

import numpy as np
import torch
from torch import nn

'''专家网络'''
class Expert_net(nn.Module):
    def __init__(self, feature_dim, expert_dim):
        super(Expert_net, self).__init__()

        p = 0
        self.dnn_layer = nn.Sequential(
            nn.Linear(feature_dim, 256),
            nn.ReLU(),
            nn.Dropout(p),
            nn.Linear(256, expert_dim),
            nn.ReLU(),
            nn.Dropout(p)
        )

    def forward(self, x):
        out = self.dnn_layer(x)
        return out

'''特征提取层'''
class Extraction_Network(nn.Module):
    '''FeatureDim-输入数据的维数; ExpertOutDim-每个Expert输出的维数; TaskExpertNum-任务特定专家数;
       CommonExpertNum-共享专家数; GateNum-gate数(2表示最后一层,3表示中间层)'''

    def __init__(self, FeatureDim, ExpertOutDim, TaskExpertNum, CommonExpertNum, GateNum):
        super(Extraction_Network, self).__init__()

        self.GateNum = GateNum  # 输出几个Gate的结果,2表示最后一层只输出两个任务的Gate,3表示还要输出中间共享层的Gate

        '''两个任务模块,一个共享模块'''
        self.n_task = 2
        self.n_share = 1

        '''TaskA-Experts'''
        for i in range(TaskExpertNum):
            setattr(self, "expert_layer" + str(i + 1), Expert_net(FeatureDim, ExpertOutDim).cuda())
        self.Experts_A = [getattr(self, "expert_layer" + str(i + 1)) for i in
                          range(TaskExpertNum)]  # Experts_A模块,TaskExpertNum个Expert
        '''Shared-Experts'''
        for i in range(CommonExpertNum):
            setattr(self, "expert_layer" + str(i + 1), Expert_net(FeatureDim, ExpertOutDim).cuda())
        self.Experts_Shared = [getattr(self, "expert_layer" + str(i + 1)) for i in
                               range(CommonExpertNum)]  # Experts_Shared模块,CommonExpertNum个Expert
        '''TaskB-Experts'''
        for i in range(TaskExpertNum):
            setattr(self, "expert_layer" + str(i + 1), Expert_net(FeatureDim, ExpertOutDim).cuda())
        self.Experts_B = [getattr(self, "expert_layer" + str(i + 1)) for i in
                          range(TaskExpertNum)]  # Experts_B模块,TaskExpertNum个Expert

        '''Task_Gate网络结构'''
        for i in range(self.n_task):
            setattr(self, "gate_layer" + str(i + 1),
                    nn.Sequential(nn.Linear(FeatureDim, TaskExpertNum + CommonExpertNum),
                                  nn.Softmax(dim=1)).cuda())
        self.Task_Gates = [getattr(self, "gate_layer" + str(i + 1)) for i in
                           range(self.n_task)]  # 为每个gate创建一个lr+softmax

        '''Shared_Gate网络结构'''
        for i in range(self.n_share):
            setattr(self, "gate_layer" + str(i + 1),
                    nn.Sequential(nn.Linear(FeatureDim, 2 * TaskExpertNum + CommonExpertNum),
                                  nn.Softmax(dim=1)).cuda())
        self.Shared_Gates = [getattr(self, "gate_layer" + str(i + 1)) for i in range(self.n_share)]  # 共享gate

    def forward(self, x_A, x_S, x_B):
        '''Experts_A模块输出'''
        Experts_A_Out = [expert(x_A) for expert in self.Experts_A]  #
        Experts_A_Out = torch.cat(([expert[:, np.newaxis, :] for expert in Experts_A_Out]),
                                  dim=1)  # 维度 (bs,TaskExpertNum,ExpertOutDim)
        '''Experts_Shared模块输出'''
        Experts_Shared_Out = [expert(x_S) for expert in self.Experts_Shared]  #
        Experts_Shared_Out = torch.cat(([expert[:, np.newaxis, :] for expert in Experts_Shared_Out]),
                                       dim=1)  # 维度 (bs,CommonExpertNum,ExpertOutDim)
        '''Experts_B模块输出'''
        Experts_B_Out = [expert(x_B) for expert in self.Experts_B]  #
        Experts_B_Out = torch.cat(([expert[:, np.newaxis, :] for expert in Experts_B_Out]),
                                  dim=1)  # 维度 (bs,TaskExpertNum,ExpertOutDim)

        '''Gate_A的权重'''
        Gate_A = self.Task_Gates[0](x_A)  # 维度 n_task个(bs,TaskExpertNum+CommonExpertNum)
        '''Gate_Shared的权重'''
        if self.GateNum == 3:
            Gate_Shared = self.Shared_Gates[0](x_S)  # 维度 n_task个(bs,2*TaskExpertNum+CommonExpertNum)
        '''Gate_B的权重'''
        Gate_B = self.Task_Gates[1](x_B)  # 维度 n_task个(bs,TaskExpertNum+CommonExpertNum)

        '''GateA输出'''
        g = Gate_A.unsqueeze(2)  # 维度(bs,TaskExpertNum+CommonExpertNum,1)
        experts = torch.cat([Experts_A_Out, Experts_Shared_Out],
                            dim=1)  # 维度(bs,TaskExpertNum+CommonExpertNum,ExpertOutDim)
        Gate_A_Out = torch.matmul(experts.transpose(1, 2), g)  # 维度(bs,ExpertOutDim,1)
        Gate_A_Out = Gate_A_Out.squeeze(2)  # 维度(bs,ExpertOutDim)
        '''GateShared输出'''
        if self.GateNum == 3:
            g = Gate_Shared.unsqueeze(2)  # 维度(bs,2*TaskExpertNum+CommonExpertNum,1)
            experts = torch.cat([Experts_A_Out, Experts_Shared_Out, Experts_B_Out],
                                dim=1)  # 维度(bs,2*TaskExpertNum+CommonExpertNum,ExpertOutDim)
            Gate_Shared_Out = torch.matmul(experts.transpose(1, 2), g)  # 维度(bs,ExpertOutDim,1)
            Gate_Shared_Out = Gate_Shared_Out.squeeze(2)  # 维度(bs,ExpertOutDim)
        '''GateB输出'''
        g = Gate_B.unsqueeze(2)  # 维度(bs,TaskExpertNum+CommonExpertNum,1)
        experts = torch.cat([Experts_B_Out, Experts_Shared_Out],
                            dim=1)  # 维度(bs,TaskExpertNum+CommonExpertNum,ExpertOutDim)
        Gate_B_Out = torch.matmul(experts.transpose(1, 2), g)  # 维度(bs,ExpertOutDim,1)
        Gate_B_Out = Gate_B_Out.squeeze(2)  # 维度(bs,ExpertOutDim)

        if self.GateNum == 3:
            return Gate_A_Out, Gate_Shared_Out, Gate_B_Out
        else:
            return Gate_A_Out, Gate_B_Out


class PLE(nn.Module):
    # FeatureDim-输入数据的维数;ExpertOutDim-每个Expert输出的维数;TaskExpertNum-任务特定专家数;CommonExpertNum-共享专家数;n_task-任务数(gate数)
    def __init__(self, FeatureDim, ExpertOutDim, TaskExpertNum, CommonExpertNum, n_task=2):
        super(PLE, self).__init__()
        # self.FeatureDim = x.shape[1]

        '''一层Extraction_Network,一层CGC'''
        self.Extraction_layer1 = Extraction_Network(FeatureDim, ExpertOutDim, TaskExpertNum, CommonExpertNum, GateNum=3)
        self.CGC = Extraction_Network(ExpertOutDim, ExpertOutDim, TaskExpertNum, CommonExpertNum, GateNum=2)

        '''TowerA'''
        p1 = 0
        hidden_layer1 = [64, 32]
        self.tower1 = nn.Sequential(
            nn.Linear(ExpertOutDim, hidden_layer1[0]),
            nn.ReLU(),
            nn.Dropout(p1),
            nn.Linear(hidden_layer1[0], hidden_layer1[1]),
            nn.ReLU(),
            nn.Dropout(p1),
            nn.Linear(hidden_layer1[1], 1))
        '''TowerB'''
        p2 = 0
        hidden_layer2 = [64, 32]
        self.tower2 = nn.Sequential(
            nn.Linear(ExpertOutDim, hidden_layer2[0]),
            nn.ReLU(),
            nn.Dropout(p2),
            nn.Linear(hidden_layer2[0], hidden_layer2[1]),
            nn.ReLU(),
            nn.Dropout(p2),
            nn.Linear(hidden_layer2[1], 1))

    def forward(self, x):
        Output_A, Output_Shared, Output_B = self.Extraction_layer1(x, x, x)
        Gate_A_Out, Gate_B_Out = self.CGC(Output_A, Output_Shared, Output_B)
        out1 = self.tower1(Gate_A_Out)
        out2 = self.tower2(Gate_B_Out)

        return out1, out2

        return Gate_A_Out, Gate_B_Out

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

京东广告算法架构体系建设--在线模型系统分布式异构计算演变 | 京东零售广告技术团队

一、现状介绍 算法策略在广告行业中起着重要的作用,它可以帮助广告主和广告平台更好地理解用户行为和兴趣,从而优化广告投放策略,提高广告点击率和转化率。模型系统作为承载算法策略的载体,目前承载搜索、推荐、首焦、站外等众多广…

2024 新年HTML5+Canvas制作3D烟花特效(附源码)

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

Demo: 前端生成条形码并打印

前端生成条形码并打印 安装依赖&#xff1a; npm i print-js // 打印 npm i jsbarcode // 生成条形码 <template><div id"printContent" style"display: none;"><div id"elTable"><div class"name">名称&…

解决import Jetson.GPIO报错“权限错误”

在导入Jetson.GPIO模块时出现权限错误&#xff0c;可能是由于缺少适当的权限或设备权限问题。以下是一些建议&#xff1a; 使用sudo&#xff1a; 尝试使用sudo来运行你的Python脚本或解释器&#xff0c;以获取足够的权限&#xff1a; sudo python your_script.py请注意&#xf…

春节运维手册:自动巡检、应急预案和管家值守哪个更香?

春节假期就要来啦&#xff0c;在气氛组的不懈努力下&#xff0c;想要放假过年的心达到了顶峰&#xff0c;但总有工作离不开我&#xff0c;回家后还被Q&#xff0c;总不能视而不见吧&#xff1f;想要get不被工作打扰的假期&#xff0c;作为资深运维工程师&#xff0c;怎么可能没…

Easy-Es操作Elasticsearch

文章目录 1 Easy-Es1.1 简介1.2 MySQL与Easy-Es语法对比1.3 集成及配置1.3.1 pom.xml1.3.2 配置 1.4 使用1.4.1 注解的使用1.4.2 EsMapper接口1.4.3 简单搜索 1.5 使用案例1.5.1 综合商品搜索1.5.2 相关商品推荐1.5.3 聚合搜索商品相关信息 1 Easy-Es 使用过Spring Data操作ES…

图灵之旅--ArrayList顺序表LinkedList链表栈Stack队列Queue

目录 线性表顺序表ArrayList简介ArrayList使用ArrayList的构造ArrayList常见操作ArrayList的遍历ArrayList的扩容机制利用ArrayList洗牌ArrayList的优缺点 链表链表的实现双向链表的实现 LinkedListLinkedList引入LinkedList的使用LinkedList的构造LinkedList的常用方法介绍Lin…

优质硬盘检测工具SMART Utility,保障您的Mac数据安全

在日常使用Mac电脑的过程中&#xff0c;我们经常会存储大量的重要数据&#xff0c;如照片、文档、视频等。然而&#xff0c;硬盘故障却是一件令人头疼的事情&#xff0c;可能会导致数据丢失、系统崩溃等严重后果。为了保障您的数据安全&#xff0c;我们推荐一款专业的硬盘检测工…

260:vue+openlayers 通过webgl方式加载矢量图层

第260个 点击查看专栏目录 本示例介绍如何在vue+openlayers中通过webgl方式加载矢量图层。在做这个示例的时候,采用vite的方式而非webpack的方式。这里的基础设置需要改变一下。 ol的版本7.5.2或者更高。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文…

matlab appdesigner系列-仪器仪表4-开关、开关(切换)、开关(翘板)

开关、开关&#xff08;切换&#xff09;、开关&#xff08;翘板&#xff09;&#xff0c;可进行On和Off两种状态切换 示例&#xff1a;开关开启时&#xff0c;可通过滑块调整表盘数值&#xff0c;并有提示框提示 开关关闭时&#xff0c;滑块、表盘数值清零&#xff0c;并有提…

30s学会JAVA几个关键词

1.final&#xff08;最终&#xff09; 修饰类-》此类无法被继承 修饰方法-》该方法不可被重写 修饰属性和局部变量-》看作常量&#xff0c;赋值位置&#xff1a;显式初始化&#xff0c;代码块初始化&#xff0c;构造器初始化 2.super(继承子类可用) 1.在子类方法或构造器中…

CentOS网络配置进阶:深入研究network服务和NetworkManager

前言 如果你正在使用CentOS系统,并且想要深入了解网络管理和配置,那么本文肯定适合你!在这篇文章中,作者深入探讨了CentOS中的两种网络管理方式:network服务和NetworkManager。通过详实的讲解和实用的示例,你将会学习到如何使用这两种工具来管理网络接口、配置IP地址、网…

故障诊断 | 一文解决,LSTM长短期记忆神经网络故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断模型 | Maltab实现LSTM长短期记忆神经网络故障诊断 专栏介绍 订阅【故障诊断】专栏,不定期更新机器学习和深度学习在故障诊断中的应用;订阅

Enzo Life Sciences:NUCLEAR-ID®系列染料

Enzo Life Sciences公司的NUCLEAR-ID Blue DNA stain (GFP-CERTIFIED)和NUCLEAR-ID Red DNA Stain是细胞渗透性染料&#xff0c;适用于活细胞的细胞核染色。这系列染料为通过流式细胞术研究细胞周期进程的诱导和抑制提供了一种简便方法。该试剂在活细胞研究中的潜在应用包括确…

UI动效如何通过ps放到贴图模板里导出gif效果图

经常看到设计网站上有将UI动效在好看的模板里进行展示的&#xff0c;效果非常棒&#xff01;很多设计师应该都可以做出好看的UI动效动画效果&#xff0c;但不知道怎么把动效放到手机模板里进行更好的展示。 这篇教程就是帮你把制作好的动效动画通过ps放到好看的模板里&#xf…

负载均衡下Webshell连接思路及难点

君衍. 一、应用场景二、环境搭建三、思路以及难点1、查看内部结构2、查看webshell3、使用蚁剑进行连接4、难点1 shell文件上传问题5、难点2 命令执行时飘逸6、难点3 大工具上传失败7、难点4 脚本失效 四、解决方式1、关闭对方节点服务器2、基于IP地址判断是否执行3、脚本实现流…

【重磅发布】已开放!模型师入驻、转格式再升级、3D展示框架全新玩法…

1月23日&#xff0c;老子云正式发布全新版本。此次新版本包含多板块功能上线和升级&#xff0c;为用户带来了含模型师入驻、三维格式在线转换升级、模型免费增值权益开放、全新3D展示框架等一系列精彩内容&#xff01; 1月23日&#xff0c;老子云正式发布全新版本。此次新版本…

【英语趣味游戏】填字谜(Crossword)第2天

谜题出处 柯林斯字谜大全&#xff08;6&#xff09;&#xff0c;Collins——Big Book of Crosswords (Book 6) Puzzle Number: 115 本期单词 横向 1、Fetch (8) 拿&#xff0c;取&#xff0c;8个字母 答案&#xff1a;Retrieve&#xff0c;取到&#xff0c;拿回 5、Common s…

【Java程序设计】【C00171】基于SSM的智慧篮球馆预约管理系统(论文+PPT)

基于SSM的智慧篮球馆预约管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的智慧篮球馆预约管理系统 本系统分为前台、管理员以及学生3个功能模块。 前台&#xff1a;当游客打开系统的网址后&#xff0c;首先看到…

Python网络爬虫实战——实验3:Python爬虫之文字验证码实战

【实验内容】 本实验主要介绍在网络爬虫数据采集的过程中出现的常见的验证码反爬手段以及解决措施。 【实验目的】 1、理解验证码反爬的背景&#xff1b; 2、掌握常见文字验证码反爬手段&#xff1b; 3、研究解决文字验证码反爬的方法&#xff1b; 【实验步骤】 步骤1 调研…