MoE开山鼻祖——1991年的论文有多么朴实无华

MoE开山鼻祖——1991年的论文有多么朴实无华

论文标题:Adaptive Mixtures of Local Experts

论文地址:https://people.engr.tamu.edu/rgutier/web_courses/cpsc636_s10/jacobs1991moe.pdf

Abstract

论文提出了一种新的监督学习方法,适用于由多个独立网络组成的系统,每个网络学习处理训练案例全集的一个子集。

这种新方法既可以看作是多层监督网络的模块化版本,也可以看作是竞争学习的关联版本。

多层监督网络: 指的是把多个中间层(隐藏层)的数据也纳入计算损失。类比到Bert模型,就是把某些个Transformer Block最后的hidden tensor结果一些变换(如平均池化)后去计算损失,然后加权到最终的损失函数上。

竞争学习: 类似在线版本的K Means,假设我们有三个数据源,当一个样本到来后,通过竞争规则(如欧式距离)计算出获胜的神经元,然后只更新获胜神经元的权重。

因此,它在这两种看似不同的方法之间建立了新的联系。论文证明,该学习方法将元音辨别任务分解为适当的子任务,每个子任务都可以由一个非常简单的专家网络解决。

Making Associative Learning Competitive

如果使用反向传播算法在不同场合训练单个多层网络来执行不同的子任务,通常会产生强烈的干扰效应,导致学习缓慢且泛化能力差。

这里说的很像是多任务学习,多任务学习有硬参数共享和软参数共享两种形式,我读研时尝试把多标签文本分类和标签个数分类作为硬参数共享多任务进行联合建模,效果一般。

如果我们事先知道一组训练样本可以自然地划分为与不同子任务相对应的子集,那么通过使用由几个不同的 “专家” 网络加上一个门控网络组成的系统,可以减少干扰。

MoE可以看作是多任务学习的一种架构,增加了门控机制来让模型选择专家网络,子任务可以是一个任务的拆分,也可以是不同学习目标的任务。

门控网络决定每个训练样本应该使用哪个专家网络。当在训练前就知道子任务的划分时可以使用该系统,该系统学习如何将样本分配给专家。这种系统背后的理念是,门控网络将一个新样本分配给一个或几个专家,如果输出不正确,权重变化将局限于这些专家(以及门控网络)。

因此,这不会对专门处理截然不同情况的其他专家的权重产生干扰。从这个意义上说,这些专家是局部的,即一个专家的权重与其他专家的权重是解耦的。

软组合

基于上述思想,最初提出的系统误差为:

$ E^{c}=\left| d^{c}-\sum_{i} p_{i}^{c} o_{i}^{c}\right| ^{2} \tag1 $

其中$ o_{i}^{c} 是专家是专家是专家 i 在案例在案例在案例 c 上的输出向量,上的输出向量,上的输出向量, p_{i}^{c} 是专家是专家是专家 i 对组合输出向量的比例贡献,而对组合输出向量的比例贡献,而对组合输出向量的比例贡献,而 d^{c} 是案例是案例是案例 c $中的期望输出向量。

对 $ E^c $ 关于 $ o_i^c $ 求偏导,我们需要分别处理两个公式。

对于公式 (1)求偏导:

$ \frac{\partial E^c}{\partial o_i^c} = 2 \left( d^c - \sum_{i} p_i^c o_i^c \right) \cdot (-p_i^c) $

根据偏导可以看出对某个专家网络更新权重,会受到所有其他专家网络的影响。当一个专家的权重发生变化时,残差误差也会改变,因此所有其他本地专家的误差导数也会改变。

在合作模式中,所有专家都参与输出,即使某个专家预测很差,只要其他专家表现好,总误差仍可能较小。这可能导致:

  • 某些专家变得懒惰(不精确也没关系,反正别人会补偿);
  • 专家之间缺乏区分性,难以实现“分工”;
  • 门控网络无法清晰地学习到“哪个专家擅长处理哪类数据”。

这就是所谓的“责任稀释”(credit assignment problem)。

硬竞争

一种更简单的补救方法是重新定义误差函数,从而鼓励本地专家相互竞争而非合作。 不再将所有专家的输出线性组合,而是设想:每次只使用一个专家,该专家由门控网络以概率 $ p_i^c $ 随机选出。

$ E^{c}=\left<\left| d{c}-o_{i}{c}\right| ^{2}\right>=\sum_{i} p_{i}^{c}\left| d{c}-o_{i}{c}\right| ^{2} \tag 2 $

对于公式 (2)求偏导:

$ \frac{\partial E^{c}}{\partial o_{i}^{c}}=-2 p_{i}{c}\left(d{c}-o_{i}^{c}\right) $

在这个新的误差函数中,一个局部专家的目标不会直接受到其他局部专家权重的影响。

仍然存在一些间接的影响,因为如果其他某个专家改变其权重,这可能会导致门控网络改变分配给各个专家的权重,但至少这些权重变化不会改变某个局部专家在给定训练样本上所感知到的误差。

如果门控网络和局部专家都通过梯度下降法针对这个新的误差函数进行训练,系统往往会为每个训练样本分配一个单独的专家。

只要某个专家给出的误差小于所有专家误差的加权平均值(利用门控网络的输出来决定如何对每个专家的误差进行加权),它对该样本的权重会增加,否则权重会降低。

尽管如此,这种方法也有局限:

  • 冷启动问题:初期所有专家表现差,门控网络难以做出好选择;
  • 局部最优:某个专家偶然表现好,就垄断资源,其他专家无法成长;
  • 方差大:因为输出是随机的,训练可能不稳定;
  • 非确定性输出:同一输入多次前向传播可能得到不同结果。

软竞争

问题设定

  • 输入:样本特征 $ x $
  • 真实目标:连续值输出 $ d^c \in \mathbb{R}^D $,表示第 $ c $ 个任务或模态下的目标向量(例如在多任务学习或条件生成中)
  • 模型结构:Mixture of Experts(MoE),包含多个“专家”网络和一个门控(gating)网络
  • 专家输出:第 $ i $ 个专家对第 $ c $ 个任务的预测输出为 $ o_i^c \in \mathbb{R}^D $
  • 门控权重:门控网络输出的归一化权重 $ p_i^c = \text{Gate}(x)_i $,满足 $ \sum_i p_i^c = 1 $ 且 $ p_i^c \in (0,1) $,表示第 $ i $ 个专家在任务 $ c $ 下的置信度或责任分配

模型预测分布建模

在 MoE 架构中,最终的预测不是单一专家的输出,而是多个专家输出的加权组合。但不同于简单的加权平均,这里通过概率视角建模整体输出的似然。

假设模型对目标 $ d^c $ 的预测服从一个由专家输出构成的高斯混合分布(Gaussian Mixture Model, GMM)

$ P(d^c | x) = \sum_{i} p_i^c \cdot \mathcal{N}(d^c \mid o_i^c, I) $

其中:

  • $ \mathcal{N}(d^c \mid o_i^c, I) \propto \exp\left(-\frac{1}{2} |d^c - o_ic|2\right) $ 是以第 $ i $ 个专家输出为中心的标准高斯核
  • $ p_i^c $ 是门控网络提供的先验权重(即第 $ i $ 个专家被选中的概率)

因此,整体似然为各专家生成目标 $ d^c $ 的加权概率密度之和。

对数似然函数

取该混合分布的对数似然:

$ \log P(d^c | x) = \log \left( \sum_{i} p_i^c \cdot \frac{1}{(2\pi)^{D/2}} \exp\left(-\frac{1}{2} |d^c - o_ic|2\right) \right) $

忽略常数项(如 $ (2\pi)^{D/2} $,因为它们不依赖于模型参数),可得有效对数似然为:

$ \log P(d^c | x) \propto \log \left( \sum_{i} p_i^c \exp\left(-\frac{1}{2} |d^c - o_ic|2\right) \right) $

我们希望最大化这个对数似然,使真实目标 $ d^c $ 在模型预测的混合分布下具有高概率。

损失函数(Negative Log-Likelihood)

等价地,定义单个任务/样本的损失函数为负对数似然:

$ E^{c} = - \log \left( \sum_{i} p_{i}^{c} \exp\left(-\frac{1}{2} | d^{c} - o_{i}^{c} |^2 \right) \right)
\quad \tag{3} $

这就是 MoE 架构中常用的 混合专家负对数似然损失(MoE NLL Loss)

  • $ \exp\left(-\frac{1}{2} |d^c - o_ic|2\right) $:衡量第 $ i $ 个专家输出 $ o_i^c $ 与真实目标 $ d^c $ 的相似性(越接近,值越大)
  • $ p_i^c $:门控网络赋予该专家的权重,反映其“被信任程度”
  • 整个求和项是加权相似性总和,代表整体模型解释数据的能力
  • 取负对数后,变成最小化目标:当某个 $ p_i^c $ 较大且对应 $ o_i^c $ 接近 $ d^c $ 时,损失较小;否则损失较大
✅ 该损失自动鼓励两种机制:专家准确性:每个专家应尽量准确预测其负责的数据门控合理性:门控网络应将高权重分配给那些能更好拟合当前输入的专家

整个训练集的损失

对于 $ N $ 个样本(或 $ N $ 个任务实例),总损失为所有任务/样本上的平均损失:

$ J = \frac{1}{N} \sum_{c=1}^N E^c = -\frac{1}{N} \sum_{c=1}^N \log \left( \sum_{i} p_{i}^{c} \exp\left(-\frac{1}{2} | d^{c} - o_{i}^{c} |^2 \right) \right) $

该损失可用于端到端训练 MoE 模型中的专家网络门控网络

为什么 (3) 比 (2) 更好?

| 特性 | Eq (2): $ \sum p_i |d - o_i|^2 $ | Eq (3): $ -\log \sum p_i e^{-\frac{1}{2}|d - o_i|^2} $ |
| — | — | — |
| 是否基于概率模型 | 否 | ✅ 是 |
| 是否抑制大误差影响 | 否 | ✅ 是(指数衰减) |
| 是否包含正则化 | 否 | ✅ 是(KL 项) |
| 是否接近“选择最佳专家” | 线性加权 | ✅ 非线性聚合,类似 soft-min |
| 训练稳定性 | 一般 | ✅ 更好 |

实验复现

实验代码

使用多层感知机作为专家网络,简单的前馈网络作为Gating Network复现了MoE,并且根据公式123定义了损失函数,在数据集上合并了MNIST和Fashion MNIST两个数据集,验证模型在处理MNIST和Fashion MNIST两种看起来差异较大的任务时,看Gating Network是否会自动分配不同的专家。

import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms import matplotlib.pyplot as plt import numpy as np import torch.nn.functional as F from torch.utils.data import DataLoader, ConcatDataset from tqdm import tqdm # 定义单个专家的神经网络classSingleExpert(nn.Module):def__init__(self, input_dim=28*28, output_dim=20):super(SingleExpert, self).__init__() self.fc1 = nn.Linear(input_dim,256) self.fc2 = nn.Linear(256,128) self.fc3 = nn.Linear(128, output_dim)defforward(self, x): x = x.view(-1,28*28) x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x)return x # 定义MoE模型classMoE(nn.Module):def__init__(self, input_dim=28*28, output_dim=20, num_experts=4):super(MoE, self).__init__() self.num_experts = num_experts # 定义专家 self.experts = nn.ModuleList([SingleExpert(input_dim, output_dim)for _ inrange(num_experts)])# 定义门网络(决定使用哪个专家) self.gating_network = nn.Linear(input_dim, num_experts)defforward(self, x): x_flat = x.view(-1,28*28)# 获取门网络的概率 gate_outputs = torch.softmax(self.gating_network(x_flat), dim=1)# Shape: [batch_size, num_experts]# 获取每个专家的输出 expert_outputs = torch.stack([expert(x)for expert in self.experts], dim=1)# Shape: [batch_size, num_experts, output_dim]# 随机选择一个专家基于门网络的概率 expert_indices = torch.multinomial(gate_outputs, num_samples=1).squeeze()# Shape: [batch_size]# 收集对应于采样索引的专家输出 final_output = expert_outputs[torch.arange(x.size(0)), expert_indices]# Shape: [batch_size, output_dim]return final_output, expert_outputs, gate_outputs, expert_indices # 定义MoE模型的损失函数defmoe_loss(targets, expert_outputs, gate_outputs):""" 计算MoE模型的损失。 Arguments: - targets: 真实输出向量,形状 [batch_size, output_dim] - expert_outputs: 每个专家的输出向量,形状 [batch_size, num_experts, output_dim] - gate_outputs: 门网络的输出(每个专家的概率),形状 [batch_size, num_experts] Returns: - loss: 计算的损失值 """# 计算目标输出和每个专家输出之间的平方误差 errors = torch.sum((expert_outputs - targets.unsqueeze(1))**2, dim=2)# Shape: [batch_size, num_experts]# 计算负半误差的指数(高斯似然) weighted_errors = torch.exp(-0.5* errors)# Shape: [batch_size, num_experts]# 通过门网络的输出(概率)加权误差 weighted_errors = gate_outputs * weighted_errors # Shape: [batch_size, num_experts]# 对专家求和并取对数以获得负对数似然 loss =-torch.log(torch.sum(weighted_errors, dim=1)+1e-8)# Shape: [batch_size]# 返回批次的平均损失return loss.mean()# 定义MoE模型的均方误差硬损失defmse_hard_loss(targets, expert_outputs, gate_outputs):""" 计算MoE模型的均方误差硬损失。 Arguments: - targets: 真实输出向量,形状 [batch_size, output_dim] - expert_outputs: 每个专家的输出向量,形状 [batch_size, num_experts, output_dim] - gate_outputs: 门网络的输出(每个专家的概率),形状 [batch_size, num_experts] Returns: - loss: 计算的损失值 """# Step 1: 使用门控权重对专家输出进行加权求和(融合输出) fused_output = torch.sum(gate_outputs.unsqueeze(-1)* expert_outputs, dim=1)# [batch_size, output_dim]# Step 2: 计算融合输出与目标之间的 L2 距离平方 reconstruction_error = torch.sum((fused_output - targets)**2, dim=1)# [batch_size]# Step 3: 取 batch 平均作为最终损失 loss = torch.mean(reconstruction_error)# 返回批次的平均损失return loss # 定义MoE模型的均方误差软损失defmse_soft_loss(targets, expert_outputs, gate_outputs):""" 计算MoE模型的均方误差损失。 Arguments: - targets: 真实输出向量,形状 [batch_size, output_dim] - expert_outputs: 每个专家的输出向量,形状 [batch_size, num_experts, output_dim] - gate_outputs: 门网络的输出(每个专家的概率),形状 [batch_size, num_experts] Returns: - loss: 计算的损失值 """ errors = torch.sum((expert_outputs - targets.unsqueeze(1))**2, dim=2)# Shape: [batch_size, output_dim] weighted_errors = gate_outputs * errors # Shape: [batch_size, output_dim]# 对专家求和并取平均以获得均方误差 loss = torch.mean(weighted_errors)# 返回批次的平均损失return loss defone_hot_encoding(labels, num_classes=10):# 确保标签矩阵在与标签相同的设备上创建return torch.eye(num_classes, device=labels.device)[labels]# 训练循环,跟踪专家选择deftrain(model, dataloader, optimizer, num_epochs=10, loss_name='moe'): model.train()# 初始化专家选择计数器 expert_selection_count = torch.zeros(model.num_experts, device=device)for epoch inrange(num_epochs): running_loss =0.0 correct =0 total =0# 使用tqdm显示进度for inputs, labels in tqdm(dataloader): inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad()# 前向传播 final_output, expert_outputs, gate_outputs, expert_indices = model(inputs)# 统计专家选择次数for idx in expert_indices: expert_selection_count[idx]+=1# 将标签转换为独热编码 one_hot_labels = one_hot_encoding(labels, num_classes=len(combined_classes))# 计算MoE损失if loss_name =='moe': loss = moe_loss(one_hot_labels, expert_outputs, gate_outputs)elif loss_name =='mse_hard': loss = mse_hard_loss(one_hot_labels, expert_outputs, gate_outputs)elif loss_name =='mse_soft': loss = mse_soft_loss(one_hot_labels, expert_outputs, gate_outputs) loss.backward() optimizer.step() running_loss += loss.item() _, predicted = torch.max(final_output,1) total += labels.size(0) correct +=(predicted == labels).sum().item()print(f'Epoch [{epoch +1}/{num_epochs}], Loss: {running_loss /len(dataloader):.4f}, Accuracy: {100* correct / total:.2f}%')# 输出专家选择次数print("\n专家选择次数统计(训练集):")for i, count inenumerate(expert_selection_count):print(f'专家 {i}: 被选择 {count.item()} 次')return expert_selection_count # 测试循环,跟踪专家选择(用于数据集层面和类别层面)deftest_with_expert_statistics(model, dataloader, dataset_name="", num_classes=20): model.eval() correct =0 total =0# 初始化专家选择计数器(数据集层面) expert_selection_count = torch.zeros(model.num_experts, device=device)with torch.no_grad():for inputs, labels in dataloader: inputs, labels = inputs.to(device), labels.to(device)# 前向传播 final_output, _, _, expert_indices = model(inputs)# 统计专家选择次数(数据集层面)for idx in expert_indices: expert_selection_count[idx]+=1# 获取预测 _, predicted = torch.max(final_output,1) total += labels.size(0) correct +=(predicted == labels).sum().item() accuracy =100* correct / total print(f'\n{dataset_name} 测试集准确率: {accuracy:.2f}%')# 输出专家选择次数统计(数据集层面)print(f"\n{dataset_name} 专家选择次数统计(数据集层面):")for i, count inenumerate(expert_selection_count):print(f'专家 {i}: 被选择 {count.item()} 次,占比 {100* count.item()/ total:.2f}%')return accuracy, expert_selection_count if __name__ =="__main__":# # 主实验 batch_size =1024 num_experts =4 loss_name =['moe','mse_hard','mse_soft'][1] device = torch.device('cpu')ifnot torch.cuda.is_available()else torch.device('cuda:0')# 定义数据预处理 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,),(0.5,))])# 加载 MNIST 和 Fashion-MNIST 数据集 mnist_train = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform) mnist_test = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform) fashion_mnist_train = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform) fashion_mnist_test = torchvision.datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)# 修改 Fashion-MNIST 的标签,使其与 MNIST 标签区分开来(加上 10) fashion_mnist_train.targets = fashion_mnist_train.targets +10 fashion_mnist_test.targets = fashion_mnist_test.targets +10# 合并训练集和测试集 combined_train_data = ConcatDataset([mnist_train, fashion_mnist_train]) combined_test_data = ConcatDataset([mnist_test, fashion_mnist_test])# 打印合并后的数据集信息print(f"训练集样本数: {len(combined_train_data)}")print(f"测试集样本数: {len(combined_test_data)}")# 定义 MNIST 和 Fashion-MNIST 的类别名称 mnist_classes =[str(i)for i inrange(10)]# MNIST 类别是 '0' 到 '9' fashion_mnist_classes =['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot']# Fashion-MNIST 类别# 合并 MNIST 和 Fashion-MNIST 的类别名称 combined_classes = mnist_classes + fashion_mnist_classes # 创建数据加载器 train_loader = DataLoader(combined_train_data, batch_size=batch_size, shuffle=True) test_loader = DataLoader(combined_test_data, batch_size=batch_size, shuffle=False)# MoE模型 moe_model = MoE(output_dim=len(combined_classes), num_experts=num_experts).to(device) optimizer_moe = optim.Adam(moe_model.parameters(), lr=0.001)print("\n训练MoE模型...") train_expert_selection = train(moe_model, train_loader, optimizer_moe, num_epochs=10, loss_name=loss_name)print("测试MoE模型在MNIST和Fashion-MNIST上...")# 测试在单个数据集上print("测试在MNIST数据集上...") mnist_test_loader = DataLoader(mnist_test, batch_size=batch_size, shuffle=False) test_accuracy_mnist, mnist_expert_selection = test_with_expert_statistics( moe_model, mnist_test_loader, dataset_name="MNIST", num_classes=len(combined_classes))print("测试在Fashion-MNIST数据集上...") fashion_mnist_test_loader = DataLoader(fashion_mnist_test, batch_size=batch_size, shuffle=False) test_accuracy_fashion_mnist, fashion_mnist_expert_selection = test_with_expert_statistics( moe_model, fashion_mnist_test_loader, dataset_name="Fashion-MNIST", num_classes=len(combined_classes))

训练参数固定如下:

  • batch=1024
  • epoch=10
  • expert=4

对比三种损失函数:

  • 公式1 mse-hard
  • 公式2 mse-soft
  • 公式3 moe

实验分析

公式1 mse-hard

训练日志如下

Epoch [1/10], Loss: 0.3535, Accuracy: 64.07% Epoch [2/10], Loss: 0.1851, Accuracy: 80.30% Epoch [3/10], Loss: 0.1515, Accuracy: 84.36% Epoch [4/10], Loss: 0.1331, Accuracy: 86.52% Epoch [5/10], Loss: 0.1210, Accuracy: 88.03% Epoch [6/10], Loss: 0.1123, Accuracy: 89.14% Epoch [7/10], Loss: 0.1066, Accuracy: 89.77% Epoch [8/10], Loss: 0.0995, Accuracy: 90.36% Epoch [9/10], Loss: 0.0943, Accuracy: 90.98% Epoch [10/10], Loss: 0.0908, Accuracy: 91.47% 专家选择次数统计(训练集): 专家 0: 被选择 537500.0 次 专家 1: 被选择 167879.0 次 专家 2: 被选择 194856.0 次 专家 3: 被选择 299765.0 次 测试MoE模型在MNIST和Fashion-MNIST上... 测试在MNIST数据集上... MNIST 测试集准确率: 93.73% MNIST 专家选择次数统计(数据集层面): 专家 0: 被选择 4584.0 次,占比 45.84% 专家 1: 被选择 1927.0 次,占比 19.27% 专家 2: 被选择 1194.0 次,占比 11.94% 专家 3: 被选择 2295.0 次,占比 22.95% 测试在Fashion-MNIST数据集上... Fashion-MNIST 测试集准确率: 85.36% Fashion-MNIST 专家选择次数统计(数据集层面): 专家 0: 被选择 4290.0 次,占比 42.90% 专家 1: 被选择 1249.0 次,占比 12.49% 专家 2: 被选择 1622.0 次,占比 16.22% 专家 3: 被选择 2839.0 次,占比 28.39% 

公式2 mse-soft

训练日志如下

Epoch [1/10], Loss: 0.0924, Accuracy: 79.95% Epoch [2/10], Loss: 0.0470, Accuracy: 89.93% Epoch [3/10], Loss: 0.0381, Accuracy: 91.64% Epoch [4/10], Loss: 0.0341, Accuracy: 92.55% Epoch [5/10], Loss: 0.0311, Accuracy: 93.20% Epoch [6/10], Loss: 0.0286, Accuracy: 93.82% Epoch [7/10], Loss: 0.0271, Accuracy: 94.16% Epoch [8/10], Loss: 0.0255, Accuracy: 94.49% Epoch [9/10], Loss: 0.0241, Accuracy: 94.82% Epoch [10/10], Loss: 0.0230, Accuracy: 95.05% 专家选择次数统计(训练集): 专家 0: 被选择 884.0 次 专家 1: 被选择 1861.0 次 专家 2: 被选择 377796.0 次 专家 3: 被选择 819459.0 次 测试MoE模型在MNIST和Fashion-MNIST上... 测试在MNIST数据集上... MNIST 测试集准确率: 97.57% MNIST 专家选择次数统计(数据集层面): 专家 0: 被选择 0.0 次,占比 0.00% 专家 1: 被选择 0.0 次,占比 0.00% 专家 2: 被选择 14.0 次,占比 0.14% 专家 3: 被选择 9986.0 次,占比 99.86% 测试在Fashion-MNIST数据集上... Fashion-MNIST 测试集准确率: 88.30% Fashion-MNIST 专家选择次数统计(数据集层面): 专家 0: 被选择 1.0 次,占比 0.01% 专家 1: 被选择 2.0 次,占比 0.02% 专家 2: 被选择 6474.0 次,占比 64.74% 专家 3: 被选择 3523.0 次,占比 35.23% 

公式3 moe

训练日志如下

Epoch [1/10], Loss: 0.1878, Accuracy: 79.58% Epoch [2/10], Loss: 0.0981, Accuracy: 89.75% Epoch [3/10], Loss: 0.0807, Accuracy: 91.44% Epoch [4/10], Loss: 0.0717, Accuracy: 92.37% Epoch [5/10], Loss: 0.0658, Accuracy: 92.96% Epoch [6/10], Loss: 0.0612, Accuracy: 93.35% Epoch [7/10], Loss: 0.0576, Accuracy: 93.79% Epoch [8/10], Loss: 0.0549, Accuracy: 94.12% Epoch [9/10], Loss: 0.0520, Accuracy: 94.49% Epoch [10/10], Loss: 0.0492, Accuracy: 94.74% 专家选择次数统计(训练集): 专家 0: 被选择 2878.0 次 专家 1: 被选择 132251.0 次 专家 2: 被选择 1063670.0 次 专家 3: 被选择 1201.0 次 测试MoE模型在MNIST和Fashion-MNIST上... 测试在MNIST数据集上... MNIST 测试集准确率: 97.67% MNIST 专家选择次数统计(数据集层面): 专家 0: 被选择 0.0 次,占比 0.00% 专家 1: 被选择 0.0 次,占比 0.00% 专家 2: 被选择 10000.0 次,占比 100.00% 专家 3: 被选择 0.0 次,占比 0.00% 测试在Fashion-MNIST数据集上... Fashion-MNIST 测试集准确率: 87.77% Fashion-MNIST 专家选择次数统计(数据集层面): 专家 0: 被选择 0.0 次,占比 0.00% 专家 1: 被选择 2576.0 次,占比 25.76% 专家 2: 被选择 7424.0 次,占比 74.24% 专家 3: 被选择 0.0 次,占比 0.00% 

分析

总体性能对比

损失函数MNIST 准确率Fashion-MNIST 准确率训练 Loss 下降速度专家多样性
MSE-Hard (1)93.73%85.36%中等专家均衡
MSE-Soft (2)97.57%88.30%极快专家崩溃
MoE (3)97.67%87.77%偏向单一专家(MNIST)

专家分布对比总结

模型MNIST 专家分布Fashion-MNIST 专家分布是否专业化是否稀疏
MSE-Hard均匀(45%/19%/12%/23%)均匀(43%/12%/16%/28%)
MSE-Soft专家3 占 99.86%专家2/3 主导崩溃伪稀疏
MoE Loss专家2 占 100%专家2(74%) + 专家1(26%)

Read more

猛裁1.6万人后,网站再崩6小时、一周4次重大事故!官方“紧急复盘”:跟裁员无关,也不是AI写代码的锅

猛裁1.6万人后,网站再崩6小时、一周4次重大事故!官方“紧急复盘”:跟裁员无关,也不是AI写代码的锅

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 过去几年里,科技公司几乎都在同一件事上加速:让 AI 参与写代码。 从自动补全、自动生成函数,到直接修改系统配置,生成式 AI 已经逐渐走进真实生产环境。但最近发生在亚马逊的一连串事故,却给整个行业泼了一盆冷水——当 AI 开始真正参与生产环境开发时,事情可能远比想象复杂。 最近,多家媒体披露,本周二亚马逊内部紧急召开了一场工程“深度复盘(deep dive)”会议,专门讨论最近频繁出现的系统故障——其中,一个被反复提及的关键词是:AI 辅助代码。 一周 4 次严重事故,亚马逊内部紧急复盘 事情的起点,是最近一段时间亚马逊系统稳定性明显下降。 负责亚马逊网站技术架构的高级副总裁 Dave Treadwell 在一封内部邮件中坦言:“各位,正如大家可能已经知道的,最近网站及相关基础设施的可用性确实不太理想。” 为此,公司决定把原本每周例行举行的技术会议

By Ne0inhk
这回真的“装”到了!来OpenClaw全国纵深行,你只需要带一台电脑……

这回真的“装”到了!来OpenClaw全国纵深行,你只需要带一台电脑……

AI Agent 的风,已经从 GitHub 吹到了线下。 过去几个月,越来越多开发者开始讨论一个问题: 当 AI 不再只是聊天,而是可以执行任务,软件会变成什么样? 在这股浪潮中,一个开源项目迅速进入开发者视野——OpenClaw,在 GitHub 上获得大量关注,相关教程、实践案例不断出现。有人用它自动整理资料,有人用它管理开发流程,还有人尝试让它执行复杂的工作流。 很多开发者第一次意识到: AI 不只是工具,它可能成为“执行者”。 不过,在技术社区之外,大多数人对 Agent 的理解仍停留在概念层面。 * AI Agent 到底是什么? * 如何在自己的电脑上运行? * 普通开发者能否真正用起来? 带着这些问题,一场围绕 OpenClaw 的开发者城市行动正在展开。 ZEEKLOG 发起的OpenClaw 全国纵深行将走进 20 个城市,用最直接的方式回答一个问题——如果

By Ne0inhk
MySQL 安装配置(完整教程)

MySQL 安装配置(完整教程)

文章目录 * 一、MySQL 简介 * 二、下载 MySQL * 三、安装 MySQL * 四、配置环境变量 * 五、配置 MySQL * 5.1 初始化 MySQL * 5.2 搭建 MySQL 环境 * 六、修改 MySQL 密码 * 七、卸载 MySQL * 八、结语 一、MySQL 简介 MySQL 是一款广泛使用的开源关系型数据库管理系统(RDBMS),由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司旗下产品。 发展历史: * MySQL 于 1995

By Ne0inhk