AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


模型训练 | 大模型-混合专家模型 MoE
发布日期:2024-04-18 17:17:40 浏览次数: 1999


随着 Mixtral 8x7B (announcement, model card)、MoE-LLaVA、Gemini1.5 等 MoE 架构模型的推出,一种称为混合专家模型 (Mixed Expert Models,简称 MoEs) 的 Transformer 模型在开源人工智能社区引起了广泛关注。

随着应用场景的复杂化和细分化,大模型越来越大,垂直领域应用更加碎片化,想要一个模型既能回答通识问题,又能解决专业领域问题,似乎 MoE 是一种性价比更高的选择。MoE 模型由众多小型的“专家”神经网络组成,这些模型可以根据不同的输入类型,学会仅激活最相关的专家网络路径。

开源的混合专家模型列举:

  • • Switch Transformers (Google): 基于 T5 的 MoE 集合,专家数量从 8 名到 2048 名。最大的模型有 1.6 万亿个参数;

  • • OpenMoE: 是开源社区基于 Llama 的模型对 Decoder-only MoE 最早的尝试;

  • • Mixtral 8x7B (Mistral): 一个性能超越了 Llama2-70B 的高质量混合专家模型,并且具有更快的推理速度;

  • • MoE-LLaVA: 北大联合中山大学、腾讯等机构推出的新模型MoE-LLaVA,它仅有3B激活参数,表现却已和7B稠密模型持平,甚至部分指标比13B的模型还要好。

特点

  • • 与稠密模型相比,预训练速度更快;

  • • 与具有相同参数数量的模型相比,具有更快的推理速度;

  • • 需要大量显存,因为所有专家系统都需要加载到内存中;

  • • 在微调方面存在诸多挑战,但近期的研究表明,对混合专家模型进行指令调优具有很大的潜力。

模型架构

混合专家模型(MoE)是一种稀疏门控制的深度学习模型,它主要由一组专家模型和一个门控模型组成。MoE 的基本理念是将输入数据根据任务类型分割成多个区域,并将每个区域的数据分配一个或多个专家模型。每个专家模型可以专注于处理输入这部分数据,从而提高模型的整体性能。

门控网络

GateNet:混合专家模型中“门”是一种稀疏门网络,它接收单个数据元素作为输入,然后输出一个权重,这些权重表示每个专家模型对处理输入数据的贡献。一般是通过 softmax 门控函数通过专家或 token 对概率分布进行建模,并选择前 K 个。例如,如果模型有三个专家,输出的概率可能为 0.5 和 0.4、0.1,这意味着第一个专家对处理此数据的贡献为 50%,第二个专家为 40%,第二个专家为 10%,这个时候的 K 就可以选择为 2,我们认为前两个专家模型的建议会更好,可以用于更加精确的回答中,而第三个专家模型的建议可以用于更加富有创意性的答案中。

专家

Experts:在训练的过程中,输入的数据被门控模型分配到不同的专家模型中进行处理;在推理的过程中,被门控选择的专家会针对输入的数据,产生相应的输出。这些输出最后会和每个专家模型处理该特征的能力分配的权重进行加权组合,形成最终的预测结果。

混合专家模型的实现涉及对专家模型和门控网络的联合训练,在整个数据输入处理的过程中,门控网络起到了动态调配专家模型资源的关键作用,使混合专家模型能够灵活地适应不同的输入数据分布和任务要求。以及在模型结构和参数上的细致调整,以满足具体应用的需求。这种结构允许模型在处理各种输入数据时自适应地选择合适的专家,从而提高模型的表现和效率。

MoE模型代码示例

import torchimport torch.nn as nnimport torch.nn.functional as Ffrom torch.utils.data import DataLoader, Datasetfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import accuracy_scoreimport numpy as np

# 创建一些随机数据(替换为真实数据)num_samples = 2000num_features = 300# 假设文本已经转换为固定大小的向量num_classes = 10# 假设有10个类别
# 随机生成数据和标签X = np.random.randn(num_samples, num_features)y = np.random.randint(0, num_classes, num_samples)
# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义 Datasetclass TextDataset(Dataset):def __init__(self, features, labels):self.features = featuresself.labels = labels
def __len__(self):return len(self.labels)
def __getitem__(self, idx):return torch.tensor(self.features[idx], dtype=torch.float), torch.tensor(self.labels[idx], dtype=torch.long)

# 创建 DataLoadertrain_dataset = TextDataset(X_train, y_train)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_dataset = TextDataset(X_test, y_test)test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

# 模型定义class TopKGating(nn.Module):def __init__(self, input_dim, num_experts, top_k=2):super(TopKGating, self).__init__()# 初始化线性层作为门控机制self.gate = nn.Linear(input_dim, num_experts)# 设置要选择的顶部专家数量self.top_k = top_k
def forward(self, x):# 计算每个专家的分数gating_scores = self.gate(x)# 选取分数最高的 top_k 个专家,并返回它们的索引和 softmax 权重top_k_values, top_k_indices = torch.topk(F.softmax(gating_scores, dim=1), self.top_k)return top_k_indices, top_k_values

class Expert(nn.Module):def __init__(self, input_dim, output_dim):super(Expert, self).__init__()# 为每个专家定义一个简单的神经网络self.net = nn.Sequential(nn.Linear(input_dim, 128),nn.ReLU(),nn.Linear(128, output_dim))
def forward(self, x):# 通过专家网络传递输入数据return self.net(x)

class MoE(nn.Module):def __init__(self, input_dim, num_classes, num_experts, top_k=2):super(MoE, self).__init__()# 设置专家数量self.num_experts = num_experts# 设置类别数量self.num_classes = num_classes# 初始化 TopK 门控层self.gating = TopKGating(input_dim, num_experts, top_k)# 创建专家网络的列表,每个专家是一个 Expert 实例self.experts = nn.ModuleList([Expert(input_dim, num_classes) for _ in range(num_experts)])

def forward(self, x):# 获取批量大小batch_size = x.size(0)# 通过门控层获得 top_k 专家的索引和门控权重indices, gates = self.gating(x)# 形状 indices:[batch_size, top_k], gates:[batch_size, top_k]# 准备收集选定专家的输出expert_outputs = torch.zeros(batch_size, indices.size(1), self.num_classes).to(x.device)# 遍历每个样本和其对应的 top_k 专家for i in range(batch_size):for j in range(indices.size(1)):expert_idx = indices[i, j].item()# 获取专家的索引expert_outputs[i, j, :] = self.experts[expert_idx](x[i].unsqueeze(0))# 将门控权重扩展到与专家输出相同的维度gates = gates.unsqueeze(-1).expand(-1, -1, self.num_classes)# 形状:[batch_size, top_k, num_classes]# 计算加权的专家输出的和output = (gates * expert_outputs).sum(1)return output, gates.sum(0)# 返回模型输出和门控使用率以用于负载平衡损失计算

def moe_loss(output, target, gating_weights, lambda_balance=0.1):# 标准损失(例如交叉熵损失)# output 是模型的输出,target 是真实的标签standard_loss = F.cross_entropy(output, target)
# 负载平衡损失# gating_weights 是门控权重,表示每个专家的使用率# 使用标准差来衡量各专家使用率的平衡程度balance_loss = torch.std(gating_weights)
# 总损失# 结合标准损失和负载平衡损失,lambda_balance 是一个超参数,用于控制负载平衡损失在总损失中的比重total_loss = standard_loss + lambda_balance * balance_lossreturn total_loss

# 初始化模型model = MoE(input_dim=num_features, num_classes=num_classes, num_experts=4, top_k=2)optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练num_epochs = 3for epoch in range(num_epochs):model.train()total_loss = 0for features, labels in train_loader:optimizer.zero_grad()outputs, gating_weights = model(features)loss = moe_loss(outputs, labels, gating_weights)loss.backward()optimizer.step()total_loss += loss.item()print(f'Epoch {epoch+1}, Loss: {total_loss/len(train_loader)}')

def evaluate(model, data_loader):model.eval()predictions, true_labels = [], []with torch.no_grad():for features, labels in data_loader:s = time.time()outputs, _ = model(features)e = time.time()print(e-s)predicted = torch.argmax(outputs, dim=1)predictions.extend(predicted.tolist())true_labels.extend(labels.tolist())    return accuracy_score(true_labels, predictions)

面临的挑战

  • • 训练挑战: 虽然 MoE 能够实现更高效的计算预训练,但它们在微调阶段往往面临泛化能力不足的问题,长期以来易于引发过拟合现象。

  • • 推理挑战: MoE 模型虽然可能拥有大量参数,但在推理过程中只使用其中的一部分,这使得它们的推理速度快于具有相同数量参数的稠密模型。然而,这种模型需要将所有参数加载到内存中,因此对内存的需求非常高。以 Mixtral 8x7B 这样的 MoE 为例,需要足够的 VRAM 来容纳一个 47B 参数的稠密模型。之所以是 47B 而不是 8 x 7B = 56B,是因为在 MoE 模型中,只有 FFN 层被视为独立的专家,而模型的其他参数是共享的。此外,假设每个令牌只使用两个专家,那么推理速度 (以 FLOPs 计算) 类似于使用 12B 模型 (而不是 14B 模型),因为虽然它进行了 2x7B 的矩阵乘法计算,但某些层是共享的。


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询