首页 > 其他分享 >4-2张量的数学运算

4-2张量的数学运算

时间:2024-03-10 17:56:24浏览次数:21  
标签:randn tensor torch 矩阵 张量 数学 print 运算

张量的数学运算主要有:标量运算,向量运算,矩阵运算,以及使用非常强大而灵活的爱因斯坦求和函数torch.einsum进行任意维的张量运算。

此外我们还会介绍张量运算的广播机制:

本篇文章内容如下:

  • 标量运算
  • 向量运算
  • 矩阵运算
  • 任意维张量运算
  • 广播机制
import torch

print("torch.__version__="+torch.__version__)
"""
torch.__version__=2.1.1+cu118
"""

1.标量运算(操作的张量至少是0维)

张量的数学运算符可以分为标量运算符、向量运算符、以及矩阵运算符。

加减乘除乘方,以及三角函数,指数,对数等常见函数,逻辑比较运算符等都是标量运算符。

标量运算符的特点是对张量实施逐元素运算。

有些标量运算符对常用的数学运算符进行了重载。并且支持类似numpy的广播特性。

import torch
import numpy as np

a = torch.tensor(1.0)
b = torch.tensor(2.0)
a+b
"""
tensor(3.)
"""

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.]])
"""

torch.div(a, b, rounding_mode='floor')  # 地板除法
"""
tensor([[ 0.,  0.],
        [-1.,  0.]])
"""

a>=2  # torch.ge(a, 2)
"""
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])
"""

relu = lambda x: x.clamp(min=0.0)
relu(torch.tensor(5.0))
"""
tensor(5.)
"""

2.向量运算(原则上操作的张量至少是一维张量)

向量运算符只在一个特定轴上运算,将一个向量映射到一个标量或者另外一个向量

# 统计值
a = torch.arange(1, 10).float().view(3, 3)

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 = torch.arange(1, 10).float().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))
print(torch.topk(a, 2, dim=1))
print(torch.sort(a, dim=1))
"""
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]]))
"""

3.矩阵运算(操作的张量至少是二维张量)

矩阵必须是二维的。类似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.randn(5, 5, 6)
b = torch.randn(5, 6, 4)
(a@b).shape
"""
torch.Size([5, 5, 4])
"""

# 矩阵转置
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(a.det())  # torch.det(a)
"""
tensor(-2.)
"""

# 矩阵特征值和特征向量
a = torch.tensor([[1.0, 2], [-5, 4]], dtype=torch.float)
print(torch.linalg.eig(a))
"""
torch.return_types.linalg_eig(
eigenvalues=tensor([2.5000+2.7839j, 2.5000-2.7839j]),
eigenvectors=tensor([[0.2535-0.4706j, 0.2535+0.4706j],
        [0.8452+0.0000j, 0.8452-0.0000j]]))
"""

# 矩阵QR分解,将一个方阵分解为一个正交矩阵q和上三角矩阵r
# QR分解实际上是对矩阵q实施Schmidt正交化得到q
a = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
q, r = torch.linalg.qr(a)
print(q)
print(r)
print(q@r)
"""
tensor([[-0.3162, -0.9487],
        [-0.9487,  0.3162]])
tensor([[-3.1623, -4.4272],
        [ 0.0000, -0.6325]])
tensor([[1.0000, 2.0000],
        [3.0000, 4.0000]])
"""

# 矩阵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.linalg.svd(a)

print(u)
print(s)
print(v)

import torch.nn.functional as F

print([email protected](torch.diag(s), (0, 0, 0, 1))@v.t())  # 左右上下,下侧填充0
"""
tensor([[-0.2298,  0.8835,  0.4082],
        [-0.5247,  0.2408, -0.8165],
        [-0.8196, -0.4019,  0.4082]])
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]])
"""

4.任意维张量运算(torch.einsum)

如果问pytorch中最强大的一个数学函数是什么?

我会说是torch.einsum:爱因斯坦求和函数。

它几乎是一个"万能函数":能实现超过一万种功能的函数。

不仅如此,和其它pytorch中的函数一样,torch.einsum是支持求导和反向传播的,并且计算效率非常高。

einsum 提供了一套既简洁又优雅的规则,可实现包括但不限于:内积,外积,矩阵乘法,转置和张量收缩(tensor contraction)等张量操作,熟练掌握 einsum 可以很方便的实现复杂的张量操作,而且不容易出错。

尤其是在一些包括batch维度的高阶张量的相关计算中,若使用普通的矩阵乘法、求和、转置等算子来实现很容易出现维度匹配等问题,若换成einsum则会特别简单。

套用一句深度学习paper标题当中非常时髦的话术,einsum is all you needed

标签:randn,tensor,torch,矩阵,张量,数学,print,运算
From: https://www.cnblogs.com/lotuslaw/p/18064488

相关文章

  • 位运算 --20240310
    位运算在linux内核或裸驱中使用十分常见,下面是两种使用方式在此记录: 对寄存器进行操作:举个例子,1、清除bit8-bit10,并将bit8-bit10设置为0x2reg=(reg&(~(0x7<<8))|(0x2<<8));2、将bit4置一和置零reg=(reg&(~(0x1<<4)))|(0x0<<4);//bit4置零reg=......
  • 第04章_运算符
    第04章_运算符讲师:尚硅谷-宋红康(江湖人称:康师傅)官网:http://www.atguigu.com1.算术运算符算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行加(+)、减(-)、乘(*)、除(/)和取模(%)运算。1.加法与减法运算符mysql>SELECT100,100+0,100-0,1......
  • 数学
    组合数学\(A_n^m=\frac{n!}{(n-m)!}\)表示在\(n\)个不同的元素中选出\(m\)个元素的排列数\(C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!}\)表示在\(n\)个不同的元素中选出\(m\)个元素的方案数二项式定理:\((a+b)^n=\sumC_n^ia^ib^{n-i}\),\(2^n=\sumC_n^i\)扩展:......
  • .Net 中带有 ? 的运算符
    //带?的表达式//1.三元表达式//2.??双问号//obj1??obj2如果obj1为空(null)返回obj2//ConfiguretheHTTPrequestpipeline.//3.让值类型变成可以为空的类型inta=0;int?x=null;//?说明x可以为null//等价于Nullable<int>y=null......
  • 2024哈佛-麻省数学竞赛(HMMT)2月锦标赛 团体赛第9题
    [55](题目分数)在一个200*200的网格表的每个单元格上放置一辆汽车,它面向四个基本方向之一。在一步操作中,选择一辆前面没有汽车立即挡住的汽车,并将其向前滑动一个单元格。如果一步操作会导致汽车离开网格,则将该汽车移除。对初始放置方法的要求是,一定存在一系列操作,最终可以将所有汽......
  • 数学吧观察日记
    OI学久了,提升一下数学素养。3.8.1(几何)\(\color{green}\bigstar\)一万年没做过几何了,有点难度。注意到\(P\)是中点,连\(BD,DF\)然后分别做中点,就可以简单构造全等三角形了。偷个图:......
  • 【数学】概率&期望小总结
    开篇碎碎念好久没有更博客了(咸鱼瘫瘫),到现在还欠了最近的几场cf没补题(呜呜呜欠债upup),由于一道很显然的期望没有开出来所以最近补了几道期望,来总结一下友情指路:sshwy的期望洛谷题单相关基础概念首先是概率:常用P(X)表示X发生的概率,等价于X发生的可能性在全部事件的占比。......
  • 4-1张量的结构操作
    本篇我们介绍张量的结构操作。张量结构操作主要包括:张量创建、索引切片、维度变换、合并分割。1.创建张量张量创建的许多方法和numpy中创建array的方法很像。importnumpyasnpimporttorcha=torch.tensor([1,2,3],dtype=torch.float)print(a)"""tensor([1.,......
  • C++入门编程----C++运算符(8)
    什么是运算符运算符是让程序执行特定的数学或逻辑操作的符号,用来表示针对数据的特定操作,也称之为操作符。C++运算符分别有算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符、移位运算符、sizeof运算符、三目运算符、逗号运算符和域解析运算符。算术运算符C++中的算术......
  • 位运算
    说明参考灵神的题单刷题总结一些技巧判断一个数二进制形式下第i位是否为1可以将该数看作一个集合,该集合存储的是二进制表示下为1的下标。//n>>i后的最低位表示n的第i位if(n>>i&1){ if(i%2)奇数++ else偶数++}2的幂或者4的幂2的幂整个二进制形式的数只有一个......