Loading

PyTorch——Tensor的相关概念及操作

Tensor的概念

说起张量(tensor)就不得不说他和scalar、vertor、matrix之间的关系了,直接上图:

标量(scalar):只有大小概念,没有方向的概念。通过一个具体的数值就能表达完整。比如:重量、温度、长度、提及、时间、热量等都数据标量。

向量(vector):物理学上也叫矢量,指由大小和方向共同决定的量(跟「标量」相区别)。向量主要有2个维度:大小、方向。比如:力、速度等

矩阵(matrix):(学过线性代数的都知道,可参见之前的线代笔记

张量(tensor):一个多维数组,它是标量、向量、矩阵的高位扩展 

当下主流的深度网络学习框架是PyTorch和Tensorflow。

对于这两个框架而言,我只想用一句代码来阐述我心中的杂乱: 

Import torch as tf               

但是,我还是选择了PyTorch( ^_^ /\  ~_~ )

tensor,是PyTorch中最基础的数据类型,也是进行数据存储和运算的基本单元。

数组array这个概念,数组是类似于列表的高阶对象,是有序的元素序列。

Tensor在PyTorch的地位相当于Array在Numpy中地位。

实质上Pytorch将Numpy的Array包装成Tensor,为其定义了各种各样的运算方法和函数

以至于处理tensor的时候,觉得自己在调用Numpy和Pandas这两个包处理。

Tensor的属性

每一个tensor都有三个属性:torch.dtype,torch.device,torch.layout.

torch.dtype

Pytorch拥有12个不同的数据类型。

 tensor类型 相关代码

>>> float_tensor = torch.ones(1, dtype=torch.float)
>>> double_tensor = torch.ones(1, dtype=torch.double)
>>> complex_float_tensor = torch.ones(1, dtype=torch.complex64)
>>> complex_double_tensor = torch.ones(1, dtype=torch.complex128)
>>> int_tensor = torch.ones(1, dtype=torch.int)
>>> long_tensor = torch.ones(1, dtype=torch.long)
>>> uint_tensor = torch.ones(1, dtype=torch.uint8)
>>> double_tensor = torch.ones(1, dtype=torch.double)
>>> bool_tensor = torch.ones(1, dtype=torch.bool)
>>> long_zerodim = torch.tensor(1, dtype=torch.long)
>>> int_zerodim = torch.tensor(1, dtype=torch.int)

>>> torch.add(5, 5).dtype
torch.int64
>>> (int_tensor + 5).dtype
torch.int32
>>> (int_tensor + long_zerodim).dtype
torch.int32
>>> (long_tensor + int_tensor).dtype
torch.int64
>>> (bool_tensor + long_tensor).dtype
torch.int64
>>> (bool_tensor + uint_tensor).dtype
torch.uint8
>>> (float_tensor + double_tensor).dtype
torch.float64
>>> (complex_float_tensor + complex_double_tensor).dtype
torch.complex128
>>> (bool_tensor + int_tensor).dtype
torch.int32
>>> torch.add(long_tensor, float_tensor).dtype
torch.float32

torch.device

 由于pytorch可以在Gpu上运行tensor的相关操作。

torch.device是一个对象,表示正在或将要分配 torch.tensor的设备。

torch.device一半可选的内容有 cpu,cuda或者一些设备类型的可选设备序号

>>> torch.device('cuda:0')
device(type='cuda', index=0)

>>> torch.device('cpu')
device(type='cpu')

>>> torch.device('cuda')  # current cuda device
device(type='cuda')
>>> torch.device('cuda', 0)
device(type='cuda', index=0)

>>> torch.device('cpu', 0)
device(type='cpu', index=0)

torch.layout

torch.layout 是表示 torch.tensor 的内存布局的对象。目前,torch.tensor支持torch.strided(密集张量)和sparse_coo(稀疏的COO张量)。

 

stride()方法其实指的就是,tensor每个维度变化1在实际物理存储空间变化的大小。

>>> x = torch.tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> x.stride()
(5, 1)

>>> x.t().stride()
(1, 5)

 Tensor的创建与访问

Tensor的创建方式

  • 可以根据数据、元组、NumPy的ndarray、标量和其他类型,来构建tensor。方法有:torch.tensor()、torch.ones()、torch.zeros()、torch.from_array()...
  • 也可以从一些分布中采样构建新的张量:torch.arange()、torch.range()、torch.rand()、torch.randn()、torch.normal()...
  • 当然也有一些比较特殊的搭建:torch.eye()用于构建一个对角矩阵

Tensor的访问方式

  • 当tensor是标量或者一维数据的时候,可以使用torch.item()访问
  • 当tensor是多维数据的时候,可以使用索引的方式,用法类似于a[:,0,0]
  • 当然我们也可以使用掩膜的方式,固定的访问一些我们想要的数据。
X = torch.randn((2,3))
mask = torch.randn((2,3))>0
X1 = X[mask]
X2 = torch.masked_select(X,mask)

  •  还有条件选择这种不错的方式,也是一个值得推荐的方式。
x = torch.randn(1, 3)
y = torch.randn(1, 3)
z = torch.where(x>y,x,y)

Tensor的简单操作

常用数学运算

  • torch.add():加法
  • torch.mul():乘法
  • torch.div():除法
  • torch.abs():tensor内每个元素取绝对值
  • torch.round():tensor内每个元素取整数部分
  • torch.frac():tensor内每个元素取小数部分
  • torch.log():tensor内每个元素取对数
  • torch.pow():tensor内每个元素取幂函数
  • torch.exp():tensor内每个元素取指数
  • torch.sigmoid():tensor内每个元素取sigmoid函数值
  • torch.mean():tensor所有元素的均值
  • torch.norm():tensor所有元素的范数值
  • torch.prod():tensor所有元素积
  • torch.sum():tensor所有元素和
  • torch.max():tensor所有元素最大值
  • torch.min():tensor所有元素最小值

注意:例如add()这类函数一般都是会返回一直tensor值的,但是add_()这类加了下划线的方法是在tensor的原空间处理的,会覆盖之前的值

同样也可以是用以下方式直接处理

  1. 加 tensor1 + tensor2;
  2. 减 tensor1 - tensor2;
  3. 乘 tensor1 * tensor2;
  4. 除 tensor1 / tensor2;
  5. 内积 tensor1 @ tensor2;
  6. 幂运算 tensor1 ** n

线性代数运算

  • torch.dot():向量内积运算
  • torch.mv():矩阵与向量的乘法
  • torch.mm():矩阵乘法
  • torch.eig():方阵的特征值和特征向量
  • torch.inverse():方阵的逆
  • torch.ger():两个向量的张量积

Tensor连接、分片、变形

  • torch.cat():多个tensor的拼接
  • torch.reshape()\torch.view():返回一个张量,其数据和元素数量与输入相同,但具有指定的形状
  • torch.transpose()\torch.t():指定tensor的两个维度进行转置,torch.t()方法只适用与二维tensor
  • torch.squeeze()/unsqueeze():tensor对于张量中大小为1的维度的压缩与扩张
  • torch.permute():返回维度排列后的原始张量输入的视图。

说到计算就不得不说,tensor 的一种计算机制,BroadCasting。在一定条件下,他会使维度不同、维度大小同的tensor完成数学计算

以A+B为例,Broadcasting的过程如下: 从A,B的最后一个维度开始匹配长度,如果该维度长度一致,则匹配前一个维度。如果某个维度的长度不一致,并且两者长度都>1,那么维度不匹配,无法进行运算,如果有一个长度维1,那么就对该维度进行扩展(广播),扩展后的两个维度长度一致。依次类推直到第一个维度。如果两个张量维度不同,则在第0维进行升维并做广播。

粗略的来说,就是利用squeeze()方法使低维的数据升到高维的数据,再利用cat()方法拼接成同样的大小。(前提是,该维度长度为1,或者没有维度才可以)

下面这张图就可以很清晰的表达BroadCasting的效果。

 

 

posted @ 2021-12-13 16:15  Christopher·阳  阅读(1257)  评论(0编辑  收藏  举报