昇思25天学习打卡营第7天|函数式自动微分

概念

神经网络的训练主要使用反向传播算法,模型预测值(logits)与正确标签(label)送入损失函数(loss function)获得loss,然后进行反向传播计算,求得梯度(gradients),最终更新至模型参数(parameters)。自动微分能够计算可导函数在某点处的导数值,是反向传播算法的一般化。自动微分主要解决的问题是将一个复杂的数学运算分解为一系列简单的基本运算,该功能对用户屏蔽了大量的求导细节和过程,大大降低了框架的使用门槛。

函数与计算图

计算图是用图论语言表示数学函数的一种方式,也是深度学习框架表达神经网络模型的统一方法。
计算图
根据计算图构造计算函数和神经网络,x为输入,y为正确值,wb是需要优化的参数。
代码示例:

import numpy as np
import mindspore
from mindspore import nn
from mindspore import ops
from mindspore import 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)

# 运行结果:
# 1.3518304

微分函数与梯度计算

为了优化模型参数,需要求参数对loss的导数: ∂ loss ⁡ ∂ w \frac{\partial \operatorname{loss}}{\partial w} wloss ∂ loss ⁡ ∂ b \frac{\partial \operatorname{loss}}{\partial b} bloss,可以调用mindspore.grad函数,来获得function的微分函数。
代码示例:

# fn:待求导的函数
# grad_position:指定求导输入位置的索引
grad_fn = mindspore.grad(function, (2, 3))

# 执行微分函数
grads = grad_fn(x, y, w, b)
# 打印出w、b对应的梯度
print(grads)

# 运行结果:
'''
(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01]]), Tensor(shape=[3], dtype=Float32, value= [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01]))
'''

自定义神经网络梯度计算

可以通过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)

# 运行结果:
'''
(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01],
 [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01]]), Tensor(shape=[3], dtype=Float32, value= [ 1.74830750e-01,  2.91909929e-02,  3.20021242e-01]))
'''

我们会发现,自定义神经网络与MindSpore内置梯度计算函数,所得到的梯度值结果一致。

参考

MindSpore教程

截图时间截图时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值