张量的数学运算
时间:2022-07-22
本文章向大家介绍张量的数学运算,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Pytorch的低阶API主要包括张量操作,动态计算图和自动微分。
如果把模型比作一个房子,那么低阶API就是【模型之砖】。
在低阶API层次上,可以把Pytorch当做一个增强版的numpy来使用。
Pytorch提供的方法比numpy更全面,运算速度更快,如果需要的话,还可以使用GPU进行加速。
前面几章我们对低阶API已经有了一个整体的认识,本章我们将重点详细介绍张量操作和动态计算图。
张量的操作主要包括张量的结构操作和张量的数学运算。
张量结构操作诸如:张量创建,索引切片,维度变换,合并分割。
张量数学运算主要有:标量运算,向量运算,矩阵运算。另外我们会介绍张量运算的广播机制。
动态计算图我们将主要介绍动态计算图的特性,计算图中的Function,计算图与反向传播。
本篇我们介绍张量的数学运算。
一,标量运算
张量的数学运算符可以分为标量运算符、向量运算符、以及矩阵运算符。
加减乘除乘方,以及三角函数,指数,对数等常见函数,逻辑比较运算符等都是标量运算符。
标量运算符的特点是对张量实施逐元素运算。
有些标量运算符对常用的数学运算符进行了重载。并且支持类似numpy的广播特性。
import torch
import numpy as np
a = torch.tensor([[1.0,2],[-3,4.0]])
b = torch.tensor([[5.0,6],[7.0,8.0]])
a+b #运算符重载
tensor([[ 6., 8.],
[ 4., 12.]])
a-b
tensor([[ -4., -4.],
[-10., -4.]])
a*b
tensor([[ 5., 12.],
[-21., 32.]])
a/b
tensor([[ 0.2000, 0.3333],
[-0.4286, 0.5000]])
a**2
tensor([[ 1., 4.],
[ 9., 16.]])
a**(0.5)
tensor([[1.0000, 1.4142],
[ nan, 2.0000]])
a%3 #求模
tensor([[1., 2.],
[0., 1.]])
a//3 #地板除法
tensor([[ 0., 0.],
[-1., 1.]])
a>=2 # torch.ge(a,2) #ge: greater_equal缩写
tensor([[False, True],
[False, True]])
(a>=2)&(a<=3)
tensor([[False, True],
[False, False]])
(a>=2)|(a<=3)
tensor([[True, True],
[True, True]])
a==5 #torch.eq(a,5)
tensor([[False, False],
[False, False]])
torch.sqrt(a)
tensor([[1.0000, 1.4142],
[ nan, 2.0000]])
a = torch.tensor([1.0,8.0])
b = torch.tensor([5.0,6.0])
c = torch.tensor([6.0,7.0])
d = a+b+c
print(d)
tensor([12., 21.])
print(torch.max(a,b))
tensor([5., 8.])
print(torch.min(a,b))
tensor([1., 6.])
x = torch.tensor([2.6,-2.7])
print(torch.round(x)) #保留整数部分,四舍五入
print(torch.floor(x)) #保留整数部分,向下归整
print(torch.ceil(x)) #保留整数部分,向上归整
print(torch.trunc(x)) #保留整数部分,向0归整
tensor([ 3., -3.])
tensor([ 2., -3.])
tensor([ 3., -2.])
tensor([ 2., -2.])
x = torch.tensor([2.6,-2.7])
print(torch.fmod(x,2)) #作除法取余数
print(torch.remainder(x,2)) #作除法取剩余的部分,结果恒正
tensor([ 0.6000, -0.7000])
tensor([0.6000, 1.3000])
# 幅值裁剪
x = torch.tensor([0.9,-0.8,100.0,-20.0,0.7])
y = torch.clamp(x,min=-1,max = 1)
z = torch.clamp(x,max = 1)
print(y)
print(z)
tensor([ 0.9000, -0.8000, 1.0000, -1.0000, 0.7000])
tensor([ 0.9000, -0.8000, 1.0000, -20.0000, 0.7000])
二,向量运算
向量运算符只在一个特定轴上运算,将一个向量映射到一个标量或者另外一个向量。
#统计值
a = torch.arange(1,10).float()
print(torch.sum(a))
print(torch.mean(a))
print(torch.max(a))
print(torch.min(a))
print(torch.prod(a)) #累乘
print(torch.std(a)) #标准差
print(torch.var(a)) #方差
print(torch.median(a)) #中位数
tensor(45.)
tensor(5.)
tensor(9.)
tensor(1.)
tensor(362880.)
tensor(2.7386)
tensor(7.5000)
tensor(5.)
#指定维度计算统计值
b = a.view(3,3)
print(b)
print(torch.max(b,dim = 0))
print(torch.max(b,dim = 1))
tensor([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
torch.return_types.max(
values=tensor([7., 8., 9.]),
indices=tensor([2, 2, 2]))
torch.return_types.max(
values=tensor([3., 6., 9.]),
indices=tensor([2, 2, 2]))
#cum扫描
a = torch.arange(1,10)
print(torch.cumsum(a,0))
print(torch.cumprod(a,0))
print(torch.cummax(a,0).values)
print(torch.cummax(a,0).indices)
print(torch.cummin(a,0))
tensor([ 1, 3, 6, 10, 15, 21, 28, 36, 45])
tensor([ 1, 2, 6, 24, 120, 720, 5040, 40320, 362880])
tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])
torch.return_types.cummin(
values=tensor([1, 1, 1, 1, 1, 1, 1, 1, 1]),
indices=tensor([0, 0, 0, 0, 0, 0, 0, 0, 0]))
#torch.sort和torch.topk可以对张量排序
a = torch.tensor([[9,7,8],[1,3,2],[5,6,4]]).float()
print(torch.topk(a,2,dim = 0),"n")
print(torch.topk(a,2,dim = 1),"n")
print(torch.sort(a,dim = 1),"n")
#利用torch.topk可以在Pytorch中实现KNN算法
torch.return_types.topk(
values=tensor([[9., 7., 8.],
[5., 6., 4.]]),
indices=tensor([[0, 0, 0],
[2, 2, 2]]))
torch.return_types.topk(
values=tensor([[9., 8.],
[3., 2.],
[6., 5.]]),
indices=tensor([[0, 2],
[1, 2],
[1, 0]]))
torch.return_types.sort(
values=tensor([[7., 8., 9.],
[1., 2., 3.],
[4., 5., 6.]]),
indices=tensor([[1, 2, 0],
[0, 2, 1],
[2, 0, 1]]))
三,矩阵运算
矩阵必须是二维的。类似torch.tensor([1,2,3])这样的不是矩阵。
矩阵运算包括:矩阵乘法,矩阵转置,矩阵逆,矩阵求迹,矩阵范数,矩阵行列式,矩阵求特征值,矩阵分解等运算。
#矩阵乘法
a = torch.tensor([[1,2],[3,4]])
b = torch.tensor([[2,0],[0,2]])
print(a@b) #等价于torch.matmul(a,b) 或 torch.mm(a,b)
tensor([[2, 4],
[6, 8]])
#矩阵转置
a = torch.tensor([[1.0,2],[3,4]])
print(a.t())
tensor([[1., 3.],
[2., 4.]])
#矩阵逆,必须为浮点类型
a = torch.tensor([[1.0,2],[3,4]])
print(torch.inverse(a))
tensor([[-2.0000, 1.0000],
[ 1.5000, -0.5000]])
#矩阵求trace
a = torch.tensor([[1.0,2],[3,4]])
print(torch.trace(a))
tensor(5.)
#矩阵求范数
a = torch.tensor([[1.0,2],[3,4]])
print(torch.norm(a))
tensor(5.4772)
#矩阵行列式
a = torch.tensor([[1.0,2],[3,4]])
print(torch.det(a))
tensor(-2.0000)
#矩阵特征值和特征向量
a = torch.tensor([[1.0,2],[-5,4]],dtype = torch.float)
print(torch.eig(a,eigenvectors=True))
#两个特征值分别是 -2.5+2.7839j, 2.5-2.7839j
torch.return_types.eig(
eigenvalues=tensor([[ 2.5000, 2.7839],
[ 2.5000, -2.7839]]),
eigenvectors=tensor([[ 0.2535, -0.4706],
[ 0.8452, 0.0000]]))
#矩阵QR分解, 将一个方阵分解为一个正交矩阵q和上三角矩阵r
#QR分解实际上是对矩阵a实施Schmidt正交化得到q
a = torch.tensor([[1.0,2.0],[3.0,4.0]])
q,r = torch.qr(a)
print(q,"n")
print(r,"n")
print(q@r)
#矩阵svd分解
#svd分解可以将任意一个矩阵分解为一个正交矩阵u,一个对角阵s和一个正交矩阵v.t()的乘积
#svd常用于矩阵压缩和降维
a=torch.tensor([[1.0,2.0],[3.0,4.0],[5.0,6.0]])
u,s,v = torch.svd(a)
print(u,"n")
print(s,"n")
print(v,"n")
print(u@torch.diag(s)@v.t())
#利用svd分解可以在Pytorch中实现主成分分析降维
tensor([[-0.2298, 0.8835],
[-0.5247, 0.2408],
[-0.8196, -0.4019]])
tensor([9.5255, 0.5143])
tensor([[-0.6196, -0.7849],
[-0.7849, 0.6196]])
tensor([[1.0000, 2.0000],
[3.0000, 4.0000],
[5.0000, 6.0000]])
四,广播机制
Pytorch的广播规则和numpy是一样的:
- 1、如果张量的维度不同,将维度较小的张量进行扩展,直到两个张量的维度都一样。
- 2、如果两个张量在某个维度上的长度是相同的,或者其中一个张量在该维度上的长度为1,那么我们就说这两个张量在该维度上是相容的。
- 3、如果两个张量在所有维度上都是相容的,它们就能使用广播。
- 4、广播之后,每个维度的长度将取两个张量在该维度长度的较大值。
- 5、在任何一个维度上,如果一个张量的长度为1,另一个张量长度大于1,那么在该维度上,就好像是对第一个张量进行了复制。
torch.broadcast_tensors可以将多个张量根据广播规则转换成相同的维度。
a = torch.tensor([1,2,3])
b = torch.tensor([[0,0,0],[1,1,1],[2,2,2]])
print(b + a)
tensor([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
a_broad,b_broad = torch.broadcast_tensors(a,b)
print(a_broad,"n")
print(b_broad,"n")
print(a_broad + b_broad)
tensor([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
tensor([[0, 0, 0],
[1, 1, 1],
[2, 2, 2]])
tensor([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
- Apache+wsgi+flask部署
- “勒索病毒”到底会勒索啥,尽可以做到让全球对之恐惧无奈!
- 解决win10 关键错误开始菜单和cortana无法工作 的问题(转-真的成功了)
- “AS3.0高级动画编程”学习:第二章转向行为(下)
- windows系统中eclipse C开发环境的架设
- 5个酷毙的Python工具
- ”盒模型“之如何防止边框和内边距把元素撑开
- excel中的不同类型图表叠加
- 这几天遇到的关于IE6/sql2008/win2003的奇怪bug
- 基于Web的工作流管理系统的设计与实现
- 这是对position讲解最通俗易懂的版本了。
- 你到底该如何看待比特币?
- OpenApplus小程序容器
- 点名了,最具投资价值的50家物联网企业名单发布
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 3分钟短文 | Laravel 中间件传递数据到控制器
- 3分钟短文 | Laravel 表单验证数组的数据
- 3分钟短文:Laravel 编程中优雅地添加定义常量
- 极客算法训练笔记(四),栈和队列,从实际应用看数据结构
- 微博爬虫出错居然还和网络运营商有关
- 8.深入k8s:资源控制Qos和eviction及其源码分析
- 1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知
- CNN不用乘法? AdderNet和DeepShift论文理解
- 动手构建地铁关系网,实现最短路径查询
- Java并发编程(08):Executor线程池框架
- 用Scipy求解单个正态总体的置信区间
- 架构设计 | 基于电商交易流程,图解TCC事务分段提交
- 用Gaussian做CASSCF计算
- 用Gaussian 16计算振动分辨的紫外-可见吸收光谱
- graylog日志分析系统上手教程