深度学习 - 45.MMOE Gate 简单实现 By Keras

目录

一.引言

二.MMoE 模型分析

三.MMoE 逻辑实现

• Input

• Expert Output

• Gate Output

• Weighted Sum

• Sigmoid Output

• 完整代码

四.总结


一.引言

上一篇文章介绍了 MMoE 借鉴 MoE 的思路,为每一类输出构建一个 Gate 并最终加权多个 Expert 的输出,提高了相关性不高的多任务问题,下面根据思路简易实现下 MMoE 逻辑。

 

二.MMoE 模型分析

上图为 BaseLine、MoE 与 MMoE,下面我们专门了解 MMoE 的实现细节,其中 bs 为 BatchSize,Hidden_units 代表隐层输出维度,E0、E1、E2 代表多个 Expert,Tower A、Tower B 代表 N 个输出。

这里 Gate 与 Expert 都可以理解为浅层模型。 下面针对 bs 里的一个样本,分析下 MMoE 执行过程。

• Input 

输入一个 embedding_size 长度的向量,这里也可以是 Filed 个变量,进入对应 Embedding 层 Lookup 再做 pooling,为了简单,这里直接取 1 x F,F 为 Field Size。

• Expert Output

输入向量分别经过 E1、E2、... 的 K 个 Expert 计算,得到 Expert 个输出,每个输出维度为 1 x Hidden。

• Gate output

输入向量分别经过 G1、G2、... 的 K 个 Gate 计算,得到 Expert 个输出,维度为 1 x expert,每一维代表对应 Expert Output 的权重,注意这里 Gate 最终输出需经过一层 softmax。

• Weighted Sum

将当前样本输出的 expert 分别与对应 Expert Output 加权求和作为每个任务的 Tower 的输入向量,合并后维度为 1 x hidden_units。

• Sigmoid Output

每个 Tower 最终为 sigmoid 输出的二分类深度模型,输入为 Expert x Hidden 的加权求和,维度仍然为 1 x Hidden。

Tips:

实际 BatchSize 执行时,将上述 1 x ... 换为 bs x ... 即对应 Batch 的逻辑。

三.MMoE 逻辑实现

参数设置为:

    num_field = 4
    hidden_units = 8
    num_expert = 3
    num_output = 2

4 个 Field 域、8 维输出、3 个 Expert、2 个任务。

• Input

这里 N 就是上面的 bs 即 Batch Size,F 为 Field Size,这里实现逻辑比较简单,实践场景下可以先将 Field Lookup 得到 Embedding 再 pooling 输入到后面的 Expert 和 Gate:

    # 1.构造 Input => N x F
    num_samples = 10
    inputs = np.array([np.ones(shape=num_field) for i in range(num_samples)])
    print("Input Shape:", inputs.shape)
Input Shape: (10, 4)

• Expert Output

    # 2.构建专家 kernel [(filed * hidden) x expert]
    expert_kernels = np.random.random(size=(num_field, hidden_units, num_expert))
    print("Expert Shape:", expert_kernels.shape)

    # 3.获取 Expert 输出 => [N x F] * [F x Hidden x Expert] = N x Hidden x Expert
    outputs_by_expert = tf.tensordot(inputs, expert_kernels, axes=1)
    print("Output By Expert:", outputs_by_expert.shape)
Expert Shape: (4, 8, 3)
Output By Expert: (10, 8, 3)

• Gate Output

Gate:在 Dense 输出基础上,增加 softmax 逻辑。

class Gate(Layer):

    def __init__(self, expert_num, **kwargs):
        self.expert_num = expert_num
        self.gate = None

        super(Gate, self).__init__(**kwargs)

    def build(self, input_shape):
        self.gate = Dense(self.expert_num, activation='relu', kernel_initializer=glorot_normal_initializer)

        super(Gate, self).build(input_shape)

    def call(self, _inputs, **kwargs):
        weight = self.gate(_inputs)
        _output = tf.nn.softmax(weight)
        return _output

 根据 num_output 任务输出数,决定构造 Gate 的数量,这是 MMoE 与 MoE 的区别之一。

    # 4.构建 Gate
    gate = [Gate(num_expert) for i in range(num_output)]

    # 5.获取每个任务的 Gate 输出权重 output x N x expert
    outputs_by_gate = np.array([gate[i](inputs) for i in range(num_output)])
    print("Output By Gate:", outputs_by_gate.shape)
Output By Gate: (2, 10, 3)

 

• Weighted Sum

    # 6.获取最终输出 N x output
    part_input = []
    for output_by_gate in outputs_by_gate:
        # N x Expert => N x 1 x Expert
        expand_output_by_gate = tf.expand_dims(output_by_gate, axis=1)

        # N x 1 x Expert => N x Hidden x Expert
        repeat_gate_weight = K.repeat_elements(expand_output_by_gate, hidden_units, axis=1)

        # N x Hidden x Expert
        weighted_expert_output = tf.cast(outputs_by_expert, dtype='float32') * repeat_gate_weight

        # N x Hidden
        weighted_expert_sum = tf.reduce_sum(weighted_expert_output, axis=2)
        part_input.append(weighted_expert_sum)

    print("Part Input:", np.array(part_input).shape)

原始输入样本个数 N=10,输出 hidden_size=8,任务有2个,所以每个任务获得 BS x hidden_size 即 10 x 8 的 batch 样本。 

Part Input: (2, 10, 8)

 

• Sigmoid Output

这里两个任务对应两个 Tower,之前介绍了多输出模型:TF x Keras 之多输出模型

任务架构基于 Shared-bottom Multi-task Model,实现了同时预测年龄、收入、性别的多分类问题,有兴趣的同学可以把 Shared-bottom 的架构切换为多个 Expert 再加入 Gate 即可实现基础的 MMoE,这里就不再展开了。

 

• 完整代码

import numpy as np
import tensorflow as tf
from tensorflow.python.keras.layers import *
from tensorflow.keras.layers import Layer
from tensorflow.python.ops.init_ops import glorot_normal_initializer
from tensorflow.keras import backend as K


class Gate(Layer):

    def __init__(self, expert_num, **kwargs):
        self.expert_num = expert_num
        self.gate = None

        super(Gate, self).__init__(**kwargs)

    def build(self, input_shape):
        self.gate = Dense(self.expert_num, activation='relu', kernel_initializer=glorot_normal_initializer)

        super(Gate, self).build(input_shape)

    def call(self, _inputs, **kwargs):
        weight = self.gate(_inputs)
        _output = tf.nn.softmax(weight)
        return _output


def MMOE(num_field, hidden_units, num_expert, num_output):
    # 1.构造 Input => N x F
    num_samples = 10
    inputs = np.array([np.ones(shape=num_field) for i in range(num_samples)])
    print("Input Shape:", inputs.shape)

    # 2.构建专家 kernel [(filed * hidden) x expert]
    expert_kernels = np.random.random(size=(num_field, hidden_units, num_expert))
    print("Expert Shape:", expert_kernels.shape)

    # 3.获取 Expert 输出 => [N x F] * [F x Hidden x Expert] = N x Hidden x Expert
    outputs_by_expert = tf.tensordot(inputs, expert_kernels, axes=1)
    print("Output By Expert:", outputs_by_expert.shape)

    # 4.构建 Gate
    gate = [Gate(num_expert) for i in range(num_output)]

    # 5.获取每个任务的 Gate 输出权重 output x N x expert
    outputs_by_gate = np.array([gate[i](inputs) for i in range(num_output)])
    print("Output By Gate:", outputs_by_gate.shape)

    # 6.获取最终输出 N x output
    part_input = []
    for output_by_gate in outputs_by_gate:
        # N x Expert => N x 1 x Expert
        expand_output_by_gate = tf.expand_dims(output_by_gate, axis=1)

        # N x 1 x Expert => N x Hidden x Expert
        repeat_gate_weight = K.repeat_elements(expand_output_by_gate, hidden_units, axis=1)

        # N x Hidden x Expert
        weighted_expert_output = tf.cast(outputs_by_expert, dtype='float32') * repeat_gate_weight

        # N x Hidden
        weighted_expert_sum = tf.reduce_sum(weighted_expert_output, axis=2)
        part_input.append(weighted_expert_sum)

    print("Part Input:", np.array(part_input).shape)


if __name__ == '__main__':
    num_field, hidden_units, num_expert, num_output = 4, 8, 3, 2
    MMOE(num_field, hidden_units, num_expert, num_output)

四.总结

MMoE 几个 Expert 最终输出维度相同,Gate 输出维度与 Expert 数量相同,通过分析 Gate 的输出概率可以看出不同 Expert 对不同 Output 的测出,也可以控制 loss_weights 显式的指定某个 Output 占据主导地位。

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

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

相关文章

05 KVM虚拟化Linux Bridge环境部署

文章目录 05 KVM虚拟化Linux Bridge环境部署5.1 安装Linux Bridge5.1.1 安装bridge-utils软件包5.1.2 确认安装是否成功 5.2 配置Linux Bridge5.2.1 创建网桥br05.2.2 将物理网卡ens33绑定到Linux Bridge5.2.3 配置ens33的ip5.2.4 为Linux Bridge网桥br0分配ip5.2.4.1 DHCP设置…

sin(x) + cos(x) 的极大值和极小值

sinx cosx 的极大值和极小值 理论推导图像 今天遇到了一个问题,就是如何求解 sin ⁡ x cos ⁡ x \sin{x} \cos{x} sinxcosx 的极大值和极小值。这里特来记录一下。 理论推导 首先,我们假设: sin ⁡ x cos ⁡ x R sin ⁡ ( x α ) (…

Vue(Vue脚手架)

一、使用Vue脚手架(Vue Cli) Vue官方提供脚手架平台选择最新版本: 可以相加兼容的标准化开发工具(开发平台) 禁止:最新的开发技术版本和比较旧版本的开发平台 Vue CLI🛠️ Vue.js 开发的标准工…

所有知识付费都可以用 ChatGPT 再割一次?

伴随春天一起到来的,还有如雨后春笋般冒出的 ChatGPT / AI 相关的付费社群、课程训练营、知识星球等。 ChatGPT 吹来的这股 AI 热潮,这几个月想必大家多多少少都能感受到。 ▲ 图片来源:网络 这两张图是最近在圈子里看到的。 一张是国内各…

第五章——动态规划3

蒙德里安的梦想 我们在黑框内横着放红框,我们发现当横向小方格摆好之后,纵向小方格只能一次纵向摆好,即纵向小方格只有一种方案,即整个摆放小方格的方案数等于横着摆放小方格的方案数 f[i,j]表示的是现在要在第i列摆,j…

MyBats

一、MyBatis简介 1. MyBatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github。 iBatis一词来…

Packet Tracer - 研究直连路由

Packet Tracer - 研究直连路由 目标 第 1 部分:研究 IPv4 直连路由 第 2 部分:研究 IPv6 直连路由 拓扑图 背景信息 本活动中的网络已配置。 您将登录路由器并使用 show 命令发现并回答以下有关直连路由的问题。 注:用户 EXEC 密码是 c…

通用智能的瓶颈及可能的解决途径

通用智能是指能够在各种不同的任务和环境中灵活地适应和执行任务的智能。通用智能与特定任务的智能相反,后者只能在特定领域或任务中表现出色。通用智能的理论基础是人工智能领域的通用人工智能(AGI)研究,旨在设计出能够像人类一样…

三分钟看懂Python分支循环规范:if elif for while

人生苦短,我用python 分支与循环 条件是分支与循环中最为核心的点, 解决的问题场景是不同的问题有不同的处理逻辑。 当满足单个或者多个条件或者不满足条件进入分支和循环, 这里也就说明这个对相同问题处理执行逻辑依据具体参数动态变化&…

从0搭建Vue3组件库(四): 如何开发一个组件

本篇文章将介绍如何在组件库中开发一个组件,其中包括 如何本地实时调试组件如何让组件库支持全局引入如何在 setup 语法糖下给组件命名如何开发一个组件 目录结构 在packages目录下新建components和utils两个包,其中components就是我们组件存放的位置,而utils包则是存放一些…

史上最全Maven教程(五)

文章目录 🔥Maven聚合案例_搭建dao模块🔥Maven聚合案例_搭建service模块🔥Maven聚合案例_搭建web模块🔥Maven聚合案例_运行项目🔥依赖传递失效及解决方案 🔥Maven聚合案例_搭建dao模块 dao子工程中一般写实…

055:cesium两种方法加载天地影像图

第055个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中用两种方法加载天地影像图。一种是利用WebMapTileServiceImageryProvider,另一种是利用UrlTemplateImageryProvider. 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方…

面试题30天打卡-day14

1、线程的生命周期是什么,线程有几种状态,什么是上下文切换? 线程通常有五种状态:创建,就绪,运行、阻塞和死亡状态。 新建状态(New):新创建了一个线程对象。就绪状态&am…

controlnet1.1模型和预处理器功能详解(各预处理器出稿对比及对应模型说明)

ControlNet 1.1 与 ControlNet 1.0 具有完全相同的体系结构,ControlNet 1.1 包括所有以前的模型,具有改进的稳健性和结果质量,且增加并细化了多个模型。 命名规范 项目名版本号标识基础模型版本功能名文件后缀名 control 官方总是以control为项目名&…

Go | 一分钟掌握Go | 9 - 通道

作者:Mars酱 声明:本文章由Mars酱编写,部分内容来源于网络,如有疑问请联系本人。 转载:欢迎转载,转载前先请联系我! 前言 在Java中,多线程之间的通信方式有哪些?记得吗&…

【云计算•云原生】3.一小时熟练掌握docker容器

文章目录 docker简介ubuntu下安装dockerkali下安装dockerdocker基本命令docker搭建mysql、nginx、redis容器/镜像打包搭建私有镜像仓库docker网络管理Dockerfile文件docker-compose.yml示例:搭建lamp docker简介 docker是一个开源的应用容器引擎,可以让…

缓存优化----SpringCache

spring cache spring Cache介绍 spring cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。 Spring cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不…

解决方案丨票据集中在集团总部处理,如何解决实物票据管理难?

目前越来越多的企业都成立了财务共享中心,通过统一财务中心可以进行集中式、标准化、统一化管理,提升财务运营水平与效率、降低企业的整体运作成本、集团战略发展支撑。 如何确保财务共享中心稳健和高效运营,是很多企业建立共享中心后面的难…

7.参数校验

在controller和service进行前端传参校验&#xff0c;保证存到数据库的数据是正确的 1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>这里无需…

《程序员面试金典(第6版)》面试题 16.05. 阶乘尾数

题目描述 设计一个算法&#xff0c;算出 n 阶乘有多少个尾随零。 示例 1: 输入: 3输出: 0解释: 3! 6, 尾数中没有零。 示例 2: 输入: 5输出: 1解释: 5! 120, 尾数中有 1 个零 说明: 你算法的时间复杂度应为 O(log n) 。 解题思路与代码 这道题&#xff0c;乍一看很简单…