pytorch基础语法问题

news2024/11/24 13:00:17

这里写目录标题

  • pytorch基础语法问题
    • shape
    • torch.ones_like函数和torch.zeros_like函数
    • y.backward(torch.ones_like(x), retain_graph=True)
      • torch.autograd.backward
        • 参数grad_tensors: z.backward(torch.ones_like(x))
        • 来个复杂例子z.backward(torch.Tensor([[1., 0]])
        • 更复杂例子
        • 实际上,也可以通过 求均值 的形式将其转为标量
        • retain_graph=True参数

pytorch基础语法问题

shape

import torch
# 创建一个形状为(2, 3)的张量
x = torch.Tensor([[1, 2, 3], [4, 5, 6],[1,1,1],[2,2,2]])
print(len(x.shape))
print(x.shape[0])
# 遍历张量中的元素
for i in range(x.shape[0]):
    for j in range(x.shape[1]):
        print(x[i, j])

len(x.shape),维数,一般为二维
x.shape[0]:行数
x.shape[1]: 列数

2
4
tensor(1.)
tensor(2.)
tensor(3.)
tensor(4.)
tensor(5.)
tensor(6.)
tensor(1.)
tensor(1.)
tensor(1.)
tensor(2.)
tensor(2.)
tensor(2.)

进程已结束,退出代码0

torch.ones_like函数和torch.zeros_like函数

返回一个形状与input相同且值全为1的张量。torch.ones_like(input)相当于torch.ones(input.size, dtype=input.dtype,layout=input.layout,device=input.device)

input = torch.rand(4, 6)
print(input)
# 生成与input形状相同、元素全为1的张量
a = torch.ones_like(input)
print(a)
# 生成与input形状相同、元素全为0的张量
b = torch.zeros_like(input)
print(b)

在这里插入图片描述

z.backward(torch.ones_like(z))

z.backward(torch.ones_like(z))中的torch.ones_like(z)相当于在对z进
行求导时,对z中的元素进行了求和操作,从而将其转为一个标量。

y.backward(torch.ones_like(x), retain_graph=True)

y.backward(torch.ones_like(x), retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of relu', figsize=(5, 2.5))

torch.autograd.backward

x = torch.tensor(1.0, requires_grad=True)
y = torch.tensor(2.0, requires_grad=True)
z = x**2+y
z.backward()
print(z, x.grad, y.grad)

>>> tensor(3., grad_fn=<AddBackward0>) tensor(2.) tensor(1.)

可以z是一个标量,当调用它的backward方法后会根据链式法则自动计算出叶子节点的梯度值。

但是 如果遇到z是一个向量或者是一个矩阵的情况,这个时候又该怎么计算梯度呢? 这种情况我们需要定义grad_tensor来计算矩阵的梯度。在介绍为什么使用之前我们先看一下源代码中backward的接口是如何定义的:

torch.autograd.backward(
		tensors, 
		grad_tensors=None, 
		retain_graph=None, 
		create_graph=False, 
		grad_variables=None)
  • tensor: 用于计算梯度的tensor。也就是说这两种方式是等价的:- torch.autograd.backward(z) == z.backward()
  • grad_tensors: 在计算矩阵的梯度时会用到。他其实也是一个tensor,shape一般需要和前面的tensor保持一致。
  • retain_graph: 通常在调用一次backward后,pytorch会自动把计算图销毁,所以要想对某个变量重复调用backward,则需要将该参数设置为True
  • create_graph: 当设置为True的时候可以用来计算更高阶的梯度
  • grad_variables: 这个官方说法是grad_variables’ is deprecated. Use - ‘grad_tensors’ instead.也就是说这个参数后面版本中应该会丢弃,直接使用grad_tensors就好了。

好了,参数大致作用都介绍了,下面我们看看pytorch为什么设计了grad_tensors这么一个参数,以及它有什么用呢?

参数grad_tensors: z.backward(torch.ones_like(x))

原则上,Pytorch不支持对张量的求导,即如果z是张量的话,需要先将其转为标量。

浏览了很多博客,给出的解决方案都是说在求导时,加一个torch.ones_like(z)的参数。

torch.ones_like(z)的作用。简而言之,torch.ones_like(z)相当于在对z进行求导时,对z中的元素进行求和操作,从而将其转为一个标量,便于后续的求导。

x = torch.ones(2,requires_grad=True)
z = x + 2
z.backward()

>>> ...
RuntimeError: grad can be implicitly created only for scalar outputs

在这里插入图片描述

本质要得到 z对x求导, 但是已知的是X,Z ;一个矩阵对另一个矩阵求导,才能得到 每个z_partial 对x_partial的导数
其实,可以让sum(z_partial) 对于X求导,对xi 求偏导,就可以得到对应的z_partial
对x_partial的导数,,因为sum(z_partial) 对xi 求偏导,只有包含xi 的那一项在求导,其余与xi 无关的项
对xi求导为0

我们再仔细想想,对z求和不就是等价于z点乘一个一样维度的全为1的矩阵吗?即 [公式]
,而这个I也就是我们需要传入的grad_tensors参数。(点乘只是相对于一维向量而言的,对于矩阵或更高为的张量,可以看做是对每一个维度做点乘)

import torch

x = torch.ones(2,3,requires_grad=True)
z = 2*x + 2
print(z)
print(z.sum())
# print(z.*torch.ones_like(x))
z.sum().backward()#或者z.backward(torch.ones_like(x)) 效果一样!
print(x.grad)

'''
tensor([[4., 4., 4.],
        [4., 4., 4.]], grad_fn=<AddBackward0>)
tensor(24., grad_fn=<SumBackward0>)
tensor([[2., 2., 2.],
        [2., 2., 2.]])
'''


来个复杂例子z.backward(torch.Tensor([[1., 0]])
x = torch.tensor([2., 1.], requires_grad=True).view(1, 2)
y = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True)

z = torch.mm(x, y)
print(f"z:{z}")
z.backward(torch.Tensor([[1., 0]]), retain_graph=True)
print(f"x.grad: {x.grad}")
print(f"y.grad: {y.grad}")

>>> z:tensor([[5., 8.]], grad_fn=<MmBackward>)
x.grad: tensor([[1., 3.]])
y.grad: tensor([[2., 0.],
        [1., 0.]])

在这里插入图片描述
说了这么多,grad_tensors的作用其实可以简单地理解成在求梯度时的权重,因为可能不同值的梯度对结果影响程度不同,所以pytorch弄了个这种接口,而没有固定为全是1。引用自知乎上的一个评论:如果从最后一个节点(总loss)来backward,这种实现(torch.sum(y*w))的意义就具体化为 multiple loss term with difference weights 这种需求了吧
内容来源

看到这里我不由得想,会不会有更复杂的例子呢,万一 输入参数太多多维,导致得到的z不只是一个一维向量,是多维的矩阵,那么就是sum起来或者是点乘一个和z尺寸相同的全1矩阵咯,反正,z是一定是要被处理成一个标量才能进行求导
原则上,Pytorch不支持对张量的求导,即如果z是张量的话,需要先将其转为标量。

更复杂例子
import torch

x = torch.tensor(3.,requires_grad=True)
p = torch.ones(2,2,requires_grad=True)

y = x*x
z = 2*y+2*p*p
# [
# [1,1],
# [1,1]
# ]
z.backward(torch.ones_like(z))
# # z = z.sum() # 与下面的torch.sum(z)作用相同,即z中所有元素的和。
# z = torch.sum(z)
# z.backward()
print(x.grad)
print(p.grad)
# print(y.grad) # backward()无法对非叶子节点求导

# 知识点汇总:
# 原则上,Pytorch不支持对张量的求导,即如果z是张量的话,需要先将其转为标量。
# 就这个例子来说,z.backward(torch.ones_like(z))中的torch.ones_like(z)相当于在对z进行求导时,对z中的元素进行了求和操作,从而将其转为一个标量。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

pp,张量相乘,对应位置的元素相乘,torch.mul()和 ,广播机制
z = 2y+2p*p,张量相加,广播机制,y这个标量被生生广播 扩维了,
当 z.sum().backward(),求和再对x求导,这个导数就大了不少(广播机制之后再求和,计算过程中标量y维数扩大了四倍,导致z对y的导数也扩大了四倍,夸大了,不合适

这么大,对x求导不太公正啊

实际上,也可以通过 求均值 的形式将其转为标量
z = z.mean() # z中所有元素的均值
z.backward()

在这里插入图片描述
该部分来自于此处

retain_graph=True参数

当我们计算梯度时,PyTorch会自动根据计算图反向传播梯度来更新模型参数。但是,当我们的计算图比较复杂,或者需要多次反向传播时,我们可能需要使用retain_graph参数来保存计算图。

retain_graph表示在进行反向传播计算梯度的时候,是否保留计算图。如果设置为True,则计算图将被保留,可以在之后的操作中进行多次反向传播计算。如果为False,则计算图将被清空。这是为了释放内存并防止不必要的计算。

pytorch进行一次backward之后,各个节点的值会清除,这样进行第二次backward会报错,因为虽然计算节点数值保存了,但是计算图结构被释放了,如果加上retain_graph==True后,可以再来一次backward。

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

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

相关文章

机器/深度学习模型最优化问题详解及优化算法汇总

前言 其实最优化问题&#xff0c;从小学开始学习数学的时候就可以说已经接触到了&#xff0c;在我印象中有个问题&#xff0c;用一个平底锅煎饼&#xff0c;每次只能放2只饼&#xff0c;煎一只饼要2分钟&#xff08;正反各用1分钟&#xff09;&#xff0c;煎三只饼要几分钟。这…

C语言C位出道心法(四):文件操作

C语言C位出道心法(一):基础语法 C语言C位出道心法(二):结构体|结构体指针|链表 C语言C位出道心法(三):共用体|枚举 C语言C位出道心法(四):文件操作 一:C语言操作文件认知升维: 二:文件打开 三:文件读写操作 忙着去耍帅,后期补充完整.................................

力扣第1035题 不相交的线中等 c++ (最长公共子序列) 动态规划 附Java代码

题目 1035. 不相交的线 中等 相关标签 数组 动态规划 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#xff0c;这些直线需要同时满足满足&#xff1a; nums1[i] nums2[j]…

双编码器构建机器人零力拖动/导纳控制思路

前言 这篇博客主要记录昨日与实验室大佬针对UR5机器人拖动示教功能实现的思路。由于本人并非主攻力控方面。直到昨天在做实验的时候&#xff0c;与力控组的大佬讨论过后才了解UR机器人实现导纳控制的思路。 关于导纳控制/零力拖动 导纳控制与阻抗控制单从字面去理解很容易记…

ROS中的节点与包

ROS中的节点与包 超声波传感器节点创建Package包 创建node节点运行node节点 安装的基本单位是包 一个包就是一组节点 超声波传感器节点 创建Package包 catkin_create_pkg ssr_pkg rospy roscpp std_msgs软件包回访 其实&#xff0c;在/opt/ros/noetic/share 里面都是软件包…

【沁恒蓝牙mesh】CH58x USB功能开发记录(0)

本文主要介绍基于【沁恒蓝牙mesh】CH58x USB功能&#xff0c;结合CH583m 评估板的软硬件为二次开发作一系列说明 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是喜欢记录零碎知识点的小菜鸟。&#x1f60e;&#x1f4dd; 个人主页&#xff1a;欢迎访问我的 Etherne…

java多线程文件下载器

文章目录 1.简介2.文件下载的核心3.文件下载器的基础代码3.1 HttpURLConnection3.2 用户标识 4.下载信息4.1 计划任务4.2 ScheduledExecutorService&#x1f340; schedule方法&#x1f340; scheduleAtFixedRate方法&#x1f340; scheduleWithFixedDelay方法 5.线程池简介5.1…

多维时序 | MATLAB实现SOM-BP自组织映射结合BP神经网络的多变量时间序列预测

多维时序 | MATLAB实现SOM-BP自组织映射结合BP神经网络的多变量时间序列预测 目录 多维时序 | MATLAB实现SOM-BP自组织映射结合BP神经网络的多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现SOM-BP自组织映射结合BP神经网络的多变量时…

Qt 自定义分页控件

目录 前言1、功能描述2、代码实现2.1 ui文件2.1 头文件2.2 源码文件2.3 设计思路 4、示例5、总结 前言 在应用程序开发时经常会遇到数据分页的需求&#xff0c;每一页展示特定数量的数据&#xff0c;通过点击按钮翻页或者输入页码跳转到指定页。 本文介绍一个自定义分页控件&a…

微服务-开篇-个人对微服务的理解

从吃饭说起 个人理解新事物的时候喜欢将天上飞的理念转换成平常生活中的实践&#xff0c;对比理解这些高大上的名词&#xff0c;才能让我们减少恐慌的同时加深理解。废话不多说&#xff0c;我们从吃饭开始说起&#xff0c;逐渐类比出微服务的思想。 &#xff08;个人见解&…

计蒜客详解合集(1)期

以后对于简单题目&#xff0c;大致6道题目出一期&#xff0c;稍有难度的才单独一期发布~ 目录 T1266——出勤记录 T1170——人民币支付 T1122——最长最短单词 T1115——字符串判等 T1116——验证子串 T1118——删除单词后缀 T1266——出勤记录 小蒜的算法课老师每次…

任正非说:段到段而不是端到端的变革,一定会局部优秀了,而全局灾难了。

你好&#xff01;这是华研荟【任正非说】系列的第34篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、执行一个良好的流程和建立一个良好的流程同样重要。业务部门的一把手要担负起建设和优化流程的责任&#xff0c;而不是流程…

NFS服务器的搭建

架设一台NFS服务器&#xff0c;并按照以下要求配置 准备阶段&#xff1a;准备两台虚拟机&#xff0c;一台作为服务端&#xff0c;一台作为客户端 服务端&#xff08;Server&#xff09;&#xff1a;192.168.75.139 客户端&#xff08;Client&#xff09;:192.168.75.160 两…

【Java 进阶篇】Java Filter 执行流程及生命周期详解

引言 在 Java Web 开发中&#xff0c;Filter 是一种强大的组件&#xff0c;它允许我们在请求到达 Servlet 之前或者响应返回给客户端之前执行一些操作。Filter 的应用场景非常广泛&#xff0c;例如日志记录、权限验证、字符编码转换等。本文将深入讨论 Java Filter 的执行流程…

element-Cascader级联选择器用法?

html <el-form-item label"行业选择" :label-width"formLabelWidth"><div class"m-4"><el-cascader v-model"form.tradeid" :options"options" :props"props" /></div></el-form-ite…

【仿真动画】人机协作机器人自动化产线仿真动画欣赏

人机协作机器人自动化产线仿真动画 动画部分思维导图 机器人自动化产线仿真动画是利用三维动画技术对机器人自动化产线进行仿真模拟&#xff0c;以直观、形象的方式展示产线的运行情况。它具有以下作用&#xff1a; 提高沟通效率 机器人自动化产线的设计、实施和维护涉及多个部…

19.9 Boost Asio 同步字典传输

这里所代指的字典是Python中的样子&#xff0c;本节内容我们将通过使用Boost中自带的Tokenizer分词器实现对特定字符串的切割功能&#xff0c;使用Boost Tokenizer&#xff0c;可以通过构建一个分隔符或正则表达式的实例来初始化tokenizer。然后&#xff0c;可以使用该实例对输…

阿里云服务器u1和e实例有什么区别?哪个比较好?

阿里云服务器u1和e实例有什么区别&#xff1f;哪个比较好&#xff1f;通用算力型u1比较好&#xff0c;因为u1服务器是独享型云服务器&#xff0c;e实例是共享型。 阿里云服务器ECS经济型e实例和通用算力型u1实例有什么区别&#xff1f;如何选择&#xff1f;ECS经济型e实例是共…

Modern C++ 转换构造函数和类型转换函数

在 C/C 中&#xff0c;不同的数据类型之间可以相互转换。无需用户指明如何转换的称为自动类型转换&#xff08;隐式类型转换&#xff09;&#xff0c;需要用户显式地指明如何转换的称为强制类型转换。 不管是自动类型转换还是强制类型转换&#xff0c;前提必须是编译器知道如何…

U盘插在电脑上显示要格式化磁盘怎么办

U盘是一种便携式存储设备&#xff0c;广泛应用于各种场合。然而&#xff0c;有时候我们可能会遇到一些问题&#xff0c;比如将U盘插入电脑后显示要格式化磁盘&#xff0c;这通常意味着U盘的分区出现了问题或者U盘的文件系统已经损坏。这种情况下&#xff0c;我们应该如何解决呢…