首页 > 其他分享 >pytorch张量运算

pytorch张量运算

时间:2024-08-06 22:05:50浏览次数:16  
标签:dim 运算 tensor torch 矩阵 张量 pytorch Out

pytorch张量运算

2.1 数据操作

  • 深度学习落实到计算表现为矩阵计算
  • pytorch、tensorflow中,计算的基本组件是Tensor。张量即多维数组,是矩阵计算的基本单元。
  • Tensor:张量,一维张量即向量vector,二维张量即 二维数组。张量是n维数组的统称
  • python中有专门进行矩阵计算的库:numpy。pytorch和tensorflow等 和 numpy除了矩阵计算的相似点之外,多了如下额外的功能:
    • 张量支持GPU加速;numpy仅仅支持CPU
    • 张量支持自动微分,可以自动进行求导

2.1.1 创建张量

  • 创建向量 & 改变向量的大小
x = torch.arrange(12, dtype=torch.float)    # 创建vector,除非额外指定,否则其存储于GPU中
x = x.reshape(3,4)                          # 改变tensor的形状
x = torch.zeros((2,3,4))                    # 创建全0向量
x = torch.ones((2,3,4))                     # 创建全1向量
x = torch.randn(3,4)                        # 创建 均值为0,方差为1的标准高斯分布
x = torch.tensor([[2,1,4,3],[1,2,3,4],[4,3,2,1]])  # 将list转化为tensor
x.shape        # 矩阵维度
x.size()       # 张量维度
x.T            # 矩阵转置

查看张量位置

id(x)           #查看tensor x引用地址
x.device        #查看tensor x位于cpu还是gpu上

2.1.2 运算符

  • 按元素计算,下列常见运算均支持:
    • 常用的+、-、x,/ 均支持按照元素计算
    • 求幂运算\(x**y\)
    • 一元运算符 比如 \(torch.exp(x)\)
    • x == y
      • 当x和y相等的时候,逐元素判断是否相等
  • 向量叠加或者连结(concatenate)
    • 多个张量concatenate
    • dim = 0 按照行连接
    • dim = 1 按照列连接
torch.cat((x,y), dim=0)  # 按行叠加
torch.cat((x,y), dim=1)  # 按列叠加

2.1.3 广播机制

  • 广播机制指的是:当两个向量之间进行操作的时候,由于不满足传统条件,numpy 或者 pytorch会自动进行补全
a = torch.arange(3).reshape((3,1))
b = torch.arange(2).reshape((1,2))
a+b

换算成numpy

a=np.arange(3).reshape((3,1))
b=np.arange(2).reshape((1,2))
>>> a
array([[0],
       [1],
       [2]])
>>>  b
array([[0, 1]])

a进行复制列,b进行复制行。将a和b分别变成长度为 3*2的矩阵后,进行想加

>>> a+b
array([[0, 1],
       [1, 2],
       [2, 3]])

2.1.4 索引和切片

张量中的元素可以进行索引操作,和python的数组操作一致

  • 0表示第一个元素;-1表示最后一个元素,可以通过指定范围选择某个范围中的数据 ;
  • 特殊符号":" 表示 沿某一个轴的所有元素
  • 可以利用切片操作对选择范围中的数据进行赋值 X[1,2]=9
>>> x=np.arange(9).reshape(3,3)
>>> x
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> x[0,:]
array([0, 1, 2])

2.1.5 原位计算

矩阵操作某些写法会导致变量重新分配内存,即变量对应的内存地址会发生变化。ex: X = X + Y。但是有时候为了节省内存,我们更希望原位操作。针对矩阵,如下是表示原位操作:

  • 更新矩阵:X[:] = X + Y 或者 X += Y
  • *=

函数id(变量) 用来表示变量引用指向的内存空间的地址,可以用来判断两个变量是否是内存上相同。

>>> X=np.zeros(4).reshape(2,2)
>>> X
array([[0., 0.],
       [0., 0.]])
>>> Y = np.ones(4).reshape(2,2)
>>> id(X)
140502555798464
>>> X += Y
>>> id(X)
140502555798464

注意:Pytorch代码中很多操作都是原位操作,远不止这种写法

函数中,以_结尾的函数,都是原位操作,会改变tensor本身。

比如:y.add_(x),x.copy_(y),x_t(), x.squeeze_(),x.unsqueeze_(),mul_,reshape_()

In [69]: id(a)
Out[69]: 139970692801520
In [70]: a.add_(a)
Out[70]: 
tensor([[ 0.,  4.,  8.],
        [12., 16., 20.]])
In [71]: id(a)
Out[71]: 139970692801520

2.1.6 转换为其他python对象

  • 将pytorch定义的tensor 转换为numpy(底层都一样)
A = X.numpy()
B = torch.tensor(A)  # 进行转换
type(A), type(B)

(numpy.ndarray, torch.Tensor)

  • 将常规张量转化为numpy
a=torch.tensor([2,3])
b=a.numpy()
type(a),type(b)

(torch.Tensor, numpy.ndarray)

  • 将大小为1的张量转换为python标量,使用item 或者 python的内置函数
a = torch.tensor([3.5])
a.item(), float(a), int(a)  # 将张量转化为标量

适用于numpy

>>> a=np.array([1.0])
>>> type(a.item())
<type 'float'>
>>> type(int(a))
<type 'int'>

2.1.7 张量叠加与切割

张量的拼接:几个小张量拼接成一个大的张量。主要的函数有torch.cat,torch.stack

张量的切割:将一个张量切割成几个小的。主要的函数有torch.chunk,torch.split

下面注意介绍:

torch.cat

功能:在给定维度上对张量序列进行叠加操作,所有的张量必须有相同的形状(连接维度除外)或者为空

In [87]: a
Out[87]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])

In [88]: torch.cat((a,a),dim=0)    # 沿行叠加
Out[88]: 
tensor([[0., 1., 2.],
        [3., 4., 5.],
        [0., 1., 2.],
        [3., 4., 5.]])

In [89]: torch.cat((a,a),dim=1)   # 沿列叠加
Out[89]: 
tensor([[0., 1., 2., 0., 1., 2.],
        [3., 4., 5., 3., 4., 5.]])

torch.stack

功能:在一个新的维度上,叠加张量,所有的张量必须是相同的大小

In [92]: a                        # shape: 3*2
Out[92]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])
In [93]: torch.stack((a,a),dim=0)  # shape 2 * 2 * 3
Out[93]: 
tensor([[[0., 1., 2.],
         [3., 4., 5.]],

        [[0., 1., 2.],
         [3., 4., 5.]]])

In [97]: torch.stack((a,a),dim=1) # shape torch.Size([2, 2, 3])
Out[97]: 
tensor([[[0., 1., 2.],
         [0., 1., 2.]],

        [[3., 4., 5.],
         [3., 4., 5.]]])
In [100]: torch.stack((a,a),dim=2) # shape  torch.Size([2, 3, 2])
Out[100]: 
tensor([[[0., 0.],
         [1., 1.],
         [2., 2.]],

        [[3., 3.],
         [4., 4.],
         [5., 5.]]]) 

torch.chunk

用法:torch.chunk(*input*, *chunks*, *dim=0*) → List of Tensors

功能:将一个大的tensor按照不同的维度分割成k个小的tensor。每个数据块都是输入张量的一个视图。

In [4]: a=torch.arange(6).reshape(2,3)
In [5]: a.chunk(3)
Out[5]: (tensor([[0, 1, 2]]), tensor([[3, 4, 5]]))
In [6]: a.chunk(3,dim=0)   # 按照维度为0进行分割
Out[6]: (tensor([[0, 1, 2]]), tensor([[3, 4, 5]]))
In [7]: a.chunk(3,dim=1)   # 按照维度为1进行分割
Out[7]:
(tensor([[0],
         [3]]),
 tensor([[1],
         [4]]),
 tensor([[2],
         [5]]))

torch.split

用法:torch.split(*tensor*, *split_size_or_sections*, *dim=0*)

功能:将张量分成数据块,每个数据块都是原始张量的视图。和 torch.chunk功能相同

  • 当split_size_or_sections 为整数的时候,函数会沿着维度方向尽量切割成长度为plit_size_or_sections的tensor
  • 当split_size_or_sections 是list的时候,函数根据list的设置,沿着设定的维度方向,切割成长度不同的tensor
In [13]: a
Out[13]:
tensor([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]])
In [16]: torch.split(a,2,dim=0)  # 按照行分
Out[16]:
(tensor([[0, 1],
         [2, 3]]),
 tensor([[4, 5],
         [6, 7]]),
 tensor([[8, 9]]))

In [17]: torch.split(a,2,dim=1) # 按照列分
Out[17]:
(tensor([[0, 1],
         [2, 3],
         [4, 5],
         [6, 7],
         [8, 9]]),)     

2.1.8 维度变化

维度变化函数可以直接对tensor的维度进行更改,比如 torch.flatten, torch.squeeze,torch.unsqueeze 。严格意义上来讲,torch.split,torch.cat 还是传统的 聚合函数如torch.sum 也是维度变化。

torch.flatten:扁平化

用法:torch.flatten(*input*, *start_dim=0*, *end_dim=-1*) → [Tensor]

功能:将张量进行进行压扁操作(扁平化操作)。 如果张量是1维,不需要压扁;如果张量是2维,压扁到1维;如果张量是3维,那么可以根据实际的需求进行全部压扁或者部分压扁操作。

输入:

  • start_dim:从那一维度开始flatten
  • end_dim:从那一维度结束flatten的操作

注意:维度dim从0开始,-1表示最后一维。

案例: 二维压一维

In [115]: a=torch.arange(4).reshape(2,2)
In [116]: a
Out[116]: 
tensor([[0, 1],
        [2, 3]])
In [117]: torch.flatten(a)
Out[117]: tensor([0, 1, 2, 3])

三维压二维

In [126]: a=torch.arange(12).reshape(2,2,3)
In [127]: a.flatten(0,1)  # 将第0维消除 变成 4*3
Out[127]: 
tensor([[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11]])

In [128]: a.flatten(0,2)  # 等价于a.flatten, a.flatten(0,-1)直接压到以维
Out[128]: tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

In [129]: a.flatten(1,2) # 将第1维压了,变成 2 * 6 按照什么方向压的
Out[129]: 
tensor([[ 0,  1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10, 11]])

torch.squeeze

用法:torch.squeeze(*input*, *dim=None*) → [Tensor]

功能:squeeze 是挤压,消除,去掉的意思

  • 对维度进行压缩,不设置参数,就是去掉矩阵中所有维数为1的维度。比如矩阵(1*3) 去掉维数为1的,大小变为长度为(3) 的tensor
  • 如果设置dim,那么就是去掉指定维为1的操作 如 矩阵(2*1*2), dim=1,那么输出矩阵就是2*2
  • squeeze 和 unsqueeze对矩阵的数据个数都没有损失

案例

In [138]: a=torch.arange(3).reshape(1,3)
In [139]: b=torch.squeeze(a)
In [140]: b,b.shape
Out[140]: (tensor([0, 1, 2]), torch.Size([3]))

去掉指定维度

In [147]: a=torch.arange(6).reshape(2,1,3)
In [148]: b=torch.squeeze(a,dim=1)
In [149]: b.shape
Out[149]: torch.Size([2, 3])

torch.unsequeeze

用法:torch.unsqueeze(*input*, *dim*) → [Tensor]

功能:在指定位置增加维数为1的维度,比如一个长度为3的向量,在dim=0位置增加一个维度,就是(1*3),在dim=1的位置增加一个维度,张量维度就变为(3*1)

In [151]: a=torch.tensor([1,2,3])
In [152]: b=a.unsqueeze(dim=0)
In [153]: c=a.unsqueeze(dim=1)
In [154]: b.shape,c.shape
Out[154]: (torch.Size([1, 3]), torch.Size([3, 1]))

2.2 矩阵乘法介绍

torch中涉及矩阵乘法函数较多:如

  • torch.mul, torch.multiply,*
  • torch.dot, torch.mv,torch.mm,torch.bmm,torch.matmul

矩阵乘法最基本有两种方式:

  • 点乘:按元素相乘。即两个矩阵中相同位置元素的乘积构成了新矩阵相应位置的元素
  • 叉乘:

2.2.1 点乘

*torch.mul,torch.multiply 三者含义相同。

两个张量的点乘注意:

  • 两个张量维度相同 ,按相同位置相同元素相乘
  • 两个张量维度不同的时候,先通过广播转化为相同

向量和向量

In [29]: a=torch.ones(3,dtype=torch.float)

In [30]: b=torch.arange(3,dtype=torch.float)

In [31]: a*b,torch.mul(a,b)
Out[31]: (tensor([0., 1., 2.]), tensor([0., 1., 2.]))

In [32]: a*b == torch.mul(a,b)
Out[32]: tensor([True, True, True])

向量和矩阵

In [33]: a=torch.arange(6,dtype=torch.float).reshape(2,3)
In [34]: b=torch.ones(3,dtype=torch.float)
In [35]: a
Out[35]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])
In [36]: b
Out[36]: tensor([1., 1., 1.])
In [37]: torch.mul(a,b)
Out[37]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])

矩阵和矩阵

In [41]: a=torch.arange(6,dtype=torch.float).reshape(2,3)
In [42]: a
Out[42]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])
In [43]: b=a
In [45]: torch.mul(a,b)
Out[45]: 
tensor([[ 0.,  1.,  4.],
        [ 9., 16., 25.]])

2.2.2 叉乘

叉乘就是传统的矩阵方法,两个向量的叉乘即两个向量的内积。

向量和向量 torch.dot

In [3]: a=torch.ones(3,dtype=torch.float)
In [4]: b=torch.arange(3,dtype=torch.float)
In [5]: a
Out[5]: tensor([1., 1., 1.])
In [7]: b
Out[7]: tensor([0., 1., 2.])

In [8]: torch.dot(a,b)       # 矩阵点乘
Out[8]: tensor(3.)

向量矩阵 torch.mv

In [11]: a=torch.arange(6,dtype=torch.float).reshape(2,3)
In [12]: b=torch.ones(3,dtype=torch.float)
In [13]: a
Out[13]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])

In [14]: b
Out[14]: tensor([1., 1., 1.])

In [15]: torch.mv(a,b)
Out[15]: tensor([ 3., 12.])

矩阵矩阵 torch.mm

In [16]: a=torch.arange(6,dtype=torch.float).reshape(2,3)

In [17]: b=torch.ones(3,2,dtype=torch.float)

In [18]: a
Out[18]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])

In [19]: b
Out[19]: 
tensor([[1., 1.],
        [1., 1.],
        [1., 1.]])

In [20]: torch.mm(a,b)
Out[20]: 
tensor([[ 3.,  3.],
        [12., 12.]])

批量矩阵乘法 torch.bmm

bmm 表示批量矩阵乘法。能够进行多个矩阵的点乘。bmm分别表示batch(批量)、matrix(矩阵)、matrix(矩阵)的首个字母

In [22]: a=torch.tensor([[[1,2],[3,4]],[[1,2],[3,4]],[[1,2],[3,4]]],dtype=torch.float)

In [23]: b=torch.tensor([[[3,4],[1,2]],[[3,4],[1,2]],[[3,4],[1,2]]],dtype=torch.float)

In [26]: a.shape,b.shape
Out[26]: (torch.Size([3, 2, 2]), torch.Size([3, 2, 2]))

In [27]: torch.bmm(a,b)
Out[27]: 
tensor([[[ 5.,  8.],
         [13., 20.]],

        [[ 5.,  8.],
         [13., 20.]],

        [[ 5.,  8.],
         [13., 20.]]])

**矩阵乘法统一接口 **torch.matmul

torch.matmul 可以用来计算向量与向量,向量与矩阵,矩阵与矩阵,批量矩阵之间的乘法

2.2.3 torch.einsum

可以包含上述所有操作。

torch.einsum('ij->ji',a)  # 矩阵转置
In [48]: torch.einsum('ij->',a)  # 矩阵元素整体求和
Out[48]: tensor(15.)
In [49]: torch.einsum('ij->i',a) # 矩阵元素列求和
Out[49]: tensor([ 3., 12.])

In [50]: torch.einsum('ij->j',a) # 行求和
Out[50]: tensor([3., 5., 7.])

矩阵相乘

In [51]: a
Out[51]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])
In [52]: b = a
In [53]: torch.einsum('ij,jk->ik',a,b.T)  # 矩阵相乘
Out[53]: 
tensor([[ 5., 14.],
        [14., 50.]])

向量矩阵相乘

In [60]: a
Out[60]: 
tensor([[0., 1., 2.],
        [3., 4., 5.]])
In [61]: c
Out[61]: tensor([1., 1., 1.])
In [62]: torch.einsum('ij,j->i',a,c)
Out[62]: tensor([ 3., 12.])

2.3 数据预处理

2.4 自动微分

深度学习需要求导,通过导数明确优化方向。深度学习的工具都支持自动求导,即自动微分。自动微分的实现依赖于 计算图 和 链式求导规则。通过链式求导法则,可以将求导计算分解为一系列有限的可微分算子,而后通过计算图将整个运算过程描述出来

计算图

计算图是用来描述运算过程的有向无环图。计算图主要有两个元素:节点(node) 和边(edge)。

  • 节点表示数据变量,如向量、矩阵,张量

  • 边表示运算,比如加减乘除torch.mul(),torch.mm()torch.div

叶子节点

叶子借点即leaf_node。叶子节点是用户自己构建的变量,反向传播过程即终点对叶子阶段进行求导。

链式求导法则

线索条

  1. https://www.cnblogs.com/leimu/p/14578392.html
    1、pandas 操作

2、数据类型

3、原位操作

4、构建layer

5、自动微分

  • 自动微分:通过计算机求微分
  • 计算图
    • 动态图
    • 静态图
  • 叶子节点
  • 引申:原位计算

6、detach、eval

标签:dim,运算,tensor,torch,矩阵,张量,pytorch,Out
From: https://www.cnblogs.com/douniwanli/p/18344412

相关文章

  • 逻辑运算符
    1.与(&&)两个变量必须一致(都是true),否则否则输出的就是false2.或(||)我或者你,其中一个变量是true,那么输出的值就一定是true3.非(!())把括号里的值进行反转,比如括号是真,则输出为假......
  • pytorch实现神经网络图像分类
    Tensor在PyTorch中,最核心的数据结构就是Tensor了,可以认为Tensor与Numpy中的ndarrays非常类似,但是Tensor可以使用GPU加速而ndarrays不可以。在pytorch进行GPU运算iftorch.cuda.is_available():x=x.cuda()y=y.cuda()print(x+y)numpy与pytorch互相转换importtorch......
  • 使用pytorch实现数字识别器
    前言:本篇文章是关于数字识别器的识别和卷积神经网络的应用。若对卷积神经网络不熟悉,可参考文章:卷积神经网络关于深度学习的一些代码及实战,可参考深度学习基础(github)下面我们尝试用PyTorch搭建一个卷积神经网络,并用它来解决手写数字识别的问题。1、数据准备#torchvisio......
  • pytorch OSError: [WinError 1114] 动态链接库(DLL)初始化例程失败”原因分析
    动态链接库失败“OSError:[WinError1114]动态链接库(DLL)初始化例程失败。Errorloading"cublas64_12.dll"oroneofitsdependencies”原因分析出错情况:在importtorch中直接被抛出异常环境探讨【问题复现】:因为使用了新的torch-gpu环境【name称为torch】,固怀疑......
  • 监控系统原理揭秘-数据运算篇
    一、监控系统概览监控系统在现代技术环境中扮演着至关重要的角色。运营同学每天检查自己的活动数据,研发人员每天检查系统各项指标是否正常,这些工作都少不了监控系统的身影。通常来讲,监控系统包括数据采集、数据计算、数据存储、数据可视化及监控预警等功能。本文主要介绍数据计算......
  • pytorch 模型加载和保存
    模型加载torch.load(f,map_location=None,pickle_module=<module'pickle'from'/opt/conda/lib/python3.6/pickle.py'>,**pickle_load_args) map_location适用于修改模型能在gpu上运行还是cpu上运行。一般情况下,加载模型,主要用于预测新来的一组样本。预测的主要流程包......
  • 算术运算符里的特殊运算符
    1.++(自加)给一个数加1自加分为两种,一个是++a,另一个是a++a++:先给数赋值,然后再给a加1++a:先给a加1,然后再给数赋值2.--(自减)给一个数减1......
  • 浮点数的加减运算
    浮点数的加减运算如果采用大阶码向小阶码看齐的原则,则尾数需要左移,最高有效位被移出,导致结果出错C语言中的浮点数据类型......
  • 运算符
    1.算术运算符强转以后:2.算术运算符的一些默认3.逻辑运算符4.取余......
  • pytorch学习笔记5 tensor 广播broadcasting
    不同shape直接加减,系统会自动做broadcasting操作先右对齐(小维度对齐)比如:Featuremaps:[4,32,14,14]Bias:[32,1,1]=>][1,32,1,1]=>[4,32,14,14]做到与Featuremaps的shape相同,才能进行相加广播扩展的时候只是做这样的操作,并不实质拷贝数据,以节省内存空间可广播的条件......