【PyTorch】7.自动微分模块:开启神经网络 “进化之门” 的魔法钥匙

目录

1. 梯度基本计算

2. 控制梯度计算

3. 梯度计算注意

4. 小节


个人主页:Icomi

专栏地址:PyTorch入门

在深度学习蓬勃发展的当下,PyTorch 是不可或缺的工具。它作为强大的深度学习框架,为构建和训练神经网络提供了高效且灵活的平台。神经网络作为人工智能的核心技术,能够处理复杂的数据模式。通过 PyTorch,我们可以轻松搭建各类神经网络模型,实现从基础到高级的人工智能应用。接下来,就让我们一同走进 PyTorch 的世界,探索神经网络与人工智能的奥秘。本系列为PyTorch入门文章,若各位大佬想持续跟进,欢迎与我交流互关。

咱们已经见识了 PyTorch 为张量封装的众多实用计算函数,这些函数就像我们在数据处理旅程中的得力助手,帮我们解决了不少计算难题。但深度学习的探索之旅永无止境,接下来,我们要踏入一个更为关键且神奇的领域 —— 自动微分(Autograd)模块。

想象一下,我们构建的神经网络就像一台超级复杂的智能机器,它能从海量的数据中学习规律,做出精准的预测。而在这台 “智能机器” 的运行过程中,参数的调整就如同精细地调校机器的各个零部件,让它能不断优化性能。这时,自动微分(Autograd)模块就如同一位无比精准的 “调校大师”,对张量做了进一步的封装,赋予了它们一项极为强大的能力 —— 自动求导。

自动微分模块可不是一个普通的工具,它可是构成神经网络训练的必要模块,就如同发动机对于汽车的重要性一样。在神经网络的训练过程中,我们可以把它看作是一个幕后英雄,默默地推动着整个网络的优化进程。

具体来说,在神经网络的反向传播过程中,这个 “调校大师” Autograd 模块会基于正向计算的结果对当前的参数进行微分计算。这就好比在我们驾驶一辆汽车时,根据当前行驶的路线和目的地,通过精确计算来调整方向盘的角度和油门的力度。Autograd 模块通过这种微分计算,精确地算出每个参数对最终结果的影响程度,从而实现网络权重参数的更新,让神经网络能够不断学习和进步,变得越来越 “聪明”。

        接下来我们要深入学习这个自动微分(Autograd)模块,掌握它的原理和使用方法,这将为我们理解神经网络的训练机制打开一扇关键的大门。

1. 梯度基本计算

我们使用 backward 方法、grad 属性来实现梯度的计算和访问.

import torch# 1. 单标量梯度的计算
# y = x**2 + 20
def test01():# 定义需要求导的张量# 张量的值类型必须是浮点类型x = torch.tensor(10, requires_grad=True, dtype=torch.float64)# 变量经过中间运算f = x ** 2 + 20# 自动微分f.backward()# 打印 x 变量的梯度# backward 函数计算的梯度值会存储在张量的 grad 变量中print(x.grad)# 2. 单向量梯度的计算
# y = x**2 + 20
def test02():# 定义需要求导张量x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)# 变量经过中间计算f1 = x ** 2 + 20# 注意:# 由于求导的结果必须是标量# 而 f 的结果是: tensor([120., 420.])# 所以, 不能直接自动微分# 需要将结果计算为标量才能进行计算f2 = f1.mean()  # f2 = 1/2 * x# 自动微分f2.backward()# 打印 x 变量的梯度print(x.grad)# 3. 多标量梯度计算
# y = x1 ** 2 + x2 ** 2 + x1*x2
def test03():# 定义需要计算梯度的张量x1 = torch.tensor(10, requires_grad=True, dtype=torch.float64)x2 = torch.tensor(20, requires_grad=True, dtype=torch.float64)# 经过中间的计算y = x1**2 + x2**2 + x1*x2# 将输出结果变为标量y = y.sum()# 自动微分y.backward()# 打印两个变量的梯度print(x1.grad, x2.grad)# 4. 多向量梯度计算
def test04():# 定义需要计算梯度的张量x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)x2 = torch.tensor([30, 40], requires_grad=True, dtype=torch.float64)# 经过中间的计算y = x1 ** 2 + x2 ** 2 + x1 * x2print(y)# 将输出结果变为标量y = y.sum()# 自动微分y.backward()# 打印两个变量的梯度print(x1.grad, x2.grad)if __name__ == '__main__':test04()

2. 控制梯度计算

我们可以通过一些方法使得在 requires_grad=True 的张量在某些时候计算不进行梯度计算。

import torch# 1. 控制不计算梯度
def test01():x = torch.tensor(10, requires_grad=True, dtype=torch.float64)print(x.requires_grad)# 第一种方式: 对代码进行装饰with torch.no_grad():y = x ** 2print(y.requires_grad)# 第二种方式: 对函数进行装饰@torch.no_grad()def my_func(x):return x ** 2print(my_func(x).requires_grad)# 第三种方式torch.set_grad_enabled(False)y = x ** 2print(y.requires_grad)# 2. 注意: 累计梯度
def test02():# 定义需要求导张量x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)for _ in range(3):f1 = x ** 2 + 20f2 = f1.mean()# 默认张量的 grad 属性会累计历史梯度值# 所以, 需要我们每次手动清理上次的梯度# 注意: 一开始梯度不存在, 需要做判断if x.grad is not None:x.grad.data.zero_()f2.backward()print(x.grad)# 3. 梯度下降优化最优解
def test03():# y = x**2x = torch.tensor(10, requires_grad=True, dtype=torch.float64)for _ in range(5000):# 正向计算f = x ** 2# 梯度清零if x.grad is not None:x.grad.data.zero_()# 反向传播计算梯度f.backward()# 更新参数x.data = x.data - 0.001 * x.gradprint('%.10f' % x.data)if __name__ == '__main__':test01()test02()test03()

3. 梯度计算注意

当对设置 requires_grad=True 的张量使用 numpy 函数进行转换时, 会出现如下报错:

Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.

此时, 需要先使用 detach 函数将张量进行分离, 再使用 numpy 函数.

注意: detach 之后会产生一个新的张量, 新的张量作为叶子结点,并且该张量和原来的张量共享数据, 但是分离后的张量不需要计算梯度。

import torch# 1. detach 函数用法
def test01():x = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.# print(x.numpy())  # 错误print(x.detach().numpy())  # 正确# 2. detach 前后张量共享内存
def test02():x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# x2 作为叶子结点x2 = x1.detach()# 两个张量的值一样: 140421811165776 140421811165776print(id(x1.data), id(x2.data))x2.data = torch.tensor([100, 200])print(x1)print(x2)# x2 不会自动计算梯度: Falseprint(x2.requires_grad)if __name__ == '__main__':test01()test02()

4. 小节

本小节主要讲解了 PyTorch 中非常重要的自动微分模块的使用和理解。我们对需要计算梯度的张量需要设置 requires_grad=True 属性,并且需要注意的是梯度是累计的,在每次计算梯度前需要先进行梯度清零。

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

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

相关文章

C++基础day1

前言:谢谢阿秀,指路阿秀的学习笔记 一、基础语法 1.构造和析构: 类的构造函数是一种特殊的函数,在创建一个新的对象时调用。类的析构函数也是一种特殊的函数,在删除所创建的对象时调用。 构造顺序:父类->子类 析…

深入理解linux中的文件(上)

1.前置知识: (1)文章 内容 属性 (2)访问文件之前,都必须打开它(打开文件,等价于把文件加载到内存中) 如果不打开文件,文件就在磁盘中 (3&am…

Spring Boot Web项目全解析:从前端请求到后端处理

第一章:对静态资源的整合 ConfigurationProperties(prefix"spring.resources", ignoreUnknownFieldsfalse)public class ResourceProperties implements ResourceLoaderAware {//可以设置和静态资源有关的参数,缓存时间等WebMvcAuotConfigura…

Java创建对象有几种方式?

大家好,我是锋哥。今天分享关于【Java创建对象有几种方式?】面试题。希望对大家有帮助; Java创建对象有几种方式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Java 中,创建对象有几种常见的方式,具体如下&…

基于Spring Security 6的OAuth2 系列之八 - 授权服务器--Spring Authrization Server的基本原理

之所以想写这一系列,是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级…

深入浅出并查集(不相交集合实现思路)

引言 并查集(Disjoint Set Union,简称DSU)是一种用于处理一些不交集的合并及查询问题。它主要支持两种操作:查找(Find)和合并(Union)。 查找:确定某个元素属于哪一个子…

如何运行Composer安装PHP包 安装JWT库

1. 使用Composer Composer是PHP的依赖管理工具,它允许你轻松地安装和管理PHP包。对于JWT,你可以使用firebase/php-jwt这个库,这是由Firebase提供的官方库。 安装Composer(如果你还没有安装的话): 访问Co…

享元模式——C++实现

目录 1. 享元模式简介 2. 代码示例 1. 享元模式简介 享元模式是一种结构型模式。 享元模式用于缓存共享对象,降低内存消耗。共享对象相同的部分,避免创建大量相同的对象,减少内存占用。 享元模式需要将对象分成内部状态和外部状态两个部分…

网络原理(4)—— 网络层详解

目录 一. IP协议报头结构 二. 地址管理 2.1 路由器 2.1.1 路由选择 2.1.2 WAN口(Wide Area Network) 2.1.3 LAN口(Local Area Network) 2.1.4 WLAN口(Wireless Local Area Network) 2.2 网段划分…

基于深度学习的输电线路缺陷检测算法研究(论文+源码)

输电线路关键部件的缺陷检测对于电网安全运行至关重要,传统方法存在效率低、准确性不高等问题。本研究探讨了利用深度学习技术进行输电线路关键组件的缺陷检测,目的是提升检测的效率与准确度。选用了YOLOv8模型作为基础,并通过加入CA注意力机…

Android --- handler详解

handler 理解 handler 是一套Android 消息传递机制,主要用于线程间通信。 tips: binder/socket 用于进程间通信。 参考: Android 进程间通信-CSDN博客 handler 就是主线程在起了一个子线程,子线程运行并生成message ,l…

vim如何解决‘’文件非法关闭后,遗留交换文件‘’的问题

过程描述: 由于我修改文件时(一定得修改了文件,不做任何修改不会产生这个问题)的非法关闭,比如直接关闭虚拟机,或者直接断开远程工具的远程连接,产生了以下遗留交换文件的问题: 点击…

六十分之三十七——一转眼、时光飞逝

一、目标 明确可落地,对于自身执行完成需要一定的努力才可以完成的 1.第三版分组、激励、立体化权限、智能设备、AIPPT做课 2.8本书 3.得到:头条、吴军来信2、卓克科技参考3 4.总结思考 二、计划 科学规律的,要结合番茄工作法、快速阅读、…

Linux环境下的Java项目部署技巧:安装 Mysql

查看 myslq 是否安装: rpm -qa|grep mysql 如果已经安装,可执行命令来删除软件包: rpm -e --nodeps 包名 下载 repo 源: http://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm 执行命令安装 rpm 源(根据下载的…

css三角图标

案例三角&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

Shadow DOM举例

这东西具有隔离效果&#xff0c;对于一些插件需要append一些div倒是不错的选择 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"utf-8"> <title>演示例子</title> </head> <body> <style&g…

万字长文深入浅出负载均衡器

前言 本篇博客主要分享Load Balancing&#xff08;负载均衡&#xff09;&#xff0c;将从以下方面循序渐进地全面展开阐述&#xff1a; 介绍什么是负载均衡介绍常见的负载均衡算法 负载均衡简介 初识负载均衡 负载均衡是系统设计中的一个关键组成部分&#xff0c;它有助于…

ChatGPT-4o和ChatGPT-4o mini的差异点

在人工智能领域&#xff0c;OpenAI再次引领创新潮流&#xff0c;近日正式发布了其最新模型——ChatGPT-4o及其经济实惠的小型版本ChatGPT-4o Mini。这两款模型虽同属于ChatGPT系列&#xff0c;但在性能、应用场景及成本上展现出显著的差异。本文将通过图文并茂的方式&#xff0…

双指针算法思想——OJ例题扩展算法解析思路

大家好&#xff01;上一期我发布了关于双指针的OJ平台上的典型例题思路解析&#xff0c;基于上一期的内容&#xff0c;我们这一期从其中内容扩展出来相似例题进行剖析和运用&#xff0c;一起来试一下吧&#xff01; 目录 一、 基于移动零的举一反三 题一&#xff1a;27. 移除…

WSL2中安装的ubuntu开启与关闭探讨

1. PC开机后&#xff0c;查询wsl状态 在cmd或者powersell中输入 wsl -l -vNAME STATE VERSION * Ubuntu Stopped 22. 从windows访问WSL2 wsl -l -vNAME STATE VERSION * Ubuntu Stopped 23. 在ubuntu中打开一个工作区后…