神经网络的训练主要使用反向传播算法,该算法通过计算梯度来优化模型参数。自动微分是一种计算可导函数在某点处导数值的方法,它是反向传播算法的基础。自动微分能够将复杂的数学运算分解为一系列简单的基本运算,极大地简化了求导过程。
MindSpore通过函数式自动微分的设计理念,提供了更接近数学语义的自动微分接口grad
和value_and_grad
。
环境配置
%%capture captured_output
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
函数与计算图
计算图是用图论语言表示数学函数的一种方式。在深度学习中,计算图用于表达神经网络模型的计算过程。下面的计算图展示了一个简单的单层线性变换模型。
- 输入:𝑥
- 目标值:𝑦
- 参数:𝑤和𝑏
import numpy as np
import mindspore
from mindspore import nn, ops, Tensor, Parameter
x = ops.ones(5, mindspore.float32) # input tensor
y = ops.zeros(3, mindspore.float32) # expected output
w = Parameter(Tensor(np.random.randn(5, 3), mindspore.float32), name='w') # weight
b = Parameter(Tensor(np.random.randn(3,), mindspore.float32), name='b') # bias
计算函数
根据计算图描述的计算过程,构造计算函数。使用binary_cross_entropy_with_logits
计算损失。
def function(x, y, w, b):
z = ops.matmul(x, w) + b
loss = ops.binary_cross_entropy_with_logits(z, y, ops.ones_like(z), ops.ones_like(z))
return loss
loss = function(x, y, w, b)
print(loss) # 输出:Tensor(shape=[], dtype=Float32, value= 0.914285)
微分函数与梯度计算
为了优化模型参数,需要计算参数对loss的导数:∂loss/∂𝑤 和 ∂loss/∂𝑏。使用mindspore.grad
函数获得微分函数。
grad_fn = mindspore.grad(function, (2, 3))
grads = grad_fn(x, y, w, b)
print(grads)
Stop Gradient
如果希望屏蔽某个输出项对梯度的影响,可以使用ops.stop_gradient
操作。
def function_stop_gradient(x, y, w, b):
z = ops.matmul(x, w) + b
loss = ops.binary_cross_entropy_with_logits(z, y, ops.ones_like(z), ops.ones_like(z))
return loss, ops.stop_gradient(z)
grad_fn = mindspore.grad(function_stop_gradient, (2, 3))
grads = grad_fn(x, y, w, b)
print(grads)
Auxiliary Data
使用grad
和value_and_grad
接口的has_aux
参数,可以自动实现前文手动添加stop_gradient
的功能。
grad_fn = mindspore.grad(function_with_logits, (2, 3), has_aux=True)
grads, (z,) = grad_fn(x, y, w, b)
print(grads, z)
神经网络梯度计算
使用面向对象编程范式的nn.Cell
构造神经网络模型,并使用函数式自动微分来实现反向传播。
class Network(nn.Cell):
def __init__(self):
super().__init__()
self.w = w
self.b = b
def construct(self, x):
z = ops.matmul(x, self.w) + self.b
return z
model = Network()
loss_fn = nn.BCEWithLogitsLoss()
def forward_fn(x, y):
z = model(x)
loss = loss_fn(z, y)
return loss
grad_fn = mindspore.value_and_grad(forward_fn, None, weights=model.trainable_params())
loss, grads = grad_fn(x, y)
print(grads)
总结
通过上述示例,展示了MindSpore中如何使用函数式自动微分接口grad
和value_and_grad
来计算梯度。
这些接口提供了更接近数学语义的自动微分方式,大大简化了深度学习模型的训练过程。自动微分通过将复杂的数学运算分解为一系列简单的基本运算,极大地降低了框架的使用门槛。
总结
操作 | 说明 | 示例 |
---|---|---|
ops.ones | 创建全为1的Tensor | ops.ones(5, mindspore.float32) |
ops.zeros | 创建全为0的Tensor | ops.zeros(3, mindspore.float32) |
Parameter | 定义参数 | Parameter(Tensor(np.random.randn(5, 3), mindspore.float32), name='w') |
mindspore.grad | 计算梯度函数 | grad_fn = mindspore.grad(function, (2, 3)) |
ops.stop_gradient | 停止梯度传播 | ops.stop_gradient(z) |
nn.Cell | 定义神经网络模型 | class Network(nn.Cell): |
value_and_grad | 计算值和梯度 | grad_fn = mindspore.value_and_grad(forward_fn, None, weights=model.trainable_params()) |