PyTorch基础学习03_数学运算自动微分

ops/2024/11/28 11:58:33/

目录

一、数学运算

1、基本操作

2、三角函数

3、统计学函数

二、保存和加载

三、并行化

四、自动微分

1、相关概念

2、计算梯度

1.标量梯度计算

2.向量梯度计算

3.多标量梯度计算

4.多向量梯度计算

5.矩阵梯度计算

3、梯度上下文控制

1、梯度控制

2、梯度更新

3、叶子节点


导入torch库:

import torch

一、数学运算

1、基本操作

  • floor: 向下取整;

  • ceil:向上取整;

  • round:四舍五入;

  • trunc:裁剪,只保留整数部分;

  • frac:只保留小数部分;

  • fix:向零方向舍入;

  • %:取余;

  • abs:取绝对值。

data = torch.tensor([[1, 2, -3.5],  # 1[4, 5, 6],  # 2[10.5, 18.6, 19.6],  # 3[11.05, 19.3, 20.6],  # 4]
)
print(data)
# 向下取整(往小取 返回不大于每个元素的最大整数)
x1 = torch.floor(data)
print(x1)
# 向上取整(往大取 返回不小于每个元素的最小整数)
x2 = torch.ceil(data)
print(x2)
# 四舍五入 与python round()一致 四舍六入五看齐(看个位奇偶,奇进偶舍)
x3 = torch.round(data)
print(x3)
# 截断,只保留整数部分
x4 = torch.trunc(data)
print(x4)
# 截断,只保留小数部分
x5 = torch.frac(data)
print(x5)
# 向零方向舍入(舍入到最接近零的整数)
x6 = torch.fix(data)
print(x6)
# 取余
x7 = torch.fmod(data, 2)
print(x7)
# 绝对值
x8 = torch.abs(data)
print(x8)

2、三角函数

  • torch.cos(input,out=None)

  • torch.cosh(input,out=None) # 双曲余弦函数

  • torch.sin(input,out=None)

  • torch.sinh(input,out=None) # 双曲正弦函数

  • torch.tan(input,out=None)

  • torch.tanh(input,out=None) # 双曲正切函数

# torch.set_printoptions(sci_mode=False)print(torch.pi) # 圆周率
deg = torch.pi/180
data = torch.tensor([0,90*deg,45*deg])
x1 = torch.sin(data)
print(x1)
x2 = torch.cos(data)
print(x2)
x3 = torch.sinh(data)
print(x3)
x4 = torch.cosh(data)
print(x4)
x5 = torch.tan(data)
print(x5)
x6 = torch.tanh(data)
print(x6)

3、统计学函数

  1. torch.mean(): 计算张量的平均值。

  2. torch.sum(): 计算张量的元素之和。

  3. torch.std(): 计算张量的标准差。

  4. torch.var(): 计算张量的方差。

  5. torch.median(): 计算张量的中位数。

  6. torch.max(): 计算张量的最大值。

  7. torch.min(): 计算张量的最小值。

  8. torch.mode():  计算张量众数

  9. torch.sort(): 对张量进行排序。 返回排序后的张量values和索引indices

  10. torch.topk(): 返回张量中的前 k 个最大值或最小值。

  11. torch.histc(): 计算张量的直方图。

  12. torch.unique(): 返回张量中的唯一值。

  13. torch.bincount(): 计算张量中每个元素的出现次数。

torch.manual_seed(66)
x = torch.tensor([1,2,2,3,3,3,4,4,5]).type(torch.float32)
print(x)
# 平均值
x1 = x.mean()
print(x1)
# 求和
x2 = x.sum()
print(x2)
# 标准差
x3 = x.std()
print(x3)
# 方差
x4 = x.var()
print(x4)
# 中位数
x5 = x.median()
print(x5)
# 最大值
x6 = x.max()
print(x6)
# 最小值
x7 = x.min()
print(x7)
# 众数
x8 = torch.mode(x)
print(x8)
# 排序 返回排序后的张量values和索引indices
x9 = torch.sort(x)
print(x9)x = torch.tensor([1,2,2,3,3,3,4,4,5,2,3,4,6]).type(torch.float32)
print(torch.topk(x,3)) # 返回前3个最大值
print(torch.histc(x,bins=10, min=2,max=4)) # 区间[min,max]分成bins份 表示各个区间的元素计数
print(torch.unique(x)) # 返回分类的数据集中的数据类型x = torch.tensor([1,2,2,3,3,3,4,4,5,2,3,4,6])
print(torch.bincount(x)) # 返回张量中每个元素的出现次数

二、保存和加载

# 保存
x = torch.tensor([1,2,3])
torch.save(x,'./data/tensor01.pth')device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 加载
y = torch.load('./data/tensor01.pth',map_location=device)
print(y)
print(y.device)

三、并行化

在 PyTorch 中,可以查看和设置用于 CPU 运算的线程数。PyTorch 使用多线程来加速 CPU 运算,但有时可能需要调整线程数来优化性能。

# torch.get_num_threads() 来查看当前 PyTorch 使用的线程数
def test01():count = torch.get_num_threads()print(count)# torch.set_num_threads() 设置 PyTorch 使用的线程数
def test02():torch.set_num_threads(4)count = torch.get_num_threads()print(count)if __name__ == '__main__':test01()test02()

 设置线程数时,确保考虑到你的 CPU 核心数和其他进程的资源需求,以获得最佳性能。

注意事项

  • 线程数设置过高可能会导致线程竞争,反而降低性能;

  • 线程数设置过低可能会导致计算资源未得到充分利用;

  • 当使用 GPU 进行计算时,线程数设置对性能影响较小,因为 GPU 计算并不依赖于 CPU 线程数。

四、自动微分

自动微分模块torch.autograd负责自动计算张量操作的梯度,具有自动求导功能。自动微分模块是构成神经网络训练的必要模块,可以实现网络权重参数的更新,使得反向传播算法的实现变得简单而高效。

1、相关概念

  1. 张量

    Torch中的对象都为张量,属性requires_grad决定是否对其进行梯度计算。默认是 False,如需计算梯度则设置为True。

  2. 计算图

    torch.autograd通过创建一个动态计算图来跟踪张量的操作,每个张量是计算图中的一个节点,节点之间的操作构成图的边。

  3. 反向传播

    使用tensor.backward()方法执行反向传播,从而计算张量的梯度。这个过程会自动计算每个张量对损失函数的梯度。

  4. 梯度

    计算得到的梯度通过tensor.grad访问,这些梯度用于优化模型参数,以最小化损失函数。

2、计算梯度

使用tensor.backward()方法执行反向传播,以计算张量的梯度。

1.标量梯度计算
# 创建张量:要计算梯度则必须为浮点类型
x = torch.tensor(3, require_grad=True, dtype=torch.float64)
# 定义函数
y = x**2 + 2*x - 5
# 计算梯度,也就是反向传播
y.backward() # # 梯度计算 1.y函数对x求导函数 y'=2*x+2 2.代入x的当前值 x=3 3.求出导数值 y'=2*3+2
# 读取梯度值
print(x.grad) # tensor(8.)
2.向量梯度计算
# 向量梯度计算
x = torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
y = x**2 + 2*x - 5
print(y) # tensor([-2.,  3., 10.], dtype=torch.float64, grad_fn=<SubBackward0>)y = y.sum() # y必须是一个标量才能用这个标量对x求导 设置一个复合函数y.backward() # y'=2x+2
print(x.grad) # tensor([4., 6., 8.], dtype=torch.float64)
3.多标量梯度计算
# 多标量的梯度计算
x1 = torch.tensor(1,requires_grad=True,dtype=torch.float64)
x2 = torch.tensor(2,requires_grad=True,dtype=torch.float64)
y = x1**2 + 3*x2 - 5y.backward() # 偏导数print(x1.grad)
print(x2.grad)
4.多向量梯度计算
# 多向量的梯度计算
x1 = torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
x2 = torch.tensor([4,5,6],requires_grad=True,dtype=torch.float64)
y = x1**2 + 3*x2 - 5y = y.sum()y.backward() # 偏导数
print(x1.grad) # 2*x1 tensor(2., dtype=torch.float64)
print(x2.grad) # 3 tensor(3., dtype=torch.float64)
5.矩阵梯度计算
# 矩阵梯度计算
x = torch.tensor([[1,2],[3,4]],requires_grad=True,dtype=torch.float64)
y = x**2 + 2*x - 5y = y.sum()y.backward()
print(x.grad)

3、梯度上下文控制

梯度计算的上下文控制和设置对于管理计算图、内存消耗、以及计算效率至关重要。

1、梯度控制

梯度计算是有性能开销的,有些时候只是简单的运算,此时并不需要梯度。

# 正常情况下
def test01():x = torch.tensor(10.5, requires_grad=True)print(x.requires_grad)  # True# 默认y的requires_grad=Truey = x**2 + 2 * x + 3print(y.requires_grad)  # Truedef test02():x = torch.tensor(5, requires_grad=True,dtype=torch.float64)# 关闭y的梯度计算 使用with进行上下文管理with torch.no_grad():y = x**2 + 2*x - 5print(y.requires_grad) # False# 使用装饰器
@torch.no_grad()
def test03():x = torch.tensor([1,2,3], requires_grad=True,dtype=torch.float64)y = x**2 + 2*x - 5y = y.sum()print(y.requires_grad) # False# 自己创建装饰器
def my_no_grad(func):def wrapper(): with torch.no_grad():re = func()return rereturn wrapper@my_no_grad
def test04():x = torch.tensor([1,2,3], requires_grad=True,dtype=torch.float64)y = x**2 + 2*x - 5y = y.sum()print(y.requires_grad) # False# 全局设置关闭梯度计算
def test05():x = torch.tensor([1,2,3], requires_grad=True,dtype=torch.float64)torch.set_grad_enabled(False)y = x**2 + 2*x - 5y = y.sum()y.backward()print(x.requires_grad)print(y.requires_grad)print(x.grad)# 累计梯度
def test06():x = torch.tensor(1, requires_grad=True,dtype=torch.float64)y = x**2 + 2*x - 5y.backward()print(x.grad)y = 2*x**2 + 7y.backward()print(x.grad)# 累计梯度02
def test07():x = torch.tensor(4, requires_grad=True,dtype=torch.float64)for _ in range(4):y = x**2 + 2*x - 5y.backward()print(x.grad)# 梯度清零
def test08():x = torch.tensor(4, requires_grad=True,dtype=torch.float64)y = x**2 + 2*x - 5y.backward() # 2*x + 2print(x.grad)z = 3*x**2 + 7*x# 清零x.grad.zero_() # 不清零则为 10+31=41z.backward() # 清零后为 6*4+7=31print(x.grad)# 综合梯度清零操作for _ in range(3):y = x**2 + 2 * x + 7z = y.mean()# 反向传播之前先对梯度进行清零if x.grad is not None:x.grad.zero_()z.backward()print(x.grad)if __name__ == '__main__':test01()test02()test03()test04()test05()test06()test07()test08()
2、梯度更新

大多数情况下是不需要梯度累加的,反向传播之前可以先用 .zero_() 对梯度进行清零。

更新梯度时,注意更新的数据应是data,直接改变原tensor会导致其变成新的数据。

# 标量训练
def test01():# 生成初始化ww = torch.tensor(25., requires_grad=True)# 训练参数lr = 0.01epoch = 5for i in range(epoch):# 生成损失函数loss = 3*w**2 + 2*w - 5# 梯度清零if w.grad is not None: w.grad.zero_()# 反向传播 求当前w的导数值:梯度值,斜率loss.backward()# 当前斜率print(w.grad)# 更新梯度# w的tensor不能修改 避免w变成新的数据 应修改w.dataw.data = w.data - lr*w.grad.dataprint(w)# 访问训练后的w的值print(w.data)# 向量训练
def test02():# 生成初始化ww = torch.tensor([10,20,30], requires_grad=True,dtype=torch.float64)# 训练参数lr = 0.01epoch = 5for i in range(epoch):# 生成损失函数loss = 3*w**2 + 2*w - 5loss = loss.sum() # 设置一个复合函数# 梯度清零if w.grad is not None: w.grad.zero_()# 反向传播 求当前w的导数值:梯度值,斜率loss.backward()# 当前斜率print(w.grad)# 更新梯度# w的tensor不能修改 避免w变成新的数据 应修改w.dataw.data = w.data - lr*w.grad.dataprint(w)# 访问训练后的w的值print(w.data)# 保存训练好的权重数据torch.save(w.data,'./data/weight.pth')# 加载训练好的权重数据
def detect():w = torch.load('./data/weight.pth',map_location='cuda')# 使用wprint(w)if __name__ == '__main__':# test01()test02()detect()
3、叶子节点

当想使用不含求导功能的tensor时,可以使用detach()创建张量,该张量是作为叶子结点存在的,并且该张量和原张量共享数据,只是该张量不需要计算梯度。

原因:可以求导的张量不能直接当作普通的tensor使用,如转换为numpy数组操作: .numpy()

# detach()产生的张量是作为叶子结点存在的,并且该张量和原张量共享数据,只是该张量不需要计算梯度。
def test01():x = torch.tensor([1, 2, 3], requires_grad=True,dtype=torch.float32)# x1 = x.numpy() # 报错 如果x是一个可以求导的张量,那么它就不能直接当作普通的tensor使用def test02():x = torch.tensor([1, 2, 3], requires_grad=True,dtype=torch.float32)x2 = x.detach() # 创建一个叶子结点,并且和x共享数据,但是不需要计算梯度print(x) # tensor([1., 2., 3.], requires_grad=True)print(x2) # tensor([1., 2., 3.])print(id(x),id(x2)) # 两个对象print(id(x.data),id(x2.data)) # 数据共享x2[0] = 5print(x,x2)if __name__ == '__main__':test02()


http://www.ppmy.cn/ops/137346.html

相关文章

tcp、http、rpc的区别

TCP、HTTP 和 RPC 是网络通信中常见的协议和方法&#xff0c;各自有不同的用途和特性。以下是它们的主要区别&#xff1a; 1. TCP&#xff08;传输控制协议&#xff09; 类型: 传输层协议功能: TCP 是一个面向连接的协议&#xff0c;提供可靠的数据传输。确保数据包的顺序和完…

2022 年 3 月青少年软编等考 C 语言三级真题解析

目录 T1. 和数思路分析T2. 生理周期思路分析T3. 分解因数T4. 文件结构 “图”思路分析T5. 矩形数量思路分析T1. 和数 给定一个正整数序列,判断其中有多少个数,等于数列中其他两个数的和。比如,对于数列 1 2 3 4 1\ 2\ 3\ 4 1 2 3 4,这个问题的答案就是 2 2 2,因为…

springboot配置https,并使用wss

学习链接 springboot如何将http转https SpringBoot配置HTTPS及开发调试 Tomcat8.5配置https和SpringBoot配置https 可借鉴的参考&#xff1a; springboot如何配置ssl支持httpsSpringBoot配置HTTPS及开发调试的操作方法springboot实现的https单向认证和双向认证(java生成证…

模型 承诺一致原则

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。言行一致&#xff0c;承诺铸就行动。 1 承诺一致原则的应用 1.1 《得到》APP如何利用承诺一致性原则提升用户忠诚度 《得到》APP是一个知识服务平台&#xff0c;其口号“和你一起&#xff0c;终身学…

【UVM】TLM通信机制

基本概念 TLM&#xff08;transaction level modeling&#xff09;是一个基于事务&#xff08;transaction&#xff09;的通信方式&#xff0c;每次传输一个transaction&#xff0c;一个transaction就是把具有某一特定功能的一组信息封装在一起而成为的一个类。 通信对象 发起…

深度学习:GPT-2的MindSpore实践

GPT-2简介 GPT-2是一个由OpenAI于2019年提出的自回归语言模型。与GPT-1相比&#xff0c;仍基于Transformer Decoder架构&#xff0c;但是做出了一定改进。 模型规格上&#xff1a; GPT-1有117M参数&#xff0c;为下游微调任务提供预训练模型。 GPT-2显著增加了模型规模&…

华为Mate 70系列发布,揭示AI+消费电子产业化新阶段

消费电子第三次创新浪潮正在到来。 从“‌PC电脑功能机”时代到“智能手机平板”时代&#xff0c;再到AI赋能下的新产品时代&#xff0c;消费电子硬件革新的“十二年定律”依然奏效。 在这样的背景下&#xff0c;11月26日举办的华为Mate品牌盛典向市场展示了终端硬件领域最新…

elasticsearch的文档管理

2 json数据入门 json数据类型 基础数据类型 字符串&#xff0c;只要用双引号包裹的都是字符串类型。“嘻嘻”&#xff0c;“文勇”&#xff0c;“2024” 数字型&#xff0c;2024&#xff0c;3.1415926 布尔型&#xff0c;true 和 false 空值&#xff0c;null 高级数据类…