qwen-moe

一、定义

  1. qwen-moe 代码讲解, 代码qwen-moe与Mixtral-moe 一样, 专家模块
  2. qwen-moe 开源教程
  3. Mixture of Experts (MoE) 模型在Transformer结构中如何实现,Gate的实现一般采用什么函数? Sparse MoE的优势有哪些?MoE是如何提高模型容量而不显著增加计算负
    担的?

二、实现

  1. qwen-moe 代码讲解
    参考:https://blog.csdn.net/v_JULY_v/article/details/135176583?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-135176583-blog-135046508.235v43pc_blog_bottom_relevance_base4&spm=1001.2101.3001.4242.1&utm_relevant_index=3
import torch
from torch import nn
from torch.nn import functional as F
from transformers.activations import ACT2FN

class Qwen2MoeMLP(nn.Module):
    def __init__(self, config, intermediate_size=None):
        super().__init__()
        self.config = config
        self.hidden_size = config.hidden_size
        self.intermediate_size = intermediate_size
        self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
        self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
        self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
        #self.act_fn = ACT2FN[config.hidden_act]

    def forward(self, x):
        return self.down_proj(self.gate_proj(x) * self.up_proj(x))


class Qwen2MoeSparseMoeBlock(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.num_experts = config.num_experts
        self.top_k = config.num_experts_per_tok
        self.norm_topk_prob = config.norm_topk_prob

        # gating
        self.gate = nn.Linear(config.hidden_size, config.num_experts, bias=False)
        self.experts = nn.ModuleList(
            [Qwen2MoeMLP(config, intermediate_size=config.moe_intermediate_size) for _ in range(self.num_experts)]
        )

        self.shared_expert = Qwen2MoeMLP(config, intermediate_size=config.shared_expert_intermediate_size)
        self.shared_expert_gate = torch.nn.Linear(config.hidden_size, 1, bias=False)

    def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
        """ """
        batch_size, sequence_length, hidden_dim = hidden_states.shape
        hidden_states = hidden_states.view(-1, hidden_dim)
        # router_logits: (batch * sequence_length, n_experts)
        router_logits = self.gate(hidden_states)

        routing_weights = F.softmax(router_logits, dim=1, dtype=torch.float)
        #选取每个token 对应的前k 个专家
        routing_weights, selected_experts = torch.topk(routing_weights, self.top_k, dim=-1)
        if self.norm_topk_prob:
            routing_weights /= routing_weights.sum(dim=-1, keepdim=True)   #权重归一化  确保每个token的专家权重之和为1
        # we cast back to the input dtype
        routing_weights = routing_weights.to(hidden_states.dtype)
        #全为0的张量
        final_hidden_states = torch.zeros(
            (batch_size * sequence_length, hidden_dim), dtype=hidden_states.dtype, device=hidden_states.device
        )

        # One hot encode the selected experts to create an expert mask
        # this will be used to easily index which expert is going to be sollicitated
        expert_mask = torch.nn.functional.one_hot(selected_experts, num_classes=self.num_experts).permute(2, 1, 0)  #稀疏矩阵

        # Loop over all available experts in the model and perform the computation on each expert
        for expert_idx in range(self.num_experts):
            expert_layer = self.experts[expert_idx]                   # 第idx 专家对应的函数
            idx, top_x = torch.where(expert_mask[expert_idx])         #idx 专家,关注的token, top_x 对应第x 个token
            print(expert_idx,top_x.cpu().tolist() )   #专家,处理的token
            # Index the correct hidden states and compute the expert hidden state for
            # the current expert. We need to make sure to multiply the output hidden
            # states by `routing_weights` on the corresponding tokens (top-1 and top-2)   专家输入信息:
            current_state = hidden_states[None, top_x].reshape(-1, hidden_dim)             #取出对应的token信息
            current_hidden_states = expert_layer(current_state) * routing_weights[top_x, idx, None]       #专家输出

            # However `index_add_` only support torch tensors for indexing so we'll use
            # the `top_x` tensor here. 使用.index_add_函数后在指定位置(top_x)加上了指定值(current_hidden_states)
            final_hidden_states.index_add_(0, top_x, current_hidden_states.to(hidden_states.dtype))

        shared_expert_output = self.shared_expert(hidden_states)
        shared_expert_output = F.sigmoid(self.shared_expert_gate(hidden_states)) * shared_expert_output

        final_hidden_states = final_hidden_states + shared_expert_output

        final_hidden_states = final_hidden_states.reshape(batch_size, sequence_length, hidden_dim)
        return final_hidden_states, router_logits

# 假设的配置
class Config:
    def __init__(self):
        self.num_experts = 8
        self.num_experts_per_tok = 2
        self.norm_topk_prob = True
        self.hidden_size = 2
        self.moe_intermediate_size = 209
        self.shared_expert_intermediate_size = 20

# 检查是否有可用的GPU

device = torch.device("cpu")

# 创建模型实例
config = Config()
model = Qwen2MoeSparseMoeBlock(config).to(device)

input_tensor = torch.randn(1,3,2).to(device)

# 前向传播
output = model(input_tensor)
print(output)

注意:1. 常规思路: 每个token 选择2 个专家, 然后每个token 传入2个专家中,进行处理。----->为了加快推理速度----->关注视角由token 转为专家。在这里插入图片描述
便把关注视角从“各个token”变成了“各个专家”,当然,大部分情况下 token数远远不止下图这5个,而是比专家数多很多。总之,这么一转换,最终可以省掉很多循环。
遍历每个专家,对token 对应的信息整体输入专家模块。

# 【代码块A】routing_weights
# 每行对应1个token,第0列为其对应排位第1的expert、第1列为其对应排位第2的expert,元素值为相应权重
[[0.5310, 0.4690],
 [0.5087, 0.4913],

 [0.5014, 0.4986],
 [0.5239, 0.4761],
 [0.5817, 0.4183],
 [0.5126, 0.4874]]
# 【代码块B】expert_mask[expert_idx]
# 下述两行例子的物理含义为:
# 第一行是“该expert作为排位1的exert存在时,需要处理第9个token;
# 第二行是“该expert作为排位2的expert存在时,需要处理第10、11个token”
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]]
# 【代码块C】idx, top_x = torch.where(expert_mask[expert_idx])
# 以上述expert_mask[expert_idx]样例为例,对应的torch.where(expert_mask[expert_idx])结果如下
idx: [0, 1, 1]
top_x: [9, 10, 11]
idx对应行索引,top_x对应列索引,例如张量expert_mask[expert_idx]中,出现元素1的索引为(0, 9)(1, 10)(1, 11)
从物理含义来理解,top_x实际上就对应着“关乎当前expert的token索引”,第9、第10、第11个token被“路由”导向了当前所关注的expert,通过top_x可以取到“需要传入该expert的输入”,也即第9、第10、第11个token对应的隐向量

因此top_x将作为索引用于从全部token的隐向量hidden_states中取出对应token的隐向量
而idx和top_x也会组合起来被用于从expert权重张量routing_weights中取出对应的权重
current_state = hidden_states[None, top_x].reshape(-1, hidden_dim)             #取出top_x的token信息
current_hidden_states = expert_layer(current_state) * routing_weights[top_x, idx, None]       #专家输出

# However `index_add_` only support torch tensors for indexing so we'll use
# the `top_x` tensor here. 使用.index_add_函数后在指定位置(top_x)加上了指定值(current_hidden_states)
final_hidden_states.index_add_(0, top_x, current_hidden_states.to(hidden_states.dtype))
  1. 开源教程
    https://developer.aliyun.com/article/1471903?spm=a2c6h.28954702.blog-index-detail.67.536b4c2d9ZzdBw

  2. Mixture of Experts (MoE) 模型在Transformer结构中如何实现,Gate的实现一般采用什么函数? Sparse MoE的优势有哪些?MoE是如何提高模型容量而不显著增加计算负担的?

self.gate = nn.Linear(config.hidden_size, config.num_experts, bias=False)

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

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

相关文章

NFTScan 获 Google Cloud 战略支持!

近日,NFT 数据基础设施服务商 NFTScan 获得全球领先云计算服务提供商 Google Cloud 战略支持。未来,双方将在链上数据和区块链领域展开战略合作,高效联动,共同探索区块链技术的更多可能性,为用户和行业带来更多惊喜与成…

强烈推荐十款数据防泄密软件,高人气的数据防泄密软件

100G的文件不见了?客户的电话信息被拷贝走了?源代码被竞争对手搞到手了?这些都是严重的数据泄密事件,为此,我们需要数据防泄密软件来全方位保护数据安全。根据当前市场上的热门推荐和综合评价,以下几款数据…

基于Linux的文件操作(socket操作)

基于Linux的文件操作(socket操作) 1. 文件描述符基本概念文件描述符的定义:标准文件描述符:文件描述符的分配: 2. 文件描述符操作打开文件读取文件中的数据 在linux中,socket也被认为是文件的一种&#xff…

JS【详解】快速排序

快速排序的时间复杂度为 O(n2) 排序流程 1、首先设定一个分界值(比如数组最中间的元素),通过该分界值将数组分成左右两部分。 2、将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。 3、对左侧和右侧的…

项目中父模块调用子模块出现 Invalid bound statement (not found)问题

背景 做某个saas项目的时候,我把用户、角色、菜单、字典等模块弄成了一个基础包,想着如果之后又类似的项目的时候可以偷个懒 直接引用基础包就可以了。 当我引用的时候出现了这个问题 Invalid bound statement (not found):xxx 分析思路 这个问题一般…

卧式饲料搅拌机:养殖场得力助手

卧式饲料搅拌机采用卧式结构,设计科学合理,操作简便。相比传统的立式搅拌机,卧式搅拌机具有更大的搅拌容量和更均匀的搅拌效果。它能够轻松应对不同种类、不同比例的饲料混合需求,确保饲料成分的均衡分布,从而提高饲料…

【强化学习】DPO(Direct Preference Optimization)算法学习笔记

【强化学习】DPO(Direct Preference Optimization)算法学习笔记 RLHF与DPO的关系KL散度Bradley-Terry模型DPO算法流程参考文献 RLHF与DPO的关系 DPO(Direct Preference Optimization)和RLHF(Reinforcement Learning f…

KMPlayer v2024.4.25.13 官方版 (万能播放器)

前言 KMPlaye通过各种插件扩展KMP可以支持层出不穷的新格式。KMPlaye强大的插件功能,直接从Winamp继承的插件功能,能够直接使用Winamp的音频,输入,视觉效果插件,而通过独有的扩展能力,只要你喜欢&#xff…

【linux-imx6ull-设备树点灯】

目录 1. 设备树简介1.1 编译-引用1.2 设备树文件结构1.3 设备树节点介绍1.3.1 特殊节点chosen 1.4 节点内容追加 2. 设备树常用OF操作函数2.1 节点寻找类2.2 属性提取类2.3 其它常用类 4. 设备树下LED实验4.1 实验简介4.2 添加LED设备节点4.3 获取设备节点并提取属性4.3.1 获取…

国内类似ChatGPT的大模型应用有哪些?发展情况如何了

第一部分:几个容易混淆的概念 很多人,包括很多粉丝的科技博主,经常把ChatGPT和预训练大模型混为一谈,因此有必要先做一个澄清。预训练大语言模型属于预训练大模型的一类,而ChatGPT、文心一言又是预训练大语言模型的一个…

【Linux】Linux基本指令3

目录 1.date指令 2.cal指令 3.find指令:(灰常重要) -name 4.grep指令——行文本过滤工具 5.zip/unzip指令: 6.tar指令(重要):打包/解包,不打开它,直接看内容 7.bc…

SpringBoot六种API请求参数读取方式

SpringBoot六种API请求参数读取方式 同步请求和异步请求 同步: 指单线程依次做几件事异步: 指多线程同时做几件事 同步请求: 指客户端浏览器只有一个主线程, 此线程负责页面的渲染和发出请求等操作, 如果此主线程发出请求的话则停止渲染而且会清空页面显示的内容 直到服务器响…

3d渲染的常用概念和技术,渲染100邀请码1a12

之前我们介绍了3D渲染的基本原理和流程,这次说下几个常用概念和技术。 3D渲染中涉及到很多专业的概念和技术,它们决定了渲染质量和效果,常用的有以下几个。1、光线追踪 光线追踪是一些专业渲染器(如V-Ray和Corona等)…

算法思想总结:哈希表

一、哈希表剖析 1、哈希表底层:通过对C的学习,我们知道STL中哈希表底层是用的链地址法封装的开散列。 2、哈希表作用:存储数据的容器,插入、删除、搜索的时间复杂度都是O(1),无序。 3、什么时…

Android HIDL接口添加

一.HIDL介绍 HIDL的全称是HAL interface definition language(硬件抽象层接口定义语言),是Android Framework 与Android HAL之间的接口。HIDL 旨在用于进程间通信 (IPC),进程之间的通信 采用 Binder 机制。 二.HIDL 与AIDL 的对…

客户文章|难能可贵,非模式生物的功能研究与创新

菜豆(Phaseolus vulgaris),又名四季豆、芸豆、油豆角,是全球第一大豆类蔬菜,我国是世界上最主要的菜豆生产国和销售国。在田间生产过程中,菜豆常面临着各种生物和非生物逆境的胁迫,对其产量品质…

FOC - BLDC六步换相驱动原理

文章目录 1 . 前言2 . 电机旋转原理3 . BLDC特点4 . BLDC反电动势投影位置5 . BLDC换相时刻6 . BLDC换相注意事项7 . 小结 【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 1 . 前言 无刷直流电机在这里区分为两种,一是永磁无刷直流电…

【Linux-LCD 驱动】

Linux-LCD 驱动 ■ Framebuffer 简称 fb■ LCD 驱动程序编写■ 1、LCD 屏幕 IO 配置■ 2、LCD 屏幕参数节点信息修改■ 3、LCD 屏幕背光节点信息■ 4、使能 Linux logo 显示 ■ 设置 LCD 作为终端控制台■ 1、设置 uboot 中的 bootargs■ 2、修改/etc/inittab 文件 ■ LCD 背光…

python前端streamlit模型部署

简单介绍使用前端streamlit框架快速部署本地模型: 1、模型训练: import pandas as pd # 流程整合 from sklearn.pipeline import make_pipeline, Pipeline # 数据处理 from sklearn.impute import SimpleImputer from sklearn.preprocessing import Min…

探索 Android Studio 中的 Gemini:加速 Android 开发的新助力

探索 Android Studio 中的 Gemini:加速 Android 开发的新助力 在 Gemini 时代的下一篇章中,Gemini融入了更多产品中,Android Studio 正在使用 Gemini 1.0 Pro 模型,使 Android 开发变得更快、更简单。 Studio Bot 现已更名为 And…