深度学习day3-自动微分

七 自动微分

torch.autograd模块:自动微分模块,自动计算张量操作的梯度,可以自动求导实现权重参数的更新

1 基础概念

张量:Torch中的一切都是张量,属性requires_grad决定是否对其进行梯度计算,True为进行梯度计算

计算图:torch.autograd通过创建一个动态计算图来跟踪张量的操作

反向传播:tenso.backward()执行反向传播,自动计算每个张量对损失函数的梯度

梯度:tensor.grad访问计算得到的梯度,最小化损失函数,优化模型

2 计算梯度

1.标量的梯度计算

import torch
def test01():
    #标量的梯度计算
    #创建标量,必须是浮点类型(涉及算术运算会有小数)
    x=torch.tensor(5,requires_grad=True,dtype=torch.float32)
    #损失函数
    y=x**2+2*x-5
    #反向传播,计算梯度
    y.backward()#计算梯度:1.y函数对x求导函数;2.把x当前的值带入上一步的函数中求导数值
    #读取梯度值
    print(x.grad)#打印出x的导数值(梯度值)
    #不能手动更新
    #x=x+5
  if __name__=='__main__':
    test01()
​

2.向量的梯度计算

import torch
def test02():
    #向量的梯度计算
    #创建向量
    x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
    #损失函数
    y=x**2+2*x-5
    print(y)
    y=y.sum()#得到一个标量
    #y=y.mean()
    y.backward()#梯度计算(y必须是一个标量,才能用这个标量对x求导)
    print(x.grad)
if __name__=='__main__':
    test02()

3.多标量的梯度计算

import torch
def test03():
    #多标量的梯度计算
    x1=torch.tensor(1.,requires_grad=True)
    x2=torch.tensor(2.,requires_grad=True)
    y=x1**2+3*x2-5
    y.backward()#梯度计算
    print(x1.grad)
    print(x2.grad)
​
if __name__=='__main__':
    test03()

4.多向量的梯度计算

import torch
def test04():
    #多向量的梯度计算
    x1=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float32)
    x2=torch.tensor([2,2,1],requires_grad=True,dtype=torch.float32)
    y=x1**2+3*x2-5
    y=y.sum()
    y.backward()
    print(x1.grad)
    print(x2.grad)
    #怎么算出tensor([2.,4.,6.]),tensor([3.,3.,3.])
   
if __name__=='__main__':
    test04()

5.矩阵梯度计算

import torch
def test05():
    #矩阵的梯度计算
    x1=torch.tensor([[1,2],[3,4]],requires_grad=True,dtype=torch.float32)
    y=x1**2+2
    y=y.sum()
    y.backward()
    print(x1.grad)
​
if __name__=='__main__':
    test05()

3 梯度上下文控制

管理计算图、内存消耗、计算效率

1.控制梯度计算

关闭梯度计算(有性能开销)

import torch
def test01():
    x=torch.tensor(5,requires_grad=True,dtype=torch.float64)
    y=x**2+2*x-5
    print(y)
    y.backward()
    print(x.grad)
    print(y.requires_grad)#默认是True
    #实际开发时y已经是最后一个数学表达式了,但是y的梯度计算功能是开启的状态
    # z=y**2+3
    # print(z)
    # z.backward()
    # print(y.grad)
    
#关闭y的计算梯度1-with
def test02():
    x=torch.tensor(5,requires_grad=True,dtype=torch.float64)
    with torch.no_grad():#在with里面是关掉y的梯度的
        y=x**2+2*x-5
        print(y.requires_grad)
 # 关闭y的计算梯度2-装饰器1(系统自带)
@torch.no_grad()#和with类似
def test03():
    x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
    y=x**2+2*x-5
    y=y.sum()
    print(y.requires_grad)
    
# 关闭y的计算梯度3-装饰器2(自己写)
#自己实现一个不要梯度计算的装饰器函数
def my_no_grad(func): 
    def wrapper(): #func=>最近调用my_no_gard的函数,即test04
        with torch.no_grad():
            res=func()
            return res
    return wrapper
    
@my_no_grad#和with类似,先把下面的test04函数传给my_no_grada()函数调用
def test04():
    x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
    y=x**2+2*x-5
    y=y.sum()
    print(y.requires_grad)
# 关闭y的计算梯度4-全局设置,需要谨慎,影响大
def test05():
    #全局关闭
    x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
    torch.set_grad_enabled(False)
    y=x**2+2*x-5
    y=y.sum()
    print(x.requires_grad)
    print(y.requires_grad)
    y.backward()
    print(x.grad)#x也不能求梯度
   
if __name__=='__main__':
    test05()

2.累计梯度

重复对一个自变量进行梯度计算时,梯度是累加的

import torch
def test06():
    #累计梯度
    x=torch.tensor(4,requires_grad=True,dtype=torch.float64)
    # y=x**2+2*x-5  
    # y.backward()
    # print(x.grad)
​
    # y=2*x**2+7
    # y.backward()
    # print(x.grad)
​
    # y=2*x**2+7
    # y.backward()
    # print(x.grad)
    #累计梯度:每次计算都会累计梯度
    for _ in range(4):
        y=2*x**2+7
        y.backward()
        print(x.grad)
       
 if __name__=='__main__':
    test05()
​

3.梯度清零

不需要梯度累加的时候,在反向传播之前可以先对梯度进行清零

import torch
def test07():
        #梯度清零
        x=torch.tensor(4,requires_grad=True,dtype=torch.float64)
        y=2*x**2+7
        #如果在未来不知道这个x还从来没有求过梯度那么可以判断是否有累计梯度值
        if x.grad is not None:
            x.grad.zero_()
        y.backward()
        print(x.grad)
​
        z=3*x**2+7*x
        #在反向传播之前对x的梯度清零
        x.grad.zero_()
        z.backward()
        print(x.grad)
​
def test08():
    x=torch.tensor(4,requires_grad=True,dtype=torch.float64)
    for _ in range(10):
         y=2*x**2+7   
    #清零操作
    if x.grad is not None:
        x.grad.zero_()
    y.backward()
    print(x.grad)
​
if __name__ == "__main__":
    test07()

4.梯度更新

import torch
import matplotlib.pyplot as plt
def test():
    w=torch.linspace(-200,100,1000)
    loss=3*w**2
    plt.grid()
    plt.plot(w,loss)
    plt.show()
​
def test01():
    #生成初始化w
    w=torch.tensor(5.,requires_grad=True)
    #定义训练的一些参数
    lr=0.01
    epoch=100
    for i in range(epoch):
        #生成损失函数
        loss=3*w**2+2*w-5
        #梯度清零
        #w.grad.zero_()
        if w.grad is not None:
            w.grad.zero_()
        #反向传播(求当前w的导数值:梯度值,斜率)
        loss.backward()
        #求得当前w的斜率
        print(w.grad)
        #更新梯度
        #w这个tensor是不能改的,否则的话未来w就变成了新的数据(可能是数字,也可能是新的张量)
        #修改w的data属性的值就可以了
       
        #w=w-0.1*w.grad
        w.data=w.data-lr*w.grad.data
        print(w)
    #访问训练100轮结束后的w的值
    print(w.item())
    
def test02():
    #生成初始化w
    w=torch.tensor([10.,2.,3.],requires_grad=True)
    #定义训练的一些参数
    lr=0.01
    epoch=100
    for i in range(epoch):
        #生成损失函数
        loss=3*w**2+2*w-5
        loss=loss.sum()
        #梯度清零
        #w.grad.zero_()
        if w.grad is not None:
            w.grad.zero_()
        #反向传播(求当前w的导数值:梯度值,斜率)
        loss.backward()
        #求得当前w的斜率
        print(w.grad)
        #更新梯度
        #w这个tensor是不能改的,否则的话未来w就变成了新的数据(可能是数字,也可能是新的张量)
        #修改w的data属性的值就可以了
        
        #w=w-0.1*w.grad
        w.data=w.data-lr*w.grad.data
        print(w)
    #访问训练100轮结束后的w的值
    print(w.data)
    #保存weights
    torch.save(w.data,'./data/weights.pth')
#调用
def detect():
    w=torch.load('./data/weights.pth',map_location="cuda")
    print(w)
​
if __name__ == "__main__":
    test01()

4叶子节点

当requires_grad=True时,调用numpy转换为ndarray时会报错,可以用detach()创建叶子节点,该张量和原张量共享数据,只是该张量不需要计算梯度

import torch
def test01():
    x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float32)
    print(x)
    #x2=x.numpy()#如果x是一个可以求导的张量,那么它就不能直接当做普通的tensor使用,比如调numpy函数
    #print(x2)
    x2=x.detach()
    print(x2)
    x3=x2.numpy()
    print(x3)
​
def test02():
    x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float32)
    print(x)
    x2=x.detach()
    print(x2)
    print(id(x),id(x2))#tensor本质是对象
    print(id(x.data),id(x2.data))
​
if __name__ == "__main__":
    test01()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

冲破AI 浪潮冲击下的 迷茫与焦虑

在这个科技日新月异的时代,人工智能如汹涌浪潮般席卷而来,不断改变我们的生活。你是否对 AI 充满好奇,却不知它将如何改变你的工作与生活?又是否会在 AI 浪潮的冲击下陷入迷茫与焦虑?《AI 时代:弯道超车新思…

【FRP 内网穿透 从0到1 那些注意事项】

【摘要】 最近跟第三方团队调试问题,遇到一个比较烦的操作。就是,你必须要发个版到公网环境,他们才能链接到你的接口地址,才能进行调试。按理说,也没啥,就是费点时间。但是,在调试的时候&#…

基于SpringBoot+RabbitMQ完成应⽤通信

前言: 经过上面俩章学习,我们已经知道Rabbit的使用方式RabbitMQ 七种工作模式介绍_rabbitmq 工作模式-CSDN博客 RabbitMQ的工作队列在Spring Boot中实现(详解常⽤的⼯作模式)-CSDN博客作为⼀个消息队列,RabbitMQ也可以⽤作应⽤程…

进度条程序

目录 1.回车与换行 2.缓冲区 强制刷新:fflush 策略 3.倒计时程序 4.进度条 4.1先做一下基本的准备工作 4.2现在我们正式来实现 进度: 比率: 旋转光标 表明动态变化: 4.3如果我们要完成一个下载任务 4.3.1实现: 4.3.2光标显示: 4.3.2.1证明一下&#…

软件测试——自动化测试常见函数

在上一篇文章软件测试——自动化测试概念篇-CSDN博客中,给大家演示了一下自动化程序,而本篇文章会带大家详细学习selenium库。 selenium库是python官方的库,里面包含了很多操控浏览器的函数。 本节重点 元素定位操作测试对象窗口等待导航弹…

STM32F103C8T6实时时钟RTC

目录 前言 一、RTC基本硬件结构 二、Unix时间戳 2.1 unix时间戳定义 2.2 时间戳与日历日期时间的转换 2.3 指针函数使用注意事项 ​三、RTC和BKP硬件结构 四、驱动代码解析 前言 STM32F103C8T6外部低速时钟LSE(一般为32.768KHz)用的引脚是PC14和PC…

AI社媒引流工具:解锁智能化营销的新未来

在数字化浪潮的推动下,社交媒体成为品牌营销的主战场。然而,面对海量的用户数据和日益复杂的运营需求,传统营销方法显得力不从心。AI社媒引流王应运而生,帮助企业在多平台中精准触达目标用户,提升营销效率和效果。 1.…

知识中台:提升企业知识管理的智能化水平

在数字化转型的浪潮中,企业知识管理的智能化水平成为提升竞争力的关键。HelpLook知识中台通过集成先进的AI技术,为企业提供了一个智能化的知识管理平台。 一、知识管理智能化的重要性 智能化的知识管理不仅能够提高信息检索的效率,还能通过…

Unreal5从入门到精通之EnhancedInput增强输入系统详解

前言 从Unreal5开始,老版的输入系统,正式替换为EnhancedInput增强型输入系统,他们之间有什么区别呢? 如果有使用过Unity的同学,大概也知道,Unity也在2020版本之后逐渐把输入系统也升级成了新版输入系统,为什么Unreal和Unity都热衷于升级输入系统呢?这之间又有什么联系…

C语言数据结构与算法--简单实现队列的入队和出队

(一)队列的基本概念 和栈相反,队列(Queue)是一种先进先出(First In First Out)的线性表。只 允许在表的一端进行插入,而在另一端删除元素,如日常生活中的排队现象。队列中 允许插入的一端叫队尾…

docker搭建私有仓库,实现镜像的推送和拉取

1.拉取docker仓库镜像 docker pull registry 2.启动registry容器 docker run -d registry 3.查看当前仓库中存在的镜像(一) curl -XGET http://192.168.111.162: 5000/v2/_catalog 192.168.111.162 部署docker仓库宿主机的ip 5000 部署docker仓库映射到宿…

算法学习笔记(九):网格图DFS、图论算法DFS、动态规划DP、贪心

一.网格图DFS 适用于需要计算连通块个数、大小的题目 1.岛屿数量 给你一个由 1(陆地) 和 0(水)组成的二维网格,请你计算网格中岛屿的数量 岛屿总是被水包围,并且每座岛屿只能由水平方向和\或竖直方向上相邻的陆地连接形成 此外&…

Cmakelist.txt之Linux-redis配置

1.cmakelist.txt cmake_minimum_required(VERSION 3.16) ​ project(redis_linux_test LANGUAGES C) ​ ​ ​ add_executable(redis_linux_test main.c) ​ # 设置hiredis库的头文件路径和库文件路径 set(Hiredis_INCLUDE_DIR /usr/local/include/hiredis) set(Hiredis_LIBRA…

【Node.js】Node.js 和浏览器之间的差异

Node.js 是一个强大的运行时环境,它在现代 JavaScript 开发中扮演着重要角色。然而,许多开发者在使用 Node.js 时常常会感到困惑,尤其是与浏览器环境的对比。本文将深入探讨 Node.js 和浏览器之间的差异,帮助你全面理解两者的设计…

【物联网原理与应用】实验二:红外传感实验

目录 一、实验目的 二、实验原理 三、实验内容及步骤 四、实验结果 五、核心代码 一、实验目的 学习试验模块上线路的连接操作理解掌握红外传感器的工作原理实现对红外传感器数据的接收和处理 二、实验原理 1、将红外辐射能转换成电能的光敏元件称为红外传感器&#…

PAL(Program-Aided Language Model)

PAL(Program-Aided Language Model)是一种结合生成式语言模型(如 GPT)和程序执行能力的技术框架。它的核心思想是通过让语言模型生成代码或程序来解决复杂任务,程序执行的结果反过来增强语言模型的输出准确性和逻辑性。…

java基础概念36:正则表达式1

一、正则表达式的作用 作用一:校验字符串是否满足规则;作用二:在一段文本中查找满足要求的内容。——爬虫 二、正则表达式 2-1、字符类 示例: public static void main(String[] args) {System.out.println("a".matc…

VsCode 插件推荐(个人常用)

VsCode 插件推荐(个人常用)

工业储能柜的大小该如何选择,工商储能系统设备哪家好?

在能源转型和可持续发展的大潮中,工商业储能系统因其提升清洁能源利用率、降低电能损耗、实现“双碳”目标等优势而备受青睐。它们不仅增强了电力系统的可靠性和灵活性,还帮助企业降低成本、提高经济效益。储能系统通过负荷管理适应电价波动,…

人工智能之数学基础:线性代数在人工智能中的地位

本文重点 从本文开始,我们将开启线性代数的学习,在线性代数中有向量、矩阵,以及各种性质,那么这些数学知识究竟和人工智能有什么关系呢? 重要性 机器学习和深度学习的本质就是训练模型,要想训练模型需要使…