在昇思 MindSpore 中,后向算子(Backward Operator) 是自动微分(Auto Gradient)的核心,用于计算神经网络训练过程中的梯度。简单来说:前向算子负责计算输出,后向算子负责计算梯度。昇思通过自动微分机制 + 自定义 BProp 函数 + 原语算子注册三种方式实现后向算子,支持自动生成、手动定义、底层扩展全场景需求,是训练框架的核心能力。
一、昇思实现后向算子核心内容
1. 基本原理:前向传播与反向传播
- 前向(Forward):输入数据,通过算子计算输出(y=f(x))。
- 反向(Backward):根据链式法则,计算损失对输入 / 权重的梯度(∂x∂L)。
- 后向算子本质:就是梯度计算函数,由框架自动生成或手动实现。
2. 昇思实现后向算子的三种方式
- 自动微分(AutoGrad)
- 框架自动推导梯度,无需手动写后向逻辑,适合普通网络层。
- 手动定义 BProp 函数
- 在
nn.Cell中重写bprop()方法,自定义前向 + 反向逻辑,适合自定义算子。 - 底层原语算子注册(Primitives)
- 注册
Forward和Backward原语,用于 C++/Ascend C 底层算子扩展,适配 NPU 加速。
3. 核心机制
- 梯度函数注册表:前向算子 ↔ 后向算子一一映射。
- 高阶微分支持:后向算子可再次求导,自动生成二阶梯度。
- 硬件无感:自动适配 CPU/GPU/Ascend,梯度计算在 NPU 上硬件加速。
二、核心代码示例(三种实现方式)
1. 方式一:自动微分(最简单,框架自动生成后向)
昇思默认支持自动反向传播,使用ops.grad()即可自动生成后向算子。
import mindspore as ms
import mindspore.nn as nn
import mindspore.ops as ops
ms.set_context(mode=ms.GRAPH_MODE, device_target="CPU")
# 定义前向函数
def forward_func(x):
return x * x * x # y = x³
# 自动生成后向算子(梯度计算)
grad_func = ops.grad(forward_func)
x = ms.Tensor(2.0)
forward_output = forward_func(x) # 前向:8
backward_output = grad_func(x) # 后向(梯度):dy/dx=3x²=12
print("前向输出:", forward_output)
print("后向梯度:", backward_output)
2. 方式二:手动实现 bprop ()(自定义前向 + 后向)
重写construct(前向)和bprop(后向),完全控制梯度计算逻辑。
# 自定义Cell,实现前向与后向算子
class MySquare(nn.Cell):
def construct(self, x):
# 前向:y = x²
return x * x
def bprop(self, x, out, dout):
# 后向:手动定义梯度 dy/dx = 2x
# dout:上游传来的梯度
grad_x = 2 * x * dout
return grad_x
# 测试
net = MySquare()
grad_net = ops.grad(net)
x = ms.Tensor(3.0)
print("前向:", net(x)) # 9
print("后向梯度:", grad_net(x)) # 6
3. 方式三:底层原语注册(高级,用于 NPU 算子)
适用于自定义昇腾 C 算子,注册前向 + 后向原语。
from mindspore.ops import prim_attr_register, PrimitiveWithInfer
# 注册自定义前向算子
class MySquarePrim(PrimitiveWithInfer):
@prim_attr_register
def __init__(self):
pass
def infer_shape(self, x_shape):
return x_shape
def infer_dtype(self, x_dtype):
return x_dtype
# 注册后向算子(梯度实现)
@ops.register_grad(MySquarePrim)
def square_backward(x, out, dout):
grad = 2 * x * dout
return grad
# 使用自定义算子
my_square = MySquarePrim()
grad_my_square = ops.grad(my_square)
x = ms.Tensor(4.0)
print("梯度:", grad_my_square(x)) # 8
三、后向算子执行流程
- 执行前向算子,保存输入输出(用于反向计算)。
- 触发反向传播,框架查找对应的后向算子。
- 调用后向算子,根据链式法则计算梯度。
- 梯度回传,更新网络权重。
昇思在图模式下会将前向 + 后向算子整合成计算图,在 NPU 上高效执行。
四、总结
昇思实现后向算子非常灵活:
- 普通开发者用自动微分,零代码实现梯度;
- 算法开发者用bprop 手动定义,灵活控制梯度;
- 底层开发者用原语注册,扩展 NPU 硬件算子。
后向算子是训练的核心,昇思通过自动微分 + 手动定义 + 底层扩展三种方式,实现了易用性、灵活性、高性能的统一,完美支持深度学习训练全场景。