【人工智能】多目标融合算法(四):多门混合专家网络MMOE(Multi-gate Mixture-of-Experts)

【人工智能】多目标融合算法(四):多门混合专家网络MMOE(Multi-gate Mixture-of-Experts)

目录

一、引言

二、MMoE(Multi-gate Mixture-of-Experts,多门混合专家网络)

2.1 技术原理

2.2 技术优缺点

2.3 业务代码实践

2.3.1 业务场景与建模

2.3.2 模型代码实现

2.3.3 模型训练与推理测试

2.3.4 打印模型结构 

三、总结


一、引言

上一篇我们讲了MoE混合专家网络,通过引入Gate门控,针对不同的Input分布,对多个专家网络赋予不同的权重,解决多场景或多目标任务task的底层信息共享及个性化问题。但MoE网络对于不同的Expert专家网络,采用同一个Gate门控网络,仅对不同的Input分布实现了个性化,对不同目标任务task的个性化刻画能力不足,今天在MoE的基础上,引入MMoE网络,为每一个task任务构建专属的Gate门控网络,这样的改进可以针对不同的task得到不同的Experts权重,从而实现对Experts专家的选择利用,不同的任务task对应的gate门控网络可以学习到不同的Experts网络组合模式,更容易捕捉到不容task间的相关性和差异性。

二、MMoE(Multi-gate Mixture-of-Experts,多门混合专家网络)

2.1 技术原理

MMoE(Multi-gate Mixture-of-Experts)全称为多门混合专家网络,主要由多个专家网络、多个任务塔、多个门控网络构成。核心原理:样本数据分别输入num_experts个专家网络进行推理,每个专家网络实际上是一个前馈神经网络(MLP),输入维度为x,输出维度为output_experts_dim;同时,样本数据分别输入目标task对应的门控网络Gate A及Gate B,门控网络也是一个MLP(可以为多层,也可以为一层),输出为num_experts个experts专家的概率分布,维度为num_experts(采用softmax将输出归一化,各个维度加起来和为1);对于每一个Task,将各自对应专家网络的输出,基于对应gate门控网络的softmax加权平均,作为各自Task的输入,所有Task的输入统一维度均为output_experts_dim。在每次反向传播迭代时,对Gate A、Gate B和num_experts个专家参数进行更新,Gate A、Gate B和专家网络的参数受任务Task A、B共同影响。

专家网络:样本数据分别输入num_experts个专家网络进行推理,每个专家网络实际上是一个前馈神经网络(MLP),输入维度为x,输出维度为output_experts_dim。门控网络:样本数据分别输入目标task对应的门控网络Gate A及Gate B,门控网络也是一个MLP(可以为多层,也可以为一层),输出为num_experts个experts专家的概率分布,维度为num_experts(采用softmax将输出归一化,各个维度加起来和为1)任务网络:对于每一个Task,将各自对应专家网络的输出,基于对应gate门控网络的softmax加权平均,作为各自Task的输入,所有Task的输入统一维度均为output_experts_dim。

2.2 技术优缺点

相较于MoE网络,MMoE的本质是每个task自带Gate门控网络对多个专家的预估结果进行选择,相当于给每个task安排了一个个人助理,对专家的结果进行评审(而MoE对于所有task仅有一个公共助理,对task的专属需求了解不深)。相较于MoE网络:

优点:对每个task安排专属的gate网络,在专家网络赋值时更加个性化更容易捕捉到不容task间的相关性和差异性。

缺点: MMOE中所有的Expert是被所有task共享的,这可能无法捕捉到任务之间更复杂的关系,从而给部分任务带来一定的噪声不同的Expert之间没有交互,联合优化的效果有所折扣,虽然可以缓解负迁移问题,但跷跷板现象仍然存在。

2.3 业务代码实践

2.3.1 业务场景与建模

我们还是以小红书推荐场景为例,针对一个视频,用户可以点红心(互动),也可以点击视频进行播放(点击),针对互动和点击两个目标进行多目标建模

我们构建一个100维特征输入,4个experts专家网络,2个task目标,2个门控的MMoE网络,用于建模多目标学习问题,模型架构图如下:

如架构图所示,其中有几个注意的点:

num_experts:门控gate的输出维度和专家数相同,均为num_experts,因为gate的用途是对专家网络最后一层进行加权平均,gate维度与专家数是直接对应关系。output_experts_dim:专家网络的输出维度和task网络的输入维度相同,task网络承接的是专家网络各维度的加权平均值,experts网络与task网络是直接对应关系。Softmax:Gate门控网络对最后一层采用Softmax归一化,保证专家网络加权平均后值域相同

2.3.2 模型代码实现

基于pytorch,实现上述网络架构,如下:

import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset class MMoEModel(nn.Module): def __init__(self, input_dim, experts_hidden1_dim, experts_hidden2_dim, output_experts_dim, task_hidden1_dim, task_hidden2_dim, output_task1_dim, output_task2_dim, gate_hidden1_dim, gate_hidden2_dim, num_experts): super(MMoEModel, self).__init__() # 初始化函数外使用初始化变量需要赋值,否则默认使用全局变量 # 初始化函数内使用初始化变量不需要赋值 self.num_experts = num_experts self.output_experts_dim = output_experts_dim # 初始化多个专家网络 self.experts = nn.ModuleList([ nn.Sequential( nn.Linear(input_dim, experts_hidden1_dim), nn.ReLU(), nn.Linear(experts_hidden1_dim, experts_hidden2_dim), nn.ReLU(), nn.Linear(experts_hidden2_dim, output_experts_dim), nn.ReLU() ) for _ in range(num_experts) ]) # 定义任务1的输出层 self.task1_head = nn.Sequential( nn.Linear(output_experts_dim, task_hidden1_dim), nn.ReLU(), nn.Linear(task_hidden1_dim, task_hidden2_dim), nn.ReLU(), nn.Linear(task_hidden2_dim, output_task1_dim), nn.Sigmoid() ) # 定义任务2的输出层 self.task2_head = nn.Sequential( nn.Linear(output_experts_dim, task_hidden1_dim), nn.ReLU(), nn.Linear(task_hidden1_dim, task_hidden2_dim), nn.ReLU(), nn.Linear(task_hidden2_dim, output_task2_dim), nn.Sigmoid() ) # 初始化门控网络1 self.gating1_network = nn.Sequential( nn.Linear(input_dim, gate_hidden1_dim), nn.ReLU(), nn.Linear(gate_hidden1_dim, gate_hidden2_dim), nn.ReLU(), nn.Linear(gate_hidden2_dim, num_experts), nn.Softmax(dim=1) ) # 初始化门控网络2 self.gating2_network = nn.Sequential( nn.Linear(input_dim, gate_hidden1_dim), nn.ReLU(), nn.Linear(gate_hidden1_dim, gate_hidden2_dim), nn.ReLU(), nn.Linear(gate_hidden2_dim, num_experts), nn.Softmax(dim=1) ) def forward(self, x): # 计算输入数据通过门控网络后的权重 gates1 = self.gating1_network(x) gates2 = self.gating2_network(x) #print(gates) batch_size, _ = x.shape task1_inputs = torch.zeros(batch_size, self.output_experts_dim) task2_inputs = torch.zeros(batch_size, self.output_experts_dim) # 计算每个专家的输出并加权求和 for i in range(self.num_experts): expert_output = self.experts[i](x) task1_inputs += expert_output * gates1[:, i].unsqueeze(1) task2_inputs += expert_output * gates2[:, i].unsqueeze(1) task1_outputs = self.task1_head(task1_inputs) task2_outputs = self.task2_head(task2_inputs) return task1_outputs, task2_outputs # 实例化模型对象 num_experts = 4 # 假设有4个专家 experts_hidden1_dim = 64 experts_hidden2_dim = 32 output_experts_dim = 16 gate_hidden1_dim = 16 gate_hidden2_dim = 8 task_hidden1_dim = 32 task_hidden2_dim = 16 output_task1_dim = 1 output_task2_dim = 1 # 构造虚拟样本数据 torch.manual_seed(42) # 设置随机种子以保证结果可重复 input_dim = 100 num_samples = 1024 X_train = torch.randint(0, 2, (num_samples, input_dim)).float() y_train_task1 = torch.rand(num_samples, output_task1_dim) # 假设任务1的输出维度为1 y_train_task2 = torch.rand(num_samples, output_task2_dim) # 假设任务2的输出维度为1 # 创建数据加载器 train_dataset = TensorDataset(X_train, y_train_task1, y_train_task2) train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True) model = MMoEModel(input_dim, experts_hidden1_dim, experts_hidden2_dim, output_experts_dim, task_hidden1_dim, task_hidden2_dim, output_task1_dim, output_task2_dim, gate_hidden1_dim, gate_hidden2_dim, num_experts) # 定义损失函数和优化器 criterion_task1 = nn.MSELoss() criterion_task2 = nn.MSELoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练循环 num_epochs = 100 for epoch in range(num_epochs): model.train() running_loss = 0.0 for batch_idx, (X_batch, y_task1_batch, y_task2_batch) in enumerate(train_loader): # 前向传播: 获取预测值 #print(batch_idx, X_batch ) #print(f'Epoch [{epoch+1}/{num_epochs}-{batch_idx}], Loss: {running_loss/len(train_loader):.4f}') outputs_task1, outputs_task2 = model(X_batch) # 计算每个任务的损失 loss_task1 = criterion_task1(outputs_task1, y_task1_batch) loss_task2 = criterion_task2(outputs_task2, y_task2_batch) total_loss = loss_task1 + loss_task2 # 反向传播和优化 optimizer.zero_grad() total_loss.backward() optimizer.step() running_loss += total_loss.item() if epoch % 10 == 0: print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}') print(model) #for param_tensor in model.state_dict(): # print(param_tensor, "\t", model.state_dict()[param_tensor].size()) # 模型预测 model.eval() with torch.no_grad(): test_input = torch.randint(0, 2, (1, input_dim)).float() # 构造一个测试样本 pred_task1, pred_task2 = model(test_input) print(f'互动目标预测结果: {pred_task1}') print(f'点击目标预测结果: {pred_task2}')

相比于上一篇MoE中的代码,MMoE初始化了gating1_network和gating2_network两个门控网络,在forward前向传播网络结构定义中,两个gate分别以input为输入,通过多层MLP后得到task相对应的加权平均权重。

2.3.3 模型训练与推理测试

运行上述代码,模型启动训练,Loss逐渐收敛,测试结果如下:

2.3.4 打印模型结构 

三、总结

本文详细介绍了MMoE多任务模型的算法原理、算法优势,并以小红书业务场景为例,构建网络结构并使用pytorch代码实现对应的网络结构、训练流程。相比于MoE,MMoE可以更好的学习不同Task任务的相关性和差异性。是深度学习推荐系统中多目标或多场景类问题中必须掌握的根基模型。

如果您还有时间,欢迎阅读本专栏的其他文章:

【深度学习】多目标融合算法(一):样本Loss加权(Sample Loss Reweight)

【深度学习】多目标融合算法(二):底部共享多任务模型(Shared-Bottom Multi-task Model) ​​​​​​​

【深度学习】多目标融合算法(三):混合专家网络MOE(Mixture-of-Experts) 

 【深度学习】多目标融合算法(四):多门混合专家网络MMOE(Multi-gate Mixture-of-Experts)

Read more

可以在命令行通过大模型使用上下文协议(MCP)与外部工具交互的软件:小巧的MCPHost

可以在命令行通过大模型使用上下文协议(MCP)与外部工具交互的软件:小巧的MCPHost

小巧的MCPHost MCPHost 可以在命令行下使用,使大型语言模型(LLM)能够通过模型上下文协议(MCP)与外部工具进行交互。目前支持Claude 3.5 Sonnet和Ollama等。本次实践使用自己架设的Deepseek v3模型,跑通了Time MCP服务。  官网:GitHub - mark3labs/mcphost: A CLI host application that enables Large Language Models (LLMs) to interact with external tools through the Model Context Protocol (MCP). 下载安装 使用非常方便,直接下载解压即可使用。官网提供Windows、Linux和MacOS三个系统的压缩包: https://github.com/

By Ne0inhk
实战篇:Python开发monogod数据库mcp server看完你就会了

实战篇:Python开发monogod数据库mcp server看完你就会了

原创不易,请关注公众号:【爬虫与大模型开发】,大模型的应用开发之路,整理了大模型在现在的企业级应用的实操及大家需要注意的一些AI开发的知识点!持续输出爬虫与大模型的相关文章。 前言 目前mcp协议是给deepseek大模型插上工具链的翅膀,让大模型不仅拥有超高的推理和文本生成能力,还能具备执行大脑意识的工具能力! 如何开发一个mcp? mcp是一种协议,指的是模型上下文协议 (Model Context Protocol)。 官方结成的mcp https://github.com/modelcontextprotocol/python-sdk mcp库 pip install mcp from mcp.server.fastmcp import FastMCP 我们先来做一个简单的案例 from mcp.server.fastmcp import FastMCP import requests mcp = FastMCP("spider") @mcp.tool() def crawl(

By Ne0inhk
【大模型实战篇】基于Claude MCP协议的智能体落地示例

【大模型实战篇】基于Claude MCP协议的智能体落地示例

1. 背景         之前我们在《MCP(Model Context Protocol) 大模型智能体第一个开源标准协议》一文中,介绍了MCP的概念,虽然了解了其概念、架构、解决的问题,但还缺少具体的示例,来帮助进一步理解整套MCP框架如何落地。         今天我们基于claude的官方例子--获取天气预报【1】,来理解MCP落地的整条链路。 2. MCP示例         该案例是构建一个简单的MCP天气预报服务器,并将其连接到主机,即Claude for Desktop。从基本设置开始,然后逐步发展到更复杂的使用场景。         大模型虽然能力非常强,但其弊端就是内容是过时的,这里的过时不是说内容很旧,只是表达内容具有非实时性。比如没有获取天气预报和严重天气警报的能力。因此我们将使用MCP来解决这一问题。         构建一个服务器,该服务器提供两个工具:获取警报(get-alerts)和获取预报(get-forecast)。然后,将该服务器连接到MCP主机(在本例中为Claude for Desktop)。         首先我们配置下环

By Ne0inhk
AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建 作者:高瑞冬 本文目录 * AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建 * 一、MCP协议简介 * 二、创建MCP工具集 * 1. 获取MCP服务地址 * 2. 在FastGPT中创建MCP工具集 * 三、测试MCP工具 * 四、AI模型调用MCP工具 * 1. 调用单个工具 * 2. 调用整个工具集 * 五、私有化部署支持 * 1. 环境准备 * 2. 修改docker-compose.yml文件 * 3. 修改FastGPT配置 * 4. 重启服务 * 六、使用MCP-Proxy集成多个MCP服务 * 1. MCP-Proxy简介 * 2. 安装MCP-Proxy * 3. 配置MCP-Proxy * 4. 将MCP-Proxy与FastGPT集成 * 5. 高级配置

By Ne0inhk