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

打卡

损失函数

损失函数(代价函数)是用来衡量模型预测值与真实值之间差异的函数,不同的损失函数适用于不同类型的问题。常用的损失函数有,均方误差损失(Mean Squared Error, MSE)、RMSE(Root MSE)、交叉熵损失(Cross-Entropy Loss)、对数损失(Log Loss)、Huber损失(Huber Loss)、绝对误差损失(Mean Absolute Error, MAE)。

mindspore.ops 和 mindspore.nn 内置了很多损失函数,本小节用到的有下面两个:

  1. mindspore.ops.binary_cross_entropy_with_logits : 计算预测值和目标值之间的二值交叉熵损失。将输入 logits 设置为 𝑋 ,输入 labels 设置为 𝑌 ,输入 weight 设置为 𝑊 ,输出设置为 𝐿 。
  2. mindspore.nn.BCEWithLogitsLoss :输入经过 sigmoid 激活函数后作为预测值,该函数计算预测值和目标值之间的二值交叉熵损失。
mindspore.ops.binary_cross_entropy_with_logits(
        logits, 
        label, 
        weight=None,  
        pos_weight=None,   
        reduction='mean'
    )
"""ARGS
logits (Tensor) - 输入预测值。其数据类型为float16或float32。

label (Tensor) - 输入目标值,shape与 logits 相同。数据类型为float16或float32。

weight (Tensor,可选) - 指定每个批次二值交叉熵的权重。支持广播,使其shape与 logits 的shape保持一致。数据类型必须为float16或float32。默认值:None , weight 是值为 1 的Tensor。

pos_weight (Tensor,可选) - 指定正类的权重。是一个长度等于分类数的向量。支持广播,使其shape与 logits 的shape保持一致。数据类型必须为float16或float32。默认值:None , pos_weight 是值为 1 的Tensor。

reduction (str,可选) - 指定应用于输出结果的规约计算方式,默认为 'mean', 可选参数如下。
   - 'none':不应用规约方法。
   - 'mean':计算输出元素的加权平均值。
   - 'sum':计算输出元素的总和。
"""

mindspore.nn.BCEWithLogitsLoss(
             reduction='mean', 
             weight=None, 
             pos_weight=None
            )
"""ARGS 
reduction (str,可选) - 指定应用于输出结果的规约计算方式,可选 'none' 、 'mean' 、 'sum' ,默认为 'mean' 。
    - "none":不应用规约方法。
    - "mean":计算输出元素的加权平均值。
    - "sum":计算输出元素的总和。

weight (Tensor, 可选) - 指定每个批次二值交叉熵的权重。如果不是None,将进行广播,其shape与 logits 的shape保持一致,数据类型为float16或float32。默认值: None 。

pos_weight (Tensor, 可选) - 指定正样本的权重。是一个长度等于分类数的向量。如果不是None,将进行广播,其shape与 logits 的shape保持一致,数据类型必须为float16或float32。默认值: None 。
"""

计算图(Computation Graph)

计算图由节点(nodes,如执行数学运算的操作节点、变量节点)边(edges,如数据流、控制流)组成,是一种用于表示数学运算和数据处理流程的图形化工具,在深度学习框架中用于自动微分(即自动计算导数)。

例子:

训练深度学习模型时,首先构建计算图,用于前向传播(Forward Propagation),即从输入数据到输出结果的计算过程;在反向传播(Backward Propagation)过程中,计算图被用于自动计算梯度,这些梯度随后用于更新模型的参数。

前向传播

如下代码例子,构建了前向传播函数过程。x 为输入,y 为正确值,w 和 b 是我们需要优化的参数。

反向传播

自动微分接口 mindspore.grad 和 mindspore.value_and_grad  声称接近于数学语义。

为了优化模型参数,需要求参数对loss的导数,即$\frac{\partial \operatorname{loss}}{\partial w}$ 和 $\frac{\partial \operatorname{loss}}{\partial b}$,通过调用 mindspore.grad 函数,生成求导函数,用于计算给定函数的梯度或微分函数。 

> 使用 grad 获得微分函数是一种函数变换,即输入为函数,输出也为函数。

mindspore.grad( fn,  
                grad_position=0, 
                weights=None, 
                has_aux=False, 
                return_ids=False
              )
"""ARGS
fn (Union[Cell, Function]) - 待求导的函数或网络。

grad_position (Union[NoneType, int, tuple[int]]) - 指定求导输入位置的索引。若为int类型,表示对单个输入求导;若为tuple类型,表示对tuple内索引的位置求导,其中索引从0开始;若是None,表示不对输入求导,这种场景下, weights 非None。默认值: 0 。

weights (Union[ParameterTuple, Parameter, list[Parameter]]) - 训练网络中需要返回梯度的网络变量。一般可通过 weights = net.trainable_params() 获取。默认值: None 。

has_aux (bool) - 是否返回辅助参数的标志。若为 True , fn 输出数量必须超过一个,其中只有 fn 第一个输出参与求导,其他输出值将直接返回。默认值: False 。

return_ids (bool) - 是否返回由返回的梯度和指定求导输入位置的索引或网络变量组成的tuple。若为 True ,其输出中所有的梯度值将被替换为:由该梯度和其输入的位置索引,或者用于计算该梯度的网络变量组成的tuple。默认值: False 。
"""

mindspore.value_and_grad( fn, 
                          grad_position=0, 
                          weights=None, 
                          has_aux=False, 
                          return_ids=False
                        )
"""ARGS
fn (Union[Cell, Function]) - 待求导的函数或网络。

grad_position (Union[NoneType, int, tuple[int]]) - 指定求导输入位置的索引。若为int类型,表示对单个输入求导;若为tuple类型,表示对tuple内索引的位置求导,其中索引从0开始;若是None,表示不对输入求导,这种场景下, weights 非None。默认值: 0 。

weights (Union[ParameterTuple, Parameter, list[Parameter]]) - 训练网络中需要返回梯度的网络变量。一般可通过 weights = net.trainable_params() 获取。默认值: None 。

has_aux (bool) - 是否返回辅助参数的标志。若为 True , fn 输出数量必须超过一个,其中只有 fn 第一个输出参与求导,其他输出值将直接返回。默认值: False 。

return_ids (bool) - 是否返回由返回的梯度和指定求导输入位置的索引或网络变量组成的tuple。若为 True ,其输出中所有的梯度值将被替换为:由该梯度和其输入的位置索引,或者用于计算该梯度的网络变量组成的tuple。默认值: False 。
"""

单输出函数求导-代码例子

如下代码中,mindspore.grad 的求导索引为 (2, 3),表示 function1 函数的参数 w 和 b。

多输出函数求导-代码例子

如下图,函数存在多个输出时,求得𝑤、𝑏对应的梯度值发生了变化。

如果想要屏蔽掉函数输出 z 对梯度的影响,即仍只求参数对loss的导数,可以使用ops.stop_gradient 接口将梯度在函数输出 z 处截断。如下代码图例。

多输出函数求导--将非loss项作为辅助数据输出

Auxiliary data(辅助数据)是函数除第一个输出项外的其他输出。通常将函数的loss设置为函数的第一个输出,其他的输出即为辅助数据。 mindspore.grad 和 mindspore.value_and_grad 提供has_aux 参数,当其设置为True时,可以自动实现前文手动添加 stop_gradient 的功能,满足返回辅助数据的同时不影响梯度计算的效果。

基于Cell网络模型反向传播-代码

使用Cell封装神经网络模型,模型参数w、b均为Cell的内部属性,此时不需要使用求导索引grad_position 对函数输入求导,将其配置为None;此时使用 weights 参数,使用 mindspore.nn.Cell.trainable_params(recurse=True) 方法从Cell中取出可以求导的参数。

本小节代码如下。

import numpy as np
import mindspore
from mindspore import nn
from mindspore import ops
from mindspore import Tensor, Parameter

 
# Define model
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


# Define forward function
def forward_fn(x, y):
    z = model(x)
    loss = loss_fn(z, y)
    return loss


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

# Instantiate model
model = Network()
# Instantiate loss function
loss_fn = nn.BCEWithLogitsLoss()

grad_fn = mindspore.value_and_grad(
            forward_fn, 
            None, 
            weights=model.trainable_params()
        )

loss, grads = grad_fn(x, y)
print(grads)

相关推荐

  1. 25学习22|MindNLP ChatGLM-6B StreamChat

    2024-07-10 04:14:01       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 04:14:01       99 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 04:14:01       107 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 04:14:01       90 阅读
  4. Python语言-面向对象

    2024-07-10 04:14:01       98 阅读

热门阅读

  1. gradle安卓开发软件简介

    2024-07-10 04:14:01       27 阅读
  2. UE5.2 AI实时抠像(无需绿幕) + OBS推流直播 全流程

    2024-07-10 04:14:01       30 阅读
  3. 微软Edge浏览器全解析

    2024-07-10 04:14:01       30 阅读
  4. toString方法介绍

    2024-07-10 04:14:01       22 阅读
  5. LLM大语言模型知识点整理

    2024-07-10 04:14:01       24 阅读
  6. 使用Boost.Asio编写TCP通信程序框架(一)

    2024-07-10 04:14:01       42 阅读
  7. 导师好奇我为什么开发后端模版只花了一小时!

    2024-07-10 04:14:01       27 阅读
  8. android 7.0 tts文字转语音

    2024-07-10 04:14:01       24 阅读
  9. 离线升级docker中的某个镜像——以etcd为例

    2024-07-10 04:14:01       52 阅读
  10. 将pytorch 模型封装为c++ api 例子

    2024-07-10 04:14:01       34 阅读
  11. Rust: 关于Pin以及move前后分析

    2024-07-10 04:14:01       32 阅读