Pytorch中张量的构造与组织

前言:《神经网络与PyTorch实战》读书笔记之PyTorch中的张量操作

文章目录

    • 1. PyTorch中的张量
    • 2. 构造Tensor实例方法
    • 3. 组织张量元素(重点)
      • 3.1 重排张量
      • 3.2 选取部分张量
      • 3.3 张量扩展和拼接
      • 3.4 torch内置统计函数

1. PyTorch中的张量

  • torch.Tensor类的常用成员:
    • size() 返回张量大小
    • dim() 返回张量维度
    • numel() 返回张量中元素个数
>>> import torch
>>> tmp = torch.tensor([[1,2,3],[4,5,6]])
>>> tmp
tensor([[1, 2, 3],[4, 5, 6]])
>>> tmp.reshape(3,2)
tensor([[1, 2],[3, 4],[5, 6]])
>>> tmp
tensor([[1, 2, 3],[4, 5, 6]])
>>> tmp.size()
torch.Size([2, 3])
>>> tmp.dim()
2
>>> tmp.numel()
6
>>> tmp.dtype
torch.int64

2. 构造Tensor实例方法

  • torch.zeros(), torch.zeros_like()

    •   >>> torch.zeros(3,4)tensor([[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.]])>>> a=torch.tensor([1,2,3])>>> torch.zeros_like(a)tensor([0, 0, 0])>>>
      
  • torch.ones(), torch.ones_like()

    •   >>> torch.ones(4,5)tensor([[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.]])>>> torch.ones_like(torch.zeros(3,4))tensor([[1., 1., 1., 1.],[1., 1., 1., 1.],[1., 1., 1., 1.]])>>>
      
  • torch.full(), torch.full_like()

    • 两个参数,张量的大小和要填充的值

      >>> torch.full((3,3),3)
      tensor([[3., 3., 3.],[3., 3., 3.],[3., 3., 3.]])
      >>> torch.full_like(torch.zeros(3,4),3)
      tensor([[3., 3., 3., 3.],[3., 3., 3., 3.],[3., 3., 3., 3.]])
      >>>
      
  • torch.empty(), torch.empty_like()

    • 不指定具体的值

      >>> torch.empty(2,2)
      tensor([[ 0.0000e+00,  0.0000e+00],[-3.7177e-36,  4.5912e-41]])
      >>> torch.empty_like(torch.zeros(3,3))
      tensor([[1.0561e-38, 1.0286e-38, 1.0653e-38],[1.0469e-38, 9.5510e-39, 6.2449e-39],[6.9796e-39, 8.4490e-39, 1.0561e-38]])
      >>>
      
  • torch.eye()

    •   >>> torch.eye(5,5)tensor([[1., 0., 0., 0., 0.],[0., 1., 0., 0., 0.],[0., 0., 1., 0., 0.],[0., 0., 0., 1., 0.],[0., 0., 0., 0., 1.]])>>>
      
  • torch.arange(), torch.range(), torch.linspace(), torch.logspace()

    •   >>> torch.arange(2,10)tensor([2, 3, 4, 5, 6, 7, 8, 9])>>> torch.arange(2,10,2)tensor([2, 4, 6, 8])>>> torch.range(2,10,2)__main__:1: UserWarning: torch.range is deprecated in favor of torch.arange and will be removed in 0.5. Note that arange generates values in [start; end), not [start; end].tensor([ 2.,  4.,  6.,  8., 10.])>>> torch.linespace(2,10,2)Traceback (most recent call last):File "", line 1, in <module>AttributeError: module 'torch' has no attribute 'linespace'>>> torch.linspace(2,10,2)tensor([ 2., 10.])>>> torch.linspace(2,10,6)tensor([ 2.0000,  3.6000,  5.2000,  6.8000,  8.4000, 10.0000])>>> torch.logspace(2,10,6)tensor([1.0000e+02, 3.9811e+03, 1.5849e+05, 6.3096e+06, 2.5119e+08, 1.0000e+10])>>>
      
    • arange() 中第三个参数代表每隔几个进行一次取样

    • linspace(), logspace()中第三个参数代表一共取多少个样本

  • torch.bernoulli(), torch.multinomial(), torch.randperm(), torch.randint(), torch.randint_like() 随机向量

    •   >>> probs = torch.full((3,4), 0.5) # 概率张量,有一定的概率取1>>> torch.bernoulli(probs)tensor([[0., 1., 1., 1.],[0., 0., 1., 1.],[1., 1., 0., 0.]])>>> torch.bernoulli(probs)tensor([[0., 0., 0., 0.],[1., 1., 0., 0.],[1., 0., 1., 0.]])>>>
      
    •   >>> import torch>>> weights=torch.tensor([[1,100],[100,1],[1,1]], dtype=torch.float32)>>> weightstensor([[  1., 100.],[100.,   1.],[  1.,   1.]])>>> torch.multinomial(weights,1)tensor([[1],[0],[1]])ps: 不知道有啥用
      
    •   >>> torch.randperm(5, dtype=torch.float32)tensor([2., 0., 3., 1., 4.])>>>功能就是随机生成一个排列,参数只有一个n, 得到{0,1,2..., n-1}一个排列
      
    •   >>> torch.randint(low=0,high=4,size=(3,4))tensor([[0, 2, 0, 1],[3, 2, 3, 1],[0, 1, 0, 0]])>>> torch.randint_like(torch.ones(3,4), low=0, high=4)tensor([[0., 0., 0., 0.],[3., 3., 1., 3.],[2., 3., 0., 2.]])功能:[low,high)范围的数,生成独立同分布的离散均匀分布的张量
      
    •   >>> torch.rand(2,3)tensor([[0.0408, 0.8364, 0.2955],[0.5750, 0.9387, 0.0326]])>>> torch.rand_like(torch.ones(3,3))tensor([[0.1841, 0.9014, 0.6892],[0.6298, 0.9209, 0.4046],[0.1707, 0.2002, 0.3489]])>>> mean=torch.tensor([0.,1.])>>> std=torch.tensor([3.,2.])>>> torch.normal(mean,std)tensor([-1.4714, -0.3917])>>>
      

3. 组织张量元素(重点)

张量的组织在深度学习中tensor的处理中非常常见,所以也是重中之重。

3.1 重排张量

  • reshape(), squeeze(), unsqueeze(),不会改变元素的实际位置
  • permute(), transpose(), t(), 可能会改变元素的实际位置
  1. reshape() 方法

    张量元素个数相同的情况下,改变张量的维度

    >>> import torch
    >>> ts = torch.arange(12)
    >>> ts.reshape(3,4)
    tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])
    >>> ts.reshape(3,4).size()
    torch.Size([3, 4])
    >>> ts.reshape(-1,4).size()
    torch.Size([3, 4])
    >>> ts.reshape(-1,2).size() # -1 代表可以通过其他维度进行计算
    torch.Size([6, 2])
    >>>
    
  2. squeeze()方法

    >>> t = torch.arange(24).reshape(2,1,3,4,1)
    >>> t.size()
    torch.Size([2, 1, 3, 4, 1])
    >>> t.squeeze()
    tensor([[[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]],[[12, 13, 14, 15],[16, 17, 18, 19],[20, 21, 22, 23]]])
    >>> t.squeeze().size() # 将 1 维度的挤压掉
    torch.Size([2, 3, 4])
    >>>
    
  3. unsqueeze()方法

    >>> t = torch.arange(24).reshape(2,3,4)
    >>> t.unsqueeze(dim=1).size() # 在第1维度进行
    torch.Size([2, 1, 3, 4])### 举个例子 两张图片
    >>> img = torch.ones([512,512,3])
    >>> img.size()
    torch.Size([512, 512, 3])
    >>> img = img.unsqueeze(dim=0)
    >>> img.size()
    torch.Size([1, 512, 512, 3])
    >>> img2 = torch.ones([512,512,3])
    >>> img2 = img2.unsqueeze(dim=0)
    >>> img2.size()
    torch.Size([1, 512, 512, 3])
    
  4. permuate()方法:英文意思是排列,重新排列,进行张量的交换

    >>> t = torch.arange(24).reshape(1,2,3,4)
    >>> t.permute(dims=[0,2,1,3])
    tensor([[[[ 0,  1,  2,  3],[12, 13, 14, 15]],[[ 4,  5,  6,  7],[16, 17, 18, 19]],[[ 8,  9, 10, 11],[20, 21, 22, 23]]]])
    >>> t.permute(dims=[0,2,1,3]).size() # 根据dims进行重排
    torch.Size([1, 3, 2, 4])
    >>>
    
  5. transpose(),张量的交换可以用转置实现

    >>> t.size()
    torch.Size([1, 2, 3, 4])
    >>> t.transpose(0,3).size()
    torch.Size([4, 2, 3, 1]) # 互换0和3维度
    >>>
    

3.2 选取部分张量

选取一个张量中部分元素,涉及index_select(), masked_select(), take()三个方法。

  1. index_select() 方法有两个参数,dim 表示对哪个维度进行处理, index表示选取该维度哪些指标

    >>> t = torch.arange(24).reshape(2,3,4)
    >>> index = torch.tensor([1,2])
    >>> t.index_select(dim=1, index=index)
    tensor([[[ 4,  5,  6,  7],[ 8,  9, 10, 11]],[[16, 17, 18, 19],[20, 21, 22, 23]]])
    >>> t.index_select(dim=1, index=index).size()
    torch.Size([2, 2, 4])
    >>>
    
  2. masked_select() 只接受一个张量参数mask, 这个mask大小必须要跟作用对象相同,且类型必须为torch.uint8,且其中元素必须是0或者1,对应为1的部分就会被选择。

    >>> t = torch.arange(12).reshape(3,4)
    >>> mask = torch.tensor([[1,0,0,1],[0,1,0,0],[0,0,0,0]])
    >>> mask = torch.tensor([[1,0,0,1],[0,1,0,0],[0,0,0,0]], dtype=torch.uint8)
    >>> t.masked_select(mask)
    tensor([0, 3, 5])
    >>> t
    tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])
    >>>
    
  3. take() 不考虑张量大小,只考虑总个数,相当于对tensor进行reshape(-1)以后进行索引的结果。

    >>> t = torch.arange(12).reshape(3,4)
    >>> t
    tensor([[ 0,  1,  2,  3],[ 4,  5,  6,  7],[ 8,  9, 10, 11]])
    >>> indices = torch.tensor([3,4,5])
    >>> t.take(indices)
    tensor([3, 4, 5])
    >>> indices = torch.tensor([1,4,2])
    >>> t.take(indices)
    tensor([1, 4, 2])
    >>>
    # ps: 用的不多
    

    3.3 张量扩展和拼接

    这部分也很重要,讲解了各个方法操作以后会介绍一个简单的但很实用的例子。

    主要涉及到三个方法:repeat(), cat(), stack()

    1. repeat() 方法可以对张量内容进行复制,复制方法具体看例子:

      >>> import torch
      >>> img = torch.ones(224,224) # 假如读入了单通道图片想要将其处理成三通道,就会用到repeat
      >>> img.size()
      torch.Size([224, 224])
      >>> img = img.unsqueeze(2)
      >>> img.size()
      torch.Size([224, 224, 1])
      >>> img = img.repeat(1,1,3)
      >>> img.size()
      torch.Size([224, 224, 3])
      >>>
      
    2. cat() 方法可以对张量内容进行拼接,有两个参数,第一个参数是一个张量列表,第二个参数就是指定根据哪个维度进行拼接。依然延续上一个例子,拼接多张图片。

      >>> img1 = torch.ones(224)
      >>> img1 = torch.ones(224,224)
      >>> img2 =torch.ones(224,224)
      >>> img_list = torch.cat([img1,img2],2)
      Traceback (most recent call last):File "", line 1, in <module>
      IndexError: Dimension out of range (expected to be in range of [-2, 1], but got 2)
      >>> img1 = img1.unsqueeze(2)
      >>> img2 = img2.unsqueeze(2)
      >>> img_list = torch.cat([img1,img2],2)
      >>> img_list.size()
      torch.Size([224, 224, 2])
      >>>
      
    3. stack()方法与cat()方法不同之处在于stack()要求输入张量大小完全相同, 也可以看出来有其他地方不太一样。

      >>> img_list2 = torch.stack([img1,img2],2)
      >>> img_list2.size()
      torch.Size([224, 224, 2, 1])
      >>> img1.size()
      torch.Size([224, 224, 1])
      >>> img2.size()
      torch.Size([224, 224, 1])
      >>> img_list2 = torch.stack([img1,img2, img1, img2],2)
      >>> img_list2.size()
      torch.Size([224, 224, 4, 1])
      >>> tp = torch.arange(12).reshape(3,4)
      >>> tp.size()
      torch.Size([3, 4])
      >>> tn=-tp
      >>> tn.size()
      torch.Size([3, 4])
      >>> ts0 = torch.stack([tn,tp], 0)
      >>> ts0.size()
      torch.Size([2, 3, 4])
      >>> ts1 = torch.stack([tn,tn, tp, tp],1)
      >>> ts1.size()
      torch.Size([3, 4, 4])
      >>>
      

3.4 torch内置统计函数

主要有mean(), sum(), std(), var(), prod(), max(), min(), median(), kthvalue(), norm()

举例:

>>> t = torch.arange(5)
>>> t
tensor([0, 1, 2, 3, 4])
>>> t.mean() # 这里报错是因为不支持Long类型,使用dtype进行类型转化即可。
Traceback (most recent call last):File "", line 1, in <module>
RuntimeError: Can only calculate the mean of floating types. Got Long instead.
>>> t = torch.arange(5, dtype=torch.float32)
>>> t.mean()# 平均值
tensor(2.)
>>> t.var()# 方差
tensor(2.5000)
>>> t.sum()# 求和
tensor(10.)
>>> t.std()# 标准差
tensor(1.5811)
>>> t.median()#中位数
tensor(2.)
>>> t.kthvalue(3)#第k大值
torch.return_types.kthvalue(
values=tensor(2.),
indices=tensor(2))
>>> t.max()# 最大值
tensor(4.)
>>> t.min()# 最小值
tensor(0.)
>>> t.norm()# 范数
tensor(5.4773)

针对某个维度进行处理:

>>> t = torch.arange(12, dtype=torch.float32).reshape(2,2,3)
>>> t.var(dim=1) # 求某维度的方差
tensor([[4.5000, 4.5000, 4.5000],[4.5000, 4.5000, 4.5000]])
>>> t.prod(dim=1) # 求某一维度积
tensor([[ 0.,  4., 10.],[54., 70., 88.]])
>>> t.max(dim=1) # 求某一维度最大值
torch.return_types.max(
values=tensor([[ 3.,  4.,  5.],[ 9., 10., 11.]]),
indices=tensor([[1, 1, 1],[1, 1, 1]]))
>>> t.median(dim=1) # 求中位数
torch.return_types.median(
values=tensor([[0., 1., 2.],[6., 7., 8.]]),
indices=tensor([[0, 0, 0],[0, 0, 0]]))
>>> t.cumsum(dim=1) # 累计求和
tensor([[[ 0.,  1.,  2.],[ 3.,  5.,  7.]],[[ 6.,  7.,  8.],[15., 17., 19.]]])
>>> t.cumprod(dim=1) #累乘
tensor([[[ 0.,  1.,  2.],[ 0.,  4., 10.]],[[ 6.,  7.,  8.],[54., 70., 88.]]])
>>>

后记:暂且先写这么多,主要的用法,都已经写上了,后期遇到更多内容也会添加进来,欢迎在评论区讨论。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部