Pytorch深度学习实战3-3:张量Tensor的分块、变形、排序、极值与in-place操作

目录

  • 1 张量分块
  • 2 张量组合
  • 3 张量变形
    • 3.1 维度变换
    • 3.2 维度交换
    • 3.3 序列化与反序列化
    • 3.4 扩展
  • 4 张量排序
  • 5 张量极值
  • 6 in-place操作与共享内存

以下示例均假设

a = torch.Tensor([[0,1,2],[3,4,5]])
b = torch.Tensor([[6,7,8],[9,10,11]]))

1 张量分块

分块方法

  • torch.chunk(tensor,num,dim):将张量沿dim分成num块
  • torch.split(tensor,size,dim):将张量沿dim按size均分

实例

torch.chunk(a, 2, dim=0)
>> (tensor([[0., 1., 2.]]),
    tensor([[3., 4., 5.]]))

torch.chunk(a, 2, dim=1)
>> (tensor([[0., 1.], [3., 4.]]),    
    tensor([[2.],[5.]]))

torch.split(a, [1,2], dim=1)
>> (tensor([[0.],[3.]]),
    tensor([[1., 2.], [4., 5.]]))

2 张量组合

组合方法

  • torch.cat([tensor...],dim):沿已有维度dim拼接,除dim外其他维度与原先相同
  • torch.stack([tensor...],dim):新增维度dim堆叠

实例

torch.cat([a,b],dim=0)
>> tensor([[ 0.,  1.,  2.],
        [ 3.,  4.,  5.],
        [ 6.,  7.,  8.],
        [ 9., 10., 11.]])
        
torch.cat([a,b],dim=1)
>> tensor([[ 0.,  1.,  2.,  6.,  7.,  8.],
        [ 3.,  4.,  5.,  9., 10., 11.]])
        
torch.stack([a,b],dim=0)
>> tensor([[[ 0.,  1.,  2.],
            [ 3.,  4.,  5.]],
          [[ 6.,  7.,  8.],
            [ 9., 10., 11.]]])
            
torch.stack([a,b],dim=1)
>> tensor([[[ 0.,  1.,  2.],
            [ 6.,  7.,  8.]],
           [[ 3.,  4.,  5.],
            [ 9., 10., 11.]]])
            
torch.stack([a,b],dim=2)
>> tensor([[[ 0.,  6.],
            [ 1.,  7.],
            [ 2.,  8.]],
           [[ 3.,  9.],
            [ 4., 10.],
            [ 5., 11.]]])

Tensor的stack()堆叠机制阐述如下。堆叠维度dim是相对待堆叠张量而言,若dim=0则表明在新增维度上依次堆叠,而原张量在该维度下没有分量,故将整个张量视为整体;若dim>0则表明以已有维度为基准依次堆叠。

3 张量变形

3.1 维度变换

变形方法

  • torch.reshape(newshape)
  • torch.resize_(newshape)

实例

a.reshape(3,2)
a.reshape(-1,2) # 用-1占位隐式表示3x2
>> tensor([[0., 1.],
           [2., 3.],
           [4., 5.]])

3.2 维度交换

变形方法

  • tensor.transpose(dim0,dim1)
  • tensor.permute([newdim])

实例

# 维度交换
c = torch.stack([a,b],dim=0) # 2x2x3
>> tensor([[[ 0.,  1.,  2.],
            [ 3.,  4.,  5.]],
           [[ 6.,  7.,  8.],
            [ 9., 10., 11.]]])

# transpose交换两个指定维度
c.transpose(0,1)            # 2x2x3
>> tensor([[[ 0.,  1.,  2.],
            [ 6.,  7.,  8.]],
           [[ 3.,  4.,  5.],
            [ 9., 10., 11.]]])

# permute指定新的维度顺序
c.permute(2,1,0)            # 3x2x2
>> tensor([[[ 0.,  6.],
            [ 3.,  9.]],
           [[ 1.,  7.],
            [ 4., 10.]],
           [[ 2.,  8.],
            [ 5., 11.]]])

3.3 序列化与反序列化

变形方法

  • torch.squeeze(N)
  • torch.unsqueeze(N)

实例

# 将a(2x3)第1维序列化为(2x1x3)
c = a.unsqueeze(1)
>> c: tensor([[[0., 1., 2.]],
              [[3., 4., 5.]]])

# 将c(2x1x3)第1维反序列化为(2x3)
c.squeeze(1)
>> tensor([[0., 1., 2.],
           [3., 4., 5.]])

3.4 扩展

变形方法

  • tensor.expand(newshape)
  • tensor.expand_as(tensor)

实例

a.expand(2,2,3)
>> tensor([[[0., 1., 2.],
            [3., 4., 5.]],
           [[0., 1., 2.],
            [3., 4., 5.]]])
            
a.expand_as(torch.randn(2,2,3))
>> tensor([[[0., 1., 2.],
            [3., 4., 5.]],
           [[0., 1., 2.],
            [3., 4., 5.]]])

以复制元素形式扩展新维度或已存在的单维度,所有复制元素都与源元素共享内存

4 张量排序

Pytorch中使用tensor.sort()函数对张量沿指定维度排序,返回排序后的张量及对应索引位置,其中descending=True表示降序,descending=False表示升序。

举例

a= torch.randn(3,3)
>> tensor([[ 1.1976,  0.2529, -0.9852],
           [-0.2465, -0.2176, -1.4343],
           [ 0.9259, -0.7622,  0.1692]])
# 沿第0维即沿行排序,每列均为降序排列
a.sort(0, descending=True)
>> (tensor([[ 1.1976,  0.2529,  0.1692],
            [ 0.9259, -0.2176, -0.9852],
            [-0.2465, -0.7622, -1.4343]]),
	tensor([[0, 0, 2],
           [2, 1, 0],
           [1, 2, 1]]))

5 张量极值

Pytorch中使用tensor.max()tensor.min()函数对张量沿指定维度取极值,并返回极值组成的向量和极值在指定维度的索引。

举例

a= torch.randn(3,3)
>> tensor([[ 0.8160,  1.5793, -0.6898],
   	       [ 0.5470, -1.2048,  0.7410],
           [ 0.6604,  0.1297, -1.2990]])
# 沿第0维即沿行取最大值,输出向量为每列最大值
a.max(0)
>> (tensor([0.8160, 1.5793, 0.7410]), tensor([0, 0, 1]))

6 in-place操作与共享内存

Pytorch中部分操作会产生内存共享的变量,主要包括:

  • 通过组合、分块、索引、变形等手段,用Tensor初始化另一个Tensor,此时这两个Tensor指向同一片内存数据;
  • Tensor和Numpy数据转换前后的变量指向同一片内存数据。

举例

a=torch.Tensor([[0,1,2],[3,4,5]])
b = a.reshape(3,2)
b[0,0]=100
>> b:tensor([[100.,   1.],
             [  2.,   3.],
             [  4.,   5.]])
>> a:tensor([[100.,   1.,   2.],
             [  3.,   4.,   5.]])

本质上共享内存是由Python引用对象造成的,若要改变这种浅拷贝,需要借助copy.deepcopy()等深拷贝方式。

为实现高效计算,Pytorch提供原地操作in-place operation机制,即不经过拷贝,直接在原内存地址的数据上进行操作,降低内存占用的同时提高运算速度。Pytorch中以_为后缀的方法属于in-place operation,这种方法只要被执行,调用该方法的Tensor随即发生相应改变。

举例

a=torch.Tensor([[0,1,2],[3,4,5]])
>> a:tensor([[100.,   1.,   2.],
             [  3.,   4.,   5.]])
a.resize_(3,2)
>> a:tensor([[0., 1.],
        [2., 3.],
        [4., 5.]])

必须指出,以下场合不能使用in-place operation,否则发生RuntimeError

  • 对于在求梯度阶段需要用到的张量,不能使用in-place operation
  • 对于requires_grad=True的叶子张量不能使用in-place operation

更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系

你可能感兴趣的:(Pytorch深度学习实战,#,Pytorch基础技巧实战,深度学习,pytorch,python,人工智能)