昇思MindSpore学习笔记7--函数式自动微分

摘要:

介绍了昇思MindSpore神经网络训练反向传播算法中函数式自动微分的使用方法和步骤。包括构造计算函数和神经网络、grad获得微分函数,以及如何处理停止渐变、获取辅助数据等内容。

一、概念要点

神经网络训练主要使用反向传播算法

        准备模型预测值logits与正确标签label

        损失函数loss function计算loss

        反向传播计算梯度gradients

        更新模型参数parameters

自动微分

        计算可导函数在某点处的导数值

        将复杂的数学运算分解为一系列简单的基本运算

MindSpore函数式自动微分接口

        grad

        value_and_grad

二、环境准备

安装minspore模块

!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.3.0rc1

导入numpy、minspore、nn、ops等相关模块

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

三、函数与计算图

计算图是用图论语言来表示数学函数。

深度学习框架用来表达神经网络模型。

以下图为例构造计算函数和神经网络。

在这个模型中,x为输入,z为预测值,y为目标值,w和b是需要优化的参数。

根据计算图表达的计算过程,构造计算函数。

binary_cross_entropy_with_logits

        损失函数,计算预测值z和目标值y之间的二值交叉熵损失。

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') # biasdef function(x, y, w, b):z = ops.matmul(x, w) + bloss = ops.binary_cross_entropy_with_logits(z, y, ops.ones_like(z), ops.ones_like(z))
return lossloss = function(x, y, w, b)
print(loss)

输出:

1.5375124

四、微分函数与梯度计算

优化模型参数需要对参数w、b求loss的导数:

调用mindspore.grad函数获得function的微分函数。

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

grad_fn = mindspore.grad(function, (2, 3))

mindspore.grad函数的两个入参:

fn: 求导函数。

grad_position:求导参数的索引位置。

参数 w和b在function入参对应的位置为(2, 3)。

执行微分函数获得w、b对应的梯度。

grads = grad_fn(x, y, w, b)
print(grads)

输出:

(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]]), 
Tensor(shape=[3], dtype=Float32, value=[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]))

五、Stop Gradient停止渐变

消除某个Tensor对梯度的影响或实现对某个输出项的梯度截断

通常情况下,求导函数的输出只有loss一项。

微分函数会对参数求所有输出项的导数。

function_with_logits修改原function支持同时输出loss和z

获得自动微分函数并执行。

def function_with_logits(x, y, w, b):z = ops.matmul(x, w) + bloss = ops.binary_cross_entropy_with_logits(z, y, ops.ones_like(z), ops.ones_like(z))return loss, z
grad_fn = mindspore.grad(function_with_logits, (2, 3))
grads = grad_fn(x, y, w, b)
print(grads)

输出:

(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 1.27216899e+00,  1.20658815e+00,  1.28590846e+00],[ 1.27216899e+00,  1.20658815e+00,  1.28590846e+00],[ 1.27216899e+00,  1.20658815e+00,  1.28590846e+00],[ 1.27216899e+00,  1.20658815e+00,  1.28590846e+00],[ 1.27216899e+00,  1.20658815e+00,  1.28590846e+00]]),Tensor(shape=[3], dtype=Float32, value=[ 1.27216899e+00,  1.20658815e+00,  1.28590846e+00]))

wb对应的梯度值变了。

使用ops.stop_gradient接口屏蔽z对梯度的影响

def function_stop_gradient(x, y, w, b):z = ops.matmul(x, w) + bloss = 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)

输出:

(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]]),Tensor(shape=[3], dtype=Float32, value=[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]))

此时wb对应的梯度值与初始function求得的梯度值一致。

六、Auxiliary data辅助数据

函数除第一个输出项外的其他输出。

通常会将loss设置为函数的第一个输出,其他的输出即为辅助数据。

grad和value_and_gradhas_aux参数

设置True,自动实现stop_gradient,返回辅助数据同时不影响梯度计算的效果。

下面仍使用function_with_logits,配置has_aux=True,并执行。

grad_fn = mindspore.grad(function_with_logits, (2, 3), has_aux=True)
grads, (z,) = grad_fn(x, y, w, b)
print(grads, z)

输出:

(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]]),Tensor(shape=[3], dtype=Float32, value=[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]))[1.4928596  0.48854822 1.7965223 ]

此时wb 对应的梯度值与初始function求得的梯度值一致

同时z能够作为微分函数的输出返回。

七、神经网络梯度计算

下面通过继承nn.Cell构造单层线性变换神经网络

利用函数式自动微分来实现反向传播。

使用mindspore.Parameter封装w、b模型参数作为内部属性

在construct内实现相同的Tensor操作。

# Define model
class Network(nn.Cell):def __init__(self):super().__init__()self.w = wself.b = b
​def construct(self, x):z = ops.matmul(x, self.w) + self.breturn z# Instantiate model
model = Network()
# Instantiate loss function
loss_fn = nn.BCEWithLogitsLoss()

使用函数式自动微分需要将神经网络和损失函数的调用封装为一个前向计算函数。

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

使用value_and_grad接口获得微分函数,用于计算梯度。

Cell封装神经网络模型,模型参数为Cell的内部属性,不需要使用grad_position指定对函数输入求导,因此将其配置为None。

使用model.trainable_params()方法从weights参数取出可以求导的参数。

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=
[[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01],[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]]),Tensor(shape=[3], dtype=Float32, value=[ 2.72169024e-01,  2.06588134e-01,  2.85908401e-01]))

执行微分函数,可以看到梯度值和前文function求得的梯度值一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/38029.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从AICore到TensorCore:华为910B与NVIDIA A100全面分析

华为NPU 910B与NVIDIA GPU A100性能对比,从AICore到TensorCore,展现各自计算核心优势。 AI 2.0浪潮汹涌而来,若仍将其与区块链等量齐观,视作炒作泡沫,则将错失新时代的巨大机遇。现在,就是把握AI时代的关键…

RAG 基本流程及处理技巧 with LangChain

LLM 主要存在两个问题:幻想和缺乏领域知识。领域知识缺乏的原因是因为训练 LLM 本身的知识更新慢,对特定领域的知识也没有太细致的输入。 RAG 主要是解决 LLM 缺乏领域知识的问题。底层的逻辑是:把 LLM 作为逻辑推理引擎,而不是信…

机器学习--概念理解

知识点 一、机器学习概述 人工智能 机器学习 深度学习 学习的范围:模式识别、数据挖掘、统计学习、计算机视觉、语音识别、自然语言处理 可以解决的问题:给定数据的预测问题 二、机器学习的类型 监督学习 分类 回归 无监督学习 聚类 降维 强化…

恢复的实现技术-日志和数据转储

一、引言 在系统正常运行的情况下,事务处理的恢复机制应采取某些技术措施为恢复做好相应的准备,保证在系统发生故障后,能将数据库从一个不一致的错误状态恢复到一个一致性状态 恢复技术主要包括 生成一个数据库日志,来记录系统中…

Unity制作一个简单抽卡系统(简单好抄)

业务流程:点击抽卡——>播放动画——>显示抽卡面板——>将随机结果添加到面板中——>关闭面板 1.准备素材并导入Unity中(包含2个抽卡动画,抽卡结果的图片,一个背景图片,一个你的展示图片) 2.给…

创建一个vue3+vite+ts项目

目录 创建项目 ​编辑 下载jsx 插件 在根目录在新建.env vue.config.js tsconfig.json tsconfig.node.json 下载ui组件库和路由(组件库根据自己的项目需要选择) 在根目录下新建views/index.tsx 在根目录下新建router/index.ts 修改App.vue 创建…

机器学习原理之 -- 朴素贝叶斯分类器:由来及原理详解

朴素贝叶斯(Naive Bayes)分类器是一类基于贝叶斯定理(Bayes Theorem)的简单而有效的概率分类算法。由于其假设特征之间的条件独立性,因此被称为“朴素”贝叶斯分类器。尽管这种独立性假设在现实中很少完全成立&#xf…

mac系统docker默认不支持host主机网络模式

环境描述:在mac系统上安装docker及docker-compose服务,并且打算搭建一个redis集群 问题描述:mac默认不支持host网络模式,导致集群无法通过外部主机访问 具体验证步骤: docker-compose.yml如下: version…

reactor网络模型的原理与实现

一、rector网络模型 对高并发编程,网络连接上的消息处理,可以分为两个阶段:等待消息准备好、消息处理。当使用默认的阻塞套接字时,往往是把这两个阶段合而为一,这样操作套接字的代码所在的线程就得睡眠来等待消息准备好…

Mysql常用SQL:日期转换成周_DAYOFWEEK(date)

有时候需要将查询出来的日期转换成周几,Mysql本身语法就是支持这种转换的,就是DAYOFWEEK()函数 语法格式:DAYOFWEEK(date) (date:可以是指定的具体日期( 如2024-06-29 ),也可以是日期…

为什么word生成的PDF内容显示不全?

在现代办公环境中,将文档从一个格式转换为另一个格式是一个常见的任务。然而,有时候我们可能会遇到意想不到的问题,比如使用Word转换成PDF时,生成的PDF文件只显示了整个界面的四分之一内容。这种问题不仅令人困扰,也可…

斜率优化DP——AcWing 303. 运输小猫

斜率优化DP 定义 斜率优化DP(Slope Optimization Dynamic Programming)是一种高级动态规划技巧,用于优化具有特定形式的状态转移方程。它主要应用于那些状态转移涉及求极值(如最小值或最大值)的问题中,通…

CesiumJS【Basic】- #028 天空盒

文章目录 天空盒1 目标2 代码2.1 main.ts3 资源天空盒 1 目标 配置显示天空盒 2 代码 2.1 main.ts import * as Cesium from cesium;// 创建 Cesium Viewer 并配置地形数据和天空盒 const viewer = new Cesium.Viewer(

理解抽象工厂设计模式

目录 抽象工厂模式抽象工厂模式结构抽象工厂模式适合应用场景抽象工厂模式优缺点练手题目题目描述输入描述输出描述提示信息题解 抽象工厂模式 抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。 抽象工厂模式结构 抽…

自定义一个MyBaits脱敏插件

自定义一个MyBaits脱敏插件 用于对查询结果中的敏感数据进行脱敏处理。这个插件将拦截ResultSetHandler对象的处理结果,对某些敏感字段进行脱敏。 插件实现步骤 创建脱敏插件类。注册插件。 1. 创建脱敏插件类 首先,我们创建一个自定义插件类 DataM…

深入理解策略梯度算法

策略梯度(Policy Gradient)算法是强化学习中的一种重要方法,通过优化策略以获得最大回报。本文将详细介绍策略梯度算法的基本原理,推导其数学公式,并提供具体的例子来指导其实现。 策略梯度算法的基本概念 在强化学习…

【Python3的内置函数和使用方法】

目录 Python 特点 Python 中文编码 Python 变量类型 Python列表 Python 元组 元组是另一个数据类型,类似于 List(列表) Python 字典 Python数据类型转换 Python 运算符 Python算术运算符 Python比较运算符 Python赋值运算符 Pyt…

一篇就够了,为你答疑解惑:锂电池一阶模型-离线参数辨识(附代码)

锂电池一阶模型-参数离线辨识 背景模型简介数据收集1. 最大可用容量实验2. 开路电压实验3. 混合动力脉冲特性实验离线辨识对应模型对应代码总结下期预告文章字数有点多,耐心不够的谨慎点击阅读。 下期继续讲解在线参数辨识方法。 背景 最近又在开始重新梳理锂电池建模仿真与S…

使用stat()函数的例子

代码&#xff1a; #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h>int main(void) {struct stat st;if(-1stat("test.txt",&st)){printf("获得文件状态失败\n");return -1;}printf(&q…

Unidbg调用-补环境V2

1.B站 内部依赖自定义的SignedQuery对象,需要找到apk中的类并补充环境。 package com.nb.demo;import com.github.unidbg.AndroidEmulator