2. Pytorch 张量运算

article/2024/4/20 15:20:34

目录

2.1 比较大小

 2.2基本运算

 2.3 统计相关的计算

2.4 张量的自动微分


张量计算 张量的计算内容主要包括:张量之间的大小比较,张量的基本运算,如元素之间的运算和矩阵之间的运算等,张量与统计相关的运算,如排序,最大值,最小值,最大值的位置等内容。

2.1 比较大小

对于torch.allclose()函数,比较的是两个元素是否接近,比较A和B是否接近的公式为: ∣A − B∣<= atol + rtol ×∣B∣

import torch# 比较两个数是否接近
A = torch.tensor([10.0])
B = torch.tensor([10.1])
torch.allclose(A,B,rtol=1e-05,atol=1e-08,equal_nan=False)
torch.allclose(A, B, rtol=0.1, atol=0.01, equal_nan=False)
# 在不同的判断条件下,得出的结果也是不同的# 如果equal_nan=True,那么缺失值可以判断为接近
A = torch.tensor(float("nan"))
print(torch.allclose(A, A, equal_nan=False))
print(torch.allclose(A, A, equal_nan=True))A = torch.tensor([1, 2, 3, 4, 5, 6])
B = torch.arange(1, 7)
C = torch.unsqueeze(B, dim=0)
# torch.eq()函数用来判断两个元素是否相等
print(torch.eq(A, B))
print(torch.eq(A, C))
# torch.equal()函数可以判断两个张量是否具有相同的形状和元素
print(torch.equal(A, B))
print(torch.equal(A, C))# torch.ge()函数是逐元素比较是否大于等于(>=)
print(torch.ge(A, B))
print(torch.ge(A, C))
# torch.gt()函数是逐元素比较大于
print(torch.gt(A, B))
print(torch.gt(A, C))
# torch.le()函数是逐元素比较是否小于等于(<=)
print(torch.le(A, B))
print(torch.le(A, C))
# torch.lt()函数是逐元素比较大于
print(torch.lt(A, B))
print(torch.lt(A, C))
# torch.ne()函数是逐元素比较不等于
print(torch.ne(A, B))
print(torch.ne(A, C))
# torch.isnan()函数用来判断是否为缺失值
# 缺失值是值:NULL,也包括表示数值确实的特殊数值(如,在系统中用-999来表示的数值不存在)
print(torch.isnan(torch.tensor([0, 1, float("nan"), 2])))

 输出:

False
True
tensor([True, True, True, True, True, True])
tensor([[True, True, True, True, True, True]])
True
False
tensor([True, True, True, True, True, True])
tensor([[True, True, True, True, True, True]])
tensor([False, False, False, False, False, False])
tensor([[False, False, False, False, False, False]])
tensor([True, True, True, True, True, True])
tensor([[True, True, True, True, True, True]])
tensor([False, False, False, False, False, False])
tensor([[False, False, False, False, False, False]])
tensor([False, False, False, False, False, False])
tensor([[False, False, False, False, False, False]])
tensor([False, False,  True, False])

 2.2基本运算

# 矩阵逐元素相乘
a = torch.arange(6.0).reshape(2,3)
b = torch.linspace(10, 20, steps=6).reshape(2, 3)
print("a", a)
print("b", b)
print(a * b)
# 逐元素相除
print(a / b)
# 逐元素相加
print(a + b)
# 逐元素相减
print(a - b)
# 逐元素整除
print(b // a)
# 计算张量的幂可以使用torch.pow()函数,或者使用**
print(torch.pow(a, 3))
print(a ** 3)
# 计算张量的指数可以使用torch.exp()函数
print(torch.exp(a))
# 计算张量的对数可以使用torch.log()函数
print(torch.log(a))
# 计算张量的平方根可以使用torch.sqrt()函数
print(torch.sqrt(a))
print(a ** 0.5)
# 计算张量的平方根倒数可以使用torch.rsqrt()函数
print(torch.rsqrt(a))
print(1 / (a**0.5))
​
# 对张量的数据裁剪,有根据最大值裁剪torch.clamp_max()函数
# 将大于x的数值都替换为x
print(a, "\n", torch.clamp_max(a, 4))
# 有根据最小值裁剪torch.clamp_min()函数
# 将小于x的数值都替换为x
print(torch.clamp_min(a, 3))
# 有根据范围裁剪torch.clamp()函数
# 按照范围剪裁张量,小于边界的数值都替换为下界值,大于上界的数值都替换为上界
print(torch.clamp(a, 2.5, 4))
​
# torch.t()计算矩阵的转置
c = torch.t(a)
print(c)
# torch.matmul()输出两个矩阵的乘积
print(a.matmul(c))
# 矩阵相乘只计算最后面的两个维度的乘法
a = torch.arange(12.0).reshape(2, 2, 3)
b = torch.arange(12.0).reshape(2, 3, 2)
print(a, b)
ab = torch.matmul(a, b)
print(ab)
print(ab[0].eq(torch.matmul(a[0], b[0])))
print(ab[0].eq(torch.matmul(a[1], b[0])))
​
# 计算矩阵的逆
c = torch.rand(3, 3)
d = torch.inverse(c)
print(torch.mm(c, d))
​
# 计算张量矩阵的迹,对角线元素的和
print(torch.trace(torch.arange(9.0).reshape(3, 3)))
a tensor([[0., 1., 2.],[3., 4., 5.]])
b tensor([[10., 12., 14.],[16., 18., 20.]])
tensor([[  0.,  12.,  28.],[ 48.,  72., 100.]])
tensor([[0.0000, 0.0833, 0.1429],[0.1875, 0.2222, 0.2500]])
tensor([[10., 13., 16.],[19., 22., 25.]])
tensor([[-10., -11., -12.],[-13., -14., -15.]])
tensor([[inf, 12.,  7.],[ 5.,  4.,  4.]])
tensor([[  0.,   1.,   8.],[ 27.,  64., 125.]])
tensor([[  0.,   1.,   8.],[ 27.,  64., 125.]])
tensor([[  1.0000,   2.7183,   7.3891],[ 20.0855,  54.5981, 148.4132]])
tensor([[  -inf, 0.0000, 0.6931],[1.0986, 1.3863, 1.6094]])
tensor([[0.0000, 1.0000, 1.4142],[1.7321, 2.0000, 2.2361]])
tensor([[0.0000, 1.0000, 1.4142],[1.7321, 2.0000, 2.2361]])
tensor([[   inf, 1.0000, 0.7071],[0.5774, 0.5000, 0.4472]])
tensor([[   inf, 1.0000, 0.7071],[0.5774, 0.5000, 0.4472]])
tensor([[0., 1., 2.],[3., 4., 5.]]) tensor([[0., 1., 2.],[3., 4., 4.]])
tensor([[3., 3., 3.],[3., 4., 5.]])
tensor([[2.5000, 2.5000, 2.5000],[3.0000, 4.0000, 4.0000]])
tensor([[0., 3.],[1., 4.],[2., 5.]])
tensor([[ 5., 14.],[14., 50.]])
tensor([[[ 0.,  1.,  2.],[ 3.,  4.,  5.]],[[ 6.,  7.,  8.],[ 9., 10., 11.]]]) tensor([[[ 0.,  1.],[ 2.,  3.],[ 4.,  5.]],[[ 6.,  7.],[ 8.,  9.],[10., 11.]]])
tensor([[[ 10.,  13.],[ 28.,  40.]],[[172., 193.],[244., 274.]]])
tensor([[True, True],[True, True]])
tensor([[False, False],[False, False]])
tensor([[ 1.0000e+00,  5.9605e-08, -2.9057e-07],[ 5.9605e-08,  1.0000e+00, -1.7881e-07],[ 5.9605e-08, -5.9605e-08,  1.0000e+00]])
tensor(12.)

API方式的写法

# 此外,加减乘除还可以使用API
A = torch.tensor([1.,2.,3.,4.,5.,6.])
A = A.reshape(2,3)
print(A+3)
B = torch.ones(2,3)
print(B)
print(A+B) #广播原则 不会改变原有的结果
A.add(B)  #不会改变原有的结果
print(A)
A.add_(B) #会改变原有的结果  很多后面加上_会就地改变原值 
print(A)
print(torch.abs(A))   #它们不仅有这种静态方法
print(A.abs_())      #也是有实例方法的
tensor([[4., 5., 6.],[7., 8., 9.]])
tensor([[1., 1., 1.],[1., 1., 1.]])
tensor([[2., 3., 4.],[5., 6., 7.]])
tensor([[1., 2., 3.],[4., 5., 6.]])
tensor([[2., 3., 4.],[5., 6., 7.]])
tensor([[2., 3., 4.],[5., 6., 7.]])
tensor([[2., 3., 4.],[5., 6., 7.]])

注意 abs,mean,cumsum,multiply,divide 都有这些性质

t = torch.rand(2,3)
print(t)
print(t.T)  #转置 shape (3,2)
print(t.matmul(t.T))
#矩阵乘法的简化写法
print(t@(t.T))
print(t.sum())
print(t.sum().item())   #将其转为python的数据类型 
result = t.mean()     
print(result.item())

tensor([[0.5961, 0.0197, 0.8739],[0.8200, 0.0368, 0.2758]])
tensor([[0.5961, 0.8200],[0.0197, 0.0368],[0.8739, 0.2758]])
tensor([[1.1194, 0.7305],[0.7305, 0.7498]])
tensor([[1.1194, 0.7305],[0.7305, 0.7498]])
tensor(2.6223)
2.6223182678222656
0.43705305457115173

 2.3 统计相关的计算

# 一维张量的最大值和最小值
a = torch.tensor([12., 34, 25, 11, 67, 32, 29, 30, 99, 55, 23, 44])
print("最大值:", a.max())
print("最大值位置:", a.argmax())
print("最小值", a.min())
print("最小值位置", a.argmin())
​
b = a.reshape(3, 4)
print("2-D张量:", b)
# 最大值及位置(每行)
print("最大值:", b.max(dim=1))
print("最大值位置:", b.argmax(dim=1))
# 最小值及位置(每列)
print("最小值", b.min(dim=0))
print("最小值位置", b.argmin(dim=0))
​
# torch.sort()可以对一维张量进行排序,或者对高维张量在指定的维度进行排序,输出排序结果,还会输出对应的值在原始位置的索引
print(torch.sort(a))
# 按照降序排序
print(torch.sort(a, descending=True))
# 对二维张量进行排序
bsort, bsort_id = torch.sort(b)
print("b sort", bsort)
print("b sort_id", bsort_id)
print("b argsort:", torch.argsort(b))
​
# torch.topk()根据指定的k值,计算出张量中取值大小为第k大的数值与数值所在的位置
# torch.kthvalue()根据指定的数值k,计算出张量中取值大小为第k小的数值与数值所在的位置
​
# 获取张量前几大的数值
print(torch.topk(a, 4))
# 获取2-D张量每列前几大的数值
btop2, btop2_id = torch.topk(b, 2, dim=0)
print("b 每列 top2", btop2)
print("b 每列 top2 位置", btop2_id)
​
# 获取张量第k小的数值和位置
print(torch.kthvalue(a, 3))
​
# 获取2-D张量第k小的数值和位置
print(torch.kthvalue(b, 3, dim=1))
# 获取2-D张量第k小的数值和位置
bkth, bkth_id = torch.kthvalue(b, 3, dim=1, keepdim=True)
print(bkth)
​
# torch.mean()根据指定的维度计算均值
# 计算每行的平均值
print(torch.mean(b, dim=1, keepdim=True))
# 计算每列的均值
print(torch.mean(b, dim=0, keepdim=True))
# torch.sum()根据指定的维度求和
# 计算每行的和
print(torch.sum(b, dim=1, keepdim=True))
# 计算每列的和
print(torch.sum(b, dim=0, keepdim=True))
# torch.cumsum()根据指定的维度计算累加和
# 按照行计算累加和
print(torch.cumsum(b, dim=1))
# 按照列计算累加和
print(torch.cumsum(b, dim=0))
# torch.median()根据指定的维度计算中位数
# 计算每行的中位数
print(torch.median(b, dim=1, keepdim=True))
# 计算每列的中位数
print(torch.median(b, dim=0, keepdim=True))
# 按照行计算乘积
print(torch.prod(b, dim=1, keepdim=True))
# 按照列计算乘积
print(torch.prod(b, dim=1, keepdim=True))
# 按照行计算累乘积
print(torch.cumprod(b, dim=1))
# 按照列计算累乘积
print(torch.cumprod(b, dim=0))
# torch.std()计算张量的标准差
print(torch.std(a))
最大值: tensor(99.)
最大值位置: tensor(8)
最小值 tensor(11.)
最小值位置 tensor(3)
2-D张量: tensor([[12., 34., 25., 11.],[67., 32., 29., 30.],[99., 55., 23., 44.]])
最大值: torch.return_types.max(
values=tensor([34., 67., 99.]),
indices=tensor([1, 0, 0]))
最大值位置: tensor([1, 0, 0])
最小值 torch.return_types.min(
values=tensor([12., 32., 23., 11.]),
indices=tensor([0, 1, 2, 0]))
最小值位置 tensor([0, 1, 2, 0])
torch.return_types.sort(
values=tensor([11., 12., 23., 25., 29., 30., 32., 34., 44., 55., 67., 99.]),
indices=tensor([ 3,  0, 10,  2,  6,  7,  5,  1, 11,  9,  4,  8]))
torch.return_types.sort(
values=tensor([99., 67., 55., 44., 34., 32., 30., 29., 25., 23., 12., 11.]),
indices=tensor([ 8,  4,  9, 11,  1,  5,  7,  6,  2, 10,  0,  3]))
b sort tensor([[11., 12., 25., 34.],[29., 30., 32., 67.],[23., 44., 55., 99.]])
b sort_id tensor([[3, 0, 2, 1],[2, 3, 1, 0],[2, 3, 1, 0]])
b argsort: tensor([[3, 0, 2, 1],[2, 3, 1, 0],[2, 3, 1, 0]])
torch.return_types.topk(
values=tensor([99., 67., 55., 44.]),
indices=tensor([ 8,  4,  9, 11]))
b 每列 top2 tensor([[99., 55., 29., 44.],[67., 34., 25., 30.]])
b 每列 top2 位置 tensor([[2, 2, 1, 2],[1, 0, 0, 1]])
torch.return_types.kthvalue(
values=tensor(23.),
indices=tensor(10))
torch.return_types.kthvalue(
values=tensor([25., 32., 55.]),
indices=tensor([2, 1, 1]))
tensor([[25.],[32.],[55.]])
tensor([[20.5000],[39.5000],[55.2500]])
tensor([[59.3333, 40.3333, 25.6667, 28.3333]])
tensor([[ 82.],[158.],[221.]])
tensor([[178., 121.,  77.,  85.]])
tensor([[ 12.,  46.,  71.,  82.],[ 67.,  99., 128., 158.],[ 99., 154., 177., 221.]])
tensor([[ 12.,  34.,  25.,  11.],[ 79.,  66.,  54.,  41.],[178., 121.,  77.,  85.]])
torch.return_types.median(
values=tensor([[12.],[30.],[44.]]),
indices=tensor([[0],[3],[3]]))
torch.return_types.median(
values=tensor([[67., 34., 25., 30.]]),
indices=tensor([[1, 0, 0, 1]]))
tensor([[ 112200.],[1865280.],[5510340.]])
tensor([[ 112200.],[1865280.],[5510340.]])
tensor([[1.2000e+01, 4.0800e+02, 1.0200e+04, 1.1220e+05],[6.7000e+01, 2.1440e+03, 6.2176e+04, 1.8653e+06],[9.9000e+01, 5.4450e+03, 1.2524e+05, 5.5103e+06]])
tensor([[1.2000e+01, 3.4000e+01, 2.5000e+01, 1.1000e+01],[8.0400e+02, 1.0880e+03, 7.2500e+02, 3.3000e+02],[7.9596e+04, 5.9840e+04, 1.6675e+04, 1.4520e+04]])
tensor(25.0108)

2.4 张量的自动微分

在torch中的torch.autograd模块,提供了实现任意标量值函数自动求导的类和函数。针对一个张量只需要设置参数requires_grad = True,通过相关计算即可输出其在传播过程中的梯度(导数)信息。 如在PyTorch中生成一个矩阵张量x,并且y=sum(x2+2x+1)。计算出y在x上的导数,实现过程如下:

import torch
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]], requires_grad=True)# requires_grad  pytorch是否自动跟踪计算它的梯度计算
# 默认requires_grad=False
y = torch.sum(x**2+2*x+1)
print("x是否可导:", x.requires_grad)
print("y是否可导:", y.requires_grad)
print("x:", x)
print("y:", y)
## 计算y在x上的梯度
y.backward()
print("y在x的每个元素上的导数为:",x.grad) #打印x的梯度,d(y)/d(x)
with torch.no_grad(): #pytorch不要跟踪运算 上下文管理器,用于测试。 有些时候,我们不想一些层参与运算,那么就让requires_grad变为false或者使用上下文管理器y = x + 2print(y.requires_grad)
result = x.detach() #截断梯度运算    
print(result.requires_grad)
x.data

x是否可导: True
y是否可导: True
x: tensor([[1., 2.],[3., 4.]], requires_grad=True)
y: tensor(54., grad_fn=<SumBackward0>)
y在x的每个元素上的导数为: tensor([[ 4.,  6.],[ 8., 10.]])
False
False

Out[24]:

tensor([[1., 2.],[3., 4.]])

http://www.ngui.cc/article/show-861348.html

相关文章

[leetcode 215] 数组中的第K个最大元素

题目 题目&#xff1a;https://leetcode.cn/problems/kth-largest-element-in-an-array/description/ 解法 这道题目目前快排可以直接过&#xff0c;但是时间复杂度是 O(nlogn)O(nlogn)O(nlogn)。 想要 O(n)O(n)O(n)&#xff0c;这就涉及到408考研知识点了&#x1f602;&…

ideal整合reids实现缓存查询

目录 前言&#xff1a; 一.工作流程 二. RedisConfig类 三.application.properties 四.开启linux中的redis 五.使用redis结合数据库进行数据查询 5.1编程式缓存 5.2声明式缓存 5.2.1在启动类上添加注解 5.2.2实现代码 六.运行结果 ​编辑 前言&#xff1a; 废话不多讲…

JAVA02_02学习总结(Spring开启事务,Spring通知和curd数据库)

今日内容 1. SpringAOP和数据库进行curd操作 SpringAOPSpring核心技术之一对数据库进行curd操作时,进行增强 思想增强数据库的curd业务,将SpringAOP技术整合进去,为后面的Spring方式控制事务做准备 需要准备的依赖包mybatismysql驱动spring-context依赖包druid连接池-德…

Word处理控件Aspose.Words功能演示:使用 C++ 处理 Word 文档中的目录

Aspose API支持流行文件格式处理&#xff0c;并允许将各类文档导出或转换为固定布局文件格式和最常用的图像/多媒体格式。 Aspose.words是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和…

软件测试真的可以达到月薪20k+?不会自动化测试的我真的很难....

做自动化测试后悔吗&#xff1f; 后悔&#xff0c;真的后悔&#xff01; 后悔没有早点学..... 虽然现在网上到处都在散播35的焦虑&#xff0c;姑且信之&#xff0c;那么反问你&#xff0c;如果你30岁了&#xff0c;那么给你5年&#xff0c;能够在某个领域成为专家呢&#xf…

Oracle的启动与关闭

启动oracle 启动数据库实例&#xff0c;分为两步&#xff1a;第一步&#xff0c;启动监听&#xff1b;第二步&#xff0c;启动数据库实例。 一、如何启动数据库实例 1.进入到sqlplus启动实例 –“切换到oracle用户” su - oracle –“打开监听” lsnrctl start –“进入到sql…

Python 初学者进阶的九大技能

Python是一种很棒的语言&#xff0c;语法简单&#xff0c;无需在代码中搜索分号。对于初学者来说&#xff0c;Python是入门最简单的语言之一。 Python有大量的库支持&#xff0c;你还可以安装其他库来增加自己的编程经验。 学了一阵子之后&#xff0c;你可能会觉得&#xff1…

同台服务器上部署多个Mysql数据库

1、新建数据库 将已安装好的5.7版本库文件夹复制一份&#xff0c;文件夹改为5.8&#xff0c;只为区分文件&#xff0c;与版本无关&#xff0c;名字自定义即可。 2、创建服务&#xff1a; 管理员身份cmd进入C:\Program Files\MySQL\MySQL Server 5.8\bin路径&#xff0c;输入my…

1月的碎碎念,但是很有必要

从今年开始每个月会整理一个我生活的琐碎但觉得有必要的事&#xff0c;一来方便年底回顾&#xff0c;二来也希望这些事情对大家有也有些参考。 不高大上&#xff0c;但是希望某一天再看到的时候会觉得充满趣味。1.新的1年的1月开始了&#xff0c;想了很多计划&#xff0c;搬新办…

springboot引入redis

在接口中添加redis缓存 由于首页数据变化不是很频繁&#xff0c;而且首页访问量相对较大&#xff0c;所以我们有必要把首页接口数据缓存到redis缓存中&#xff0c;减少数据库压力和提高访问速度。 改造service-cms模块首页banner接口&#xff0c;首页课程与讲师接口类似 3.1 Sp…