Files
paddlepaddle--paddle/python/paddle/incubate/nn/functional/cal_aux_loss.py
T
2026-07-13 12:40:42 +08:00

165 lines
4.5 KiB
Python

# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from typing import TYPE_CHECKING
import paddle
from paddle import _C_ops
# from ....framework import LayerHelper, in_dynamic_or_pir_mode
from paddle.base.framework import in_dynamic_or_pir_mode
from paddle.base.layer_helper import LayerHelper
if TYPE_CHECKING:
from paddle import Tensor
def math_cal_aux_loss(
gate_prob: Tensor,
dispatch_mask: Tensor,
tokens_mask: Tensor,
dispatch_tokens_mask: Tensor,
num_experts: int,
use_group: bool,
moe_k: int,
clip_min: float,
name: str | None = None,
) -> Tensor:
"""
Args:
gate_prob
dispatch_mask
tokens_mask
dispatch_tokens_mask
num_experts
use_group
moe_k
clip_min
Returns:
l_aux
seqlen_float
ce
"""
if tokens_mask is not None and tokens_mask.dtype != gate_prob.dtype:
tokens_mask = tokens_mask.astype(gate_prob.dtype)
scale = None
if dispatch_tokens_mask is not None:
seqlen_float = dispatch_tokens_mask.astype(gate_prob.dtype).sum()
if (
tokens_mask is not None
and gate_prob.shape[0] != dispatch_tokens_mask.shape[0]
):
scale = seqlen_float / paddle.clip(tokens_mask.sum(), min=clip_min)
elif tokens_mask is not None:
seqlen_float = tokens_mask.sum()
else:
seqlen_float = gate_prob.numel().astype(gate_prob.dtype) / num_experts
seqlen_float = paddle.clip(seqlen_float, min=clip_min)
if len(dispatch_mask.shape) == 2:
dispatch_mask = dispatch_mask.sum(0)
ce = dispatch_mask.astype(gate_prob.dtype).detach() / seqlen_float
me = paddle.sum(gate_prob, axis=0) / seqlen_float
l_aux = paddle.sum(me * ce) * num_experts
if use_group:
l_aux = l_aux / moe_k
if scale is not None:
# forward local me, backward global me
one = paddle.ones([], dtype="float32")
l_aux = l_aux + (scale - one) * l_aux.detach()
return l_aux, seqlen_float, ce
def cal_aux_loss(
gate_prob: Tensor,
dispatch_mask: Tensor,
tokens_mask: Tensor,
dispatch_tokens_mask: Tensor,
num_experts: int,
use_group: bool,
moe_k: int,
clip_min: float,
name: str | None = None,
) -> Tensor:
"""
Args:
gate_prob:
dispatch_mask:
tokens_mask:
dispatch_tokens_mask:
num_experts:
use_group:
moe_k:
clip_min:
Returns:
"""
if in_dynamic_or_pir_mode():
if paddle.is_compiled_with_xpu():
return math_cal_aux_loss(
gate_prob,
dispatch_mask,
tokens_mask,
dispatch_tokens_mask,
num_experts,
use_group,
moe_k,
clip_min,
)
else:
return _C_ops.cal_aux_loss(
gate_prob,
dispatch_mask,
tokens_mask,
dispatch_tokens_mask,
num_experts,
use_group,
moe_k,
clip_min,
)
helper = LayerHelper('cal_aux_loss', **locals())
l_aux_loss = helper.create_variable_for_type_inference(
dtype=gate_prob.dtype
)
seqlen_float = helper.create_variable_for_type_inference(
dtype=gate_prob.dtype
)
ce = helper.create_variable_for_type_inference(dtype=gate_prob.dtype)
inputs = {
'gate_prob': gate_prob,
'dispatch_mask': dispatch_mask,
'tokens_mask': tokens_mask,
'dispatch_tokens_mask': dispatch_tokens_mask,
}
attrs = {
'num_experts': num_experts,
'use_group': use_group,
'moe_k': moe_k,
'clip_min': clip_min,
}
outputs = {'l_aux_loss': l_aux_loss, 'seqlen_float': seqlen_float, 'ce': ce}
helper.append_op(
type='cal_aux_loss', inputs=inputs, attrs=attrs, outputs=outputs
)
return l_aux_loss, seqlen_float, ce