1、前言
在有限的计算资源预算下,用更少的训练步数训练更大的模型,往往比耗费更多的步数来训练模型效果更佳。比如,由于大规模推荐系统可能包含数百万甚至数十亿的参数,这些额外的参数往往是欠约束的,这可能会损害模型质量。于是,就有了专家模型(moe)。
2、MOE介绍
MoE是一种大型模型架构(图b)。一个MoE模型可以被视为由不同的子模型(或专家)组成,每个子模型专门从事不同的输入,一个可训练的门控网络(gate)决定了这些专家(expert)对每个实例所使用的稀疏组合。具体来说,每一层的专家都由门控网络控制,门控网络根据输入数据激活专家。
每一个expert都是基于DNN(深度神经网络)构造的,简单来说就是一个expert就是一个神经网络,Gate可以看作是我们要选择哪些专家(分配权重到各个Expert,即组合不同的深度神经网络)来处理输出的数据。Gate的输出是传统网络每一层对input(输入数据)进行处理得到
3、Pytorch实现
class MOELayer(nn.Module):
def __init__(self, input_dim, num_tasks, num_experts, dnn_hidden_units, dr, device):
super(MOELayer, self).__init__()
self.input_dim = input_dim
self.num_experts = num_experts # 专家个数
self.num_tasks = num_tasks # 任务个数tower
self.dnn_hidden_units = dnn_hidden_units # 隐藏层个数
self.expert_network = nn.ModuleList([DNN(input_dim, dnn_hidden_units,
activation='relu', l2_reg=0.1, dropout_rate=dr, use_bn=True,
init_std=0.001, device=device) for _ in range(self.num_experts)])
# 计算专家权重
self.gate_list = {} # 每个任务的门控权重
for g in range(self.num_tasks):
self.gate_list[g] = []
self.d = {} # 保存门控可学习参数
for i in range(self.num_tasks):
# 生成一个包含 num_experts个随机数的张量,这些随机数将作为初始化的门控权重。
self.d['gate_'+str(i)] = nn.Parameter(torch.rand(self.num_experts), requires_grad=True)
# 将门控权重参数添加到模型的参数中
self.gate = nn.ParameterDict(self.d)
def forward(self, inputs):
expert_list = []
for i in range(self.num_experts):
expert_out = self.expert_network[i](inputs)
expert_list.append(expert_out)
# 新张量的形状为 [batch_size, feature_dim, len(expert_list)]
final_expert = torch.stack(expert_list, 2) # 专家输出
# 专家组合
outputs = []
for i in range(self.num_tasks):
self.gate_list[i] = self.gate['gate_'+str(i)].softmax(0)
out_ = final_expert*self.gate_list[i]
out = torch.sum(out_, 2) # 加权求和
outputs.append(out)
return outputs, self.gate_list
4、MOE的应用
在自然语言处理领域,MoE显示出了显著的优势。通过在LSTM层之间合并MoE,已经提高了机器翻译的性能。 Switch Transformer和GLaM 进一步探索了MoE技术在自然语言处理中的潜力,取得了优异的性能。