Mixture of experts

Reference code deepseek-ai/DeepSeek-V3.2-Exp @ 87e509a · checkpoint, tokenizer and tensors not verified · How to read

61 transformer blocks › 58 MoE blocks › Mixture of experts

learnedself.gate

Score all 256 experts for each position and keep 8 from the best 4 of 8 groups; their weights are normalized, then scaled by 2.5.

Eisel=[ i∈top⁡8(s+b) within the top 4 groups ]E^{\mathrm{sel}}_i=\big[\,i\in\operatorname{top}_{8}(s+b)\text{ within the top }4\text{ groups}\,\big]
Gi=2.5 si Eisel∑jsj EjselG_{i}=2.5\,\frac{s_i\,E^{\mathrm{sel}}_i}{\sum_{j}s_j\,E^{\mathrm{sel}}_j}
All 4 steps
z=xffnWrz=x_{\mathrm{ffn}}W_{r}
s=σ(z)s=\sigma(z)
Eisel=[ i∈top⁡8(s+b) within the top 4 groups ]E^{\mathrm{sel}}_i=\big[\,i\in\operatorname{top}_{8}(s+b)\text{ within the top }4\text{ groups}\,\big]
Gi=2.5 si Eisel∑jsj EjselG_{i}=2.5\,\frac{s_i\,E^{\mathrm{sel}}_i}{\sum_{j}s_j\,E^{\mathrm{sel}}_j}
in
xffnx_{\mathrm{ffn}} [B batch, T positions, 7168 d]
out
GG [B batch, T positions, 256 experts]
parameters
1,835,264 · × 58 MoE blocks = 106,445,312
Parameters

1,835,264 parameters per instance, across its learned components

Exact per-instance accounting
ComponentCalculationParameters
Expert scores7,168×2567{,}168 \times 2561,835,008
Select experts256256256
Per-instance total1,835,264

Across 58 independent MoE blocks: 1,835,264×58=106,445,3121{,}835{,}264 \times 58 = 106{,}445{,}312 parameters.

Derived from the pinned reference configuration and inference code. Checkpoint tensors have not been independently counted; FP8 block scales and the multi-token-prediction module are not counted.

Explanation

The reference returns each position’s 8 weights with their expert indices (model.py 709); GG spreads them over all 256 experts, zero for the other 248.

Codemodel.py 668–675, 687–709
model.py 668–675
        self.dim = args.dim
        self.topk = args.n_activated_experts
        self.n_groups = args.n_expert_groups
        self.topk_groups = args.n_limited_groups
        self.score_func = args.score_func
        self.route_scale = args.route_scale
        self.weight = nn.Parameter(torch.empty(args.n_routed_experts, args.dim))
        self.bias = nn.Parameter(torch.empty(args.n_routed_experts, dtype=torch.float32)) if self.dim == 7168 else None
model.py 687–709
        scores = linear(x.float(), self.weight.float())
        if self.score_func == "softmax":
            scores = scores.softmax(dim=-1)
        else:
            scores = scores.sigmoid()
        original_scores = scores
        if self.bias is not None:
            scores = scores + self.bias
        if self.n_groups > 1:
            scores = scores.view(x.size(0), self.n_groups, -1)
            if self.bias is None:
                group_scores = scores.amax(dim=-1)
            else:
                group_scores = scores.topk(2, dim=-1)[0].sum(dim=-1)
            indices = group_scores.topk(self.topk_groups, dim=-1)[1]
            mask = scores.new_ones(x.size(0), self.n_groups, dtype=bool).scatter_(1, indices, False)
            scores = scores.masked_fill_(mask.unsqueeze(-1), float("-inf")).flatten(1)
        indices = scores.topk(self.topk, dim=-1)[1]
        weights = original_scores.gather(1, indices)
        if self.score_func == "sigmoid":
            weights /= weights.sum(dim=-1, keepdim=True)
        weights *= self.route_scale
        return weights, indices
Sources2

Direct evidence

The router owns one score vector per routed expert and, at this width, a per-expert bias used only for selection.

gate-init · deepseek-ai/DeepSeek-V3.2-Exp / inference/model.py
Pinned revision 87e509a2e5a1 ↗ · lines 668–675

Read code excerpt
        self.dim = args.dim
        self.topk = args.n_activated_experts
        self.n_groups = args.n_expert_groups
        self.topk_groups = args.n_limited_groups
        self.score_func = args.score_func
        self.route_scale = args.route_scale
        self.weight = nn.Parameter(torch.empty(args.n_routed_experts, args.dim))
        self.bias = nn.Parameter(torch.empty(args.n_routed_experts, dtype=torch.float32)) if self.dim == 7168 else None

Direct evidence

Routing: sigmoid scores, bias added for selection, the best groups kept by their top-two scores, the top-8 experts chosen, their unbiased scores renormalized and scaled.

gate-forward · deepseek-ai/DeepSeek-V3.2-Exp / inference/model.py
Pinned revision 87e509a2e5a1 ↗ · lines 687–709

Read code excerpt
        scores = linear(x.float(), self.weight.float())
        if self.score_func == "softmax":
            scores = scores.softmax(dim=-1)
        else:
            scores = scores.sigmoid()
        original_scores = scores
        if self.bias is not None:
            scores = scores + self.bias
        if self.n_groups > 1:
            scores = scores.view(x.size(0), self.n_groups, -1)
            if self.bias is None:
                group_scores = scores.amax(dim=-1)
            else:
                group_scores = scores.topk(2, dim=-1)[0].sum(dim=-1)
            indices = group_scores.topk(self.topk_groups, dim=-1)[1]
            mask = scores.new_ones(x.size(0), self.n_groups, dtype=bool).scatter_(1, indices, False)
            scores = scores.masked_fill_(mask.unsqueeze(-1), float("-inf")).flatten(1)
        indices = scores.topk(self.topk, dim=-1)[1]
        weights = original_scores.gather(1, indices)
        if self.score_func == "sigmoid":
            weights /= weights.sum(dim=-1, keepdim=True)
        weights *= self.route_scale
        return weights, indices