欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

『PyTorch』Tensor

程序员文章站 2022-07-14 20:17:55
...

1. 张量

『PyTorch』Tensor

2. Variable类型(PyTorch 0.4之前)

Variabletorch.autograd中的数据类型,主要用于封装Tensor,进行自动求导

『PyTorch』Tensor

  • data
    被包装的张量
  • grad
    data的梯度
  • grad_fn
    创建Tensor的function,是自动求导的关键
  • requires_grad
    指示是否需要梯度,True表示需要计算梯度,False表示不需要计算梯度
  • is_leaf
    指示是否是叶子结点(张量)

3. Tensor类型(PyTorch 0.4之后)

Variable从PyTorch 0.4之后开始并入Tensor,多了3个主要属性

『PyTorch』Tensor

  • dtype
    张量的数据类型,如torch.FloatTensortorch.cuda.FloatTensor
  • shape
    张量的形状,类似NumPy数组的shape
  • device
    张量所在设备,GPU/CPU,是加速的关键

4. 创建Tensor

4.1 直接创建

4.1.1 torch.tensor()

  • 函数
torch.tensor(data, dtype=None, device=None,requires_grad=False, pin_memory=False)
  • 功能
    从data创建Tensor

  • 参数

    • data:数据,可以是list,numpy的ndarray
    • dtype:数据类型,默认与data一致
    • device:所在设备,GPU/CPU
    • requires_grad:是否需要计算梯度
    • pin_memory:是否存于锁业内存,通常就是False,与转换效率有关
import torch
import numpy as np

# 通过torch.tensor()创建张量

ary = np.ones((3,3))
print(f"ndarray的数据类型:{ary.dtype}")

t = torch.tensor(ary)
print(t)

s = torch.tensor(ary,device="cuda")
print(s)

输出结果:

ndarray的数据类型:float64
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], device=‘cuda:0’, dtype=torch.float64)

4.1.2 torch.from_numpy()

  • 函数
torch.from_numpy(ndarray)
  • 功能
    从NumPy创建Tensor

从torch.from_numpy创建的Tensor与原ndarray共享内存,当修改其中一个数据,另一个也将会被改动

import torch
import numpy as np

# 通过torch.from_numpy()创建张量
ary = np.random.randint(0, 20, size=9).reshape(3, 3)

t = torch.from_numpy(ary)

print(f"ndarray的数据类型为:{ary.dtype}")
print(t)

输出结果:

ndarray的数据类型为:int32
tensor([[13, 17, 3],
[18, 11, 1],
[17, 8, 4]], dtype=torch.int32)

4.2 依据数值创建

4.2.1 torch.zeros()

  • 函数
torch.zeros(*size,out=None,dtype=None,layout=torch.strided,device=None,requires_grad=False)
  • 功能
    根据size创建全0张量
  • 参数
    • size:张量的形状
    • out:输出的张量
    • layout:内存中布局形式,有strided,sparse_coo等,一般默认值
import torch
import numpy as np

# 通过torch.zeros()创建全0张量

out_t = torch.tensor([1])

t = torch.zeros((3,3),out=out_t)

print(t)
print(out_t)
print(id(t)==id(out_t))

输出结果:

tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
True

4.2.2 torch.zeros_like()

  • 函数
torch.zeros_like(input,dtype=None,layout=None,device=None,requires_grad=False)
  • 功能
    根据input的形状创建全0张量
  • 参数
    • input:张量,创建的全0张量形状与此一致

4.2.3 torch.ones()

参考torch.zeros()

4.2.4 torch.ones_like()

参考torch.zeros_like()

4.2.5 torch.full()

  • 函数
torch.full(size,fill_value,out=None,dtype=None,
           layout=torch.strided,device=None,requires_grad=False)
  • 功能
    根据fill_value的值创建shape为size的张量

4.2.6 torch.full_like()

方法类似

4.2.7 torch.arrange()

  • 函数
torch.arange(end, *, out=None, dtype=None, device:=None, requires_grad=False)

torch.arange(start, end, *, out=None, dtype=None, device=None, requires_grad=False)

torch.arange(start, end, step, *, out=None, dtype=None, device=None, requires_grad=False)
  • 功能
    创建等差的一维张量

注意区间为[start,end)[start, end)

4.2.8 torch.linspace()

  • 函数
torch.linspace(start, end, steps=100, *, out=None, dtype=None, 
               layout=strided, device: =None, requires_grad=False)
  • 功能
    创建均分的一维张量,数值区间为[start,end][start, end],steps是该张量元素个数,步长要自己算

4.2.9 torch.logspace()

  • 函数
torch.logspace(start, end, steps=100, base=10.0, *, out=None, 
               dtype=None, layout=strided, device=None, requires_grad=False)
  • 功能
    创建对数均分的一维张量,数值区间为[basestart,baseend]\displaystyle\Big[{base}^{start}, {base}^{end}\Big],steps是该张量元素个数,步长要自己算
import torch

t = torch.logspace(2, 6, 5, base=2)
print(t)

输出结果:

tensor([ 4., 8., 16., 32., 64.])

从这可以看出,是把 [start,end][start, end] 进行等分,得到指数序列 L,然后,输出的Tensor每个元素是 baseL[i]{base}^{L[i]}

4.2.10 torch.eye()

  • 函数
torch.eye(n, m, *, out=None, dtype=None, layout=strided, device=None, requires_grad=False) 

torch.eye(n, *, out=None, dtype=None, layout=strided, device=None, requires_grad=False)
  • 功能
    创建单位矩阵(二维张量),默认方阵
import torch

t = torch.eye(4)
print(t)

s = torch.eye(3, 4)
print(s)

输出结果:

tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])

tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])

4.3 依据概率分布创建

4.3.1 torch.normal()

  • 均值和标准差都是标量

    • 函数

      torch.normal(mean, std, size, *, generator=None, out=None, 
                   dtype=None, layout=strided, device=None, requires_grad=False)
      
    • 功能
      根据均值mean,标准差std采样,返回的张量shape为size

      t_normal = torch.normal(0, 1., size=(2,3))
      
      print(t_normal)
      

      输出结果:

      tensor([[ 0.4256, -0.6451, -0.2785],
      [-0.7766, -1.0419, -0.0259]])

  • 均值和标准差都是张量

    • 函数

      torch.normal(mean, std, *, generator=None, out=None) 
      
    • 功能
      返回张量,mean和std的shape必须一致,且返回结果的shape和mean以及std的shape一致,返回结果对应位置的元素值,是根据mean和std的对应位置的值作为均值和标准差采样的

      mean = torch.arange(1, 5, dtype=torch.float)
      std = torch.arange(1, 5, dtype=torch.float)
      t_normal = torch.normal(mean, std)
      print(f"mean:{mean}")
      print(f"std:{std}")
      print(t_normal)
      

      输出结果:

      mean:tensor([1., 2., 3., 4.])
      std:tensor([1., 2., 3., 4.])
      tensor([1.6039, 3.3902, 5.8297, 1.5644])

  • 均值和标准差有一个是张量
    标量会做broadcast处理,参考都是张量的情况

4.3.2 torch.randn()

  • 函数

    torch.rand(size, *, generator=None, out=None, 
                 dtype=None, layout=strided, device=None, requires_grad=False)
    
  • 功能
    [0,1)[0, 1)均匀分布中采样,返回shape为size的张量

    torch.rand_like()参考前面类似的like函数

4.3.3 torch.randint()

  • 函数

    torch.randint(low, high, size, *, generator=None, out=None, 
                 dtype=None, layout=strided, device=None, requires_grad=False)
    
    torch.randint(high, size, *, generator=None, out=None, 
                 dtype=None, layout=strided, device=None, requires_grad=False)
    
  • 功能
    [low,high)[low, high)均匀分布中采样,返回shape为size的张量,第二种定义从[0,high)[0,high)均匀分布采样

    torch.randint_like()参考前面类似的like函数

4.3.4 torch.randperm()

  • 函数

    torch.randperm(n, *, generator, out=None, dtype=None, 
                   layout=strided, device=None, requires_grad=False)
    
  • 功能
    生成从 00n1n-1 的随机排列

4.3.5 torch.bernoulli()

  • 函数

    torch.bernoulli(p, *, generator=None, out=None)
    
  • 功能
    pp 为概率,生成伯努利分布(010-1分布,两点分布)

5. 张量的常用操作

有些方法是可以直接用Tensor对象.方法

5.1 张量的拼接与切分

5.1.1 torch.cat()

  • 函数

    torch.cat(tensors, dim=0, *, out)
    
  • 功能
    将张量按照指定维度拼接

    import torch
    
    t = torch.ones(2, 3)
    
    t_0 = torch.cat([t, t], dim=0)
    t_1 = torch.cat([t, t], dim=1)
    t_2 = torch.cat([t, t, t], dim=1)
    
    print(t)
    print(t_0)
    print(t_1)
    print(t_2)
    

    输出结果:

    tensor([[1., 1., 1.],
    [1., 1., 1.]])

    tensor([[1., 1., 1.],
    [1., 1., 1.],
    [1., 1., 1.],
    [1., 1., 1.]])

    tensor([[1., 1., 1., 1., 1., 1.],
    [1., 1., 1., 1., 1., 1.]])

    tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1.],
    [1., 1., 1., 1., 1., 1., 1., 1., 1.]])

5.1.2 torch.stack()

  • 函数

    torch.stack(tensors, dim=0, *, out=None)
    
  • 功能
    在新创建的维度dim上进行拼接,用到时先实验一下,别想当然,记不住的

    import torch
    
    t = torch.ones(2, 3)
    
    t_stack_0 = torch.stack([t, t, t, t], dim=0)
    t_stack_1 = torch.stack([t, t, t, t], dim=1)
    t_stack_2 = torch.stack([t, t, t, t], dim=2)
    
    print(f"t 的shape:{t.shape}")
    print(f"t_stack_0的shape:{t_stack_0.shape}")
    print(f"t_stack_1的shape:{t_stack_1.shape}")
    print(f"t_stack_2的shape:{t_stack_2.shape}")
    

    输出结果:

    t 的shape:torch.Size([2, 3])
    t_stack_0的shape:torch.Size([4, 2, 3])
    t_stack_1的shape:torch.Size([2, 4, 3])
    t_stack_2的shape:torch.Size([2, 3, 4])

5.1.3 torch.chunk()

  • 函数

    torch.chunk(chunks, dim=0)
    
  • 功能
    将张量按维度dim进行平均切分,返回张量列表
    【注意】若不能整除,最后一个张量小于其他张量

    import torch
    
    t = torch.ones(2, 7)
    
    tensors = torch.chunk(t, dim=1, chunks=3)
    
    for index, tensor in enumerate(tensors):
        print(f"第{index + 1}个张量:{tensor},shape is {tensor.shape}")
    
    

    输出结果:

    第1个张量: tensor([[1., 1., 1.],
    [1., 1., 1.]]),shape is torch.Size([2, 3])
    第2个张量: tensor([[1., 1., 1.],
    [1., 1., 1.]]),shape is torch.Size([2, 3])
    第3个张量: tensor([[1.],
    [1.]]),shape is torch.Size([2, 1])

5.1.4 torch.split()

  • 函数

    torch.split(tensor, split_size_or_sections, dim=0)
    
  • 功能
    将张量按维度dim进行切分,返回张量列表

  • 参数

    • split_size_or_sections
      • int时,表示每一份的长度
      • list时,按list元素大小切分(元素和要和切割的维度上元素数一致)
    import torch
    
    t = torch.ones(2, 5)
    
    tensors = torch.split(t, 3, dim=1)
    tensors1 = torch.split(t, [2, 1, 2], dim=1)
    
    for index, tensor in enumerate(tensors):
        print(f"第{index + 1}个张量:{tensor},shape is {tensor.shape}")
    
    for index, tensor in enumerate(tensors1):
        print(f"第{index + 1}个张量:{tensor},shape is {tensor.shape}")
        
    

    输出结果:

    第1个张量: tensor([[1., 1., 1.],
    [1., 1., 1.]]),shape is torch.Size([2, 3])
    第2个张量: tensor([[1., 1.],
    [1., 1.]]),shape is torch.Size([2, 2])

    第1个张量: tensor([[1., 1.],
    [1., 1.]]),shape is torch.Size([2, 2])
    第2个张量: tensor([[1.],
    [1.]]),shape is torch.Size([2, 1])
    第3个张量: tensor([[1., 1.],
    [1., 1.]]),shape is torch.Size([2, 2])

5.2 张量的索引

5.2.1 torch.index_select()

  • 函数

    torch.index_select(tensor, dim, index, *, out=None)
    
  • 功能
    在维度dim上,按照index索引数据,返回搜索结果拼接而成的张量
    【注意】index必须是long类型的一维Tensor

    import torch
    
    t = torch.randint(0, 9, size=(3, 3))
    idx = torch.tensor([0, 2], dtype=torch.long)  # 作为索引,这里必须是long
    t_select = torch.index_select(t, dim=1, index=idx)
    
    print(t)
    print(t_select)
    

    输出结果:

    tensor([[4, 7, 2],
    [7, 3, 7],
    [7, 5, 7]])
    tensor([[4, 2],
    [7, 7],
    [7, 7]])

5.2.2 torch.mask_select()

  • 函数

    torch.masked_select(tensor, mask, *, out=None)
    
  • 功能
    按mask中的True进行索引,返回一维张量

    import torch
    
    t = torch.randint(0, 9, size=(3, 3))
    mask = t.ge(5)  # ge:>= , gt:> ,  le  ,  lt
    t_select = torch.masked_select(t, mask)
    
    
    print(t)
    print(mask)
    print(t_select)
    

    输出结果:

    tensor([[0, 4, 8],
    [2, 7, 5],
    [6, 7, 6]])

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

    tensor([8, 7, 5, 6, 7, 6])

5.3 张量变换

5.3.1 torch.reshape()

  • 函数

    torch.masked_select(tensor, mask, *, out=None)
    
  • 功能
    重塑形状,但是元素个数要对的上

    import torch
    
    t = torch.randint(0, 9, size=(3, 3))
    
    print(t)
    
    t = t.reshape(1, -1)
    s = torch.reshape(t, (1, -1))
    
    print(t)
    print(s)
    

    输出结果:

    tensor([[3, 4, 8],
    [7, 8, 1],
    [1, 3, 0]])
    tensor([[3, 4, 8, 7, 8, 1, 1, 3, 0]])
    tensor([[3, 4, 8, 7, 8, 1, 1, 3, 0]])

  • 注意——内存共享

    import torch
    
    t = torch.randint(0, 9, size=(3, 3))
    
    print(t)
    
    s = t.reshape(1, -1)
    s[0][2] = 100  # 内存共享,更改它也会影响原Tensor
    
    print(s)
    print(t)
    

    输出结果:

    tensor([[5, 3, 7],
    [0, 4, 5],
    [3, 0, 7]])

    tensor([[ 5, 3, 100, 0, 4, 5, 3, 0, 7]])

    tensor([[ 5, 3, 100],
    [ 0, 4, 5],
    [ 3, 0, 7]])

5.3.2 torch.transpose()

  • 函数

    torch.transpose(dim0, dim1)
    
  • 功能
    交换两个维度,比如一般卷积神经网络输入channel×height×width,交换0和1维,然后交换1和2维,得到height×width×channel

    import torch
    
    t = torch.randint(0, 24, size=(2, 3, 4))
    
    print(t.shape)
    
    s = t.transpose(0, 2)
    
    print(s.shape)
    

    输出结果:

    torch.Size([2, 3, 4])
    torch.Size([4, 3, 2])

5.3.3 torch.t()

  • 功能:转置二维张量

5.3.4 torch.squeeze()

  • 功能

    压缩长度为1的轴

    • 不输入参数,则移除所有长度为1的维度
    • 若指定维度,则当且仅当该维度长度为1时,可以删除该维度

5.3.5 torch.unsqueeze()

  • 功能
    扩充张量维度

    import torch
    
    t = torch.ones(2, 3, 4)
    
    print(t.shape)
    
    s = t.unsqueeze(2)
    p = t.unsqueeze(0)
    print(s.shape)
    print(p.shape)
    

    输出结果:

    torch.Size([2, 3, 4])
    torch.Size([2, 3, 1, 4])
    torch.Size([1, 2, 3, 4])

6. 张量的数学运算

『PyTorch』Tensor

需要用到时查询使用

print(s.shape)


> 输出结果:
>
> torch.Size([2, 3, 4])
> torch.Size([4, 3, 2])



### 5.3.3 torch.t()

- <font size=5 color = gree>功能</font>:转置二维张量



### 5.3.4 torch.squeeze()

- <font size=5 color = gree>功能</font>

压缩长度为1的轴

- 不输入参数,则移除所有长度为1的维度
- 若指定维度,则当且仅当该维度长度为1时,可以删除该维度



### 5.3.5 torch.unsqueeze()

- <font size=5 color = gree>功能</font>
扩充张量维度

```python
import torch

t = torch.ones(2, 3, 4)

print(t.shape)

s = t.unsqueeze(2)
p = t.unsqueeze(0)
print(s.shape)
print(p.shape)

输出结果:

torch.Size([2, 3, 4])
torch.Size([2, 3, 1, 4])
torch.Size([1, 2, 3, 4])

6. 张量的数学运算

『PyTorch』Tensor

需要用到时查询使用