• 3-Pytorch张量的运算、形状改变、自动微分


    1 导入必备库

    import torch
    import numpy as np
    
    • 1
    • 2

    2 张量的运算

    张量的运算规则、切片索引规则与numpy类似,运算中遵循广播原则和同形状同位置元素对齐运算原则

    t1 = torch.randn(2,3)
    t2 = torch.ones(2,3)
    print('t1=',t1)
    print('t1+3=',t1+3)
    print('t1+t2=',t1+t2)        #同位置元素相加
    print('t1.add(t2)=',t1.add(t2))   #等价t1+t2
    
    print('t1=',t1)
    t1.add_(t2)         # add_方法表示就地改变原值,不需要存放在其它变量内
    print('t1.add_(t2)=',t1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出:

    t1= tensor([[-1.1872,  1.4624,  0.1379],
            [ 1.0701, -2.6139, -1.2106]])
    t1+3= tensor([[1.8128, 4.4624, 3.1379],
            [4.0701, 0.3861, 1.7894]])
    t1+t2= tensor([[-0.1872,  2.4624,  1.1379],
            [ 2.0701, -1.6139, -0.2106]])
    t1.add(t2)= tensor([[-0.1872,  2.4624,  1.1379],
            [ 2.0701, -1.6139, -0.2106]])
    t1= tensor([[-1.1872,  1.4624,  0.1379],
            [ 1.0701, -2.6139, -1.2106]])
    t1.add_(t2)= tensor([[-0.1872,  2.4624,  1.1379],
            [ 2.0701, -1.6139, -0.2106]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3 张量的算数运算

    张量的算数运算包括:abs(绝对值)、cunsum(累加)、divide(除)、floor_divide(整除)、mean(均值)、min(最小值)、max(最大值)、multiply(乘)等,矩阵转置常用(tensor.T)和矩阵乘法用(matmul或@)

    print('t1.matmul(t2.T)=',t1.matmul(t2.T))
    print('t1 @ (t2.T)=',t1 @ (t2.T))
    
    • 1
    • 2

    输出:

    t1.matmul(t2.T)= tensor([[3.4131, 3.4131],
            [0.2456, 0.2456]])
    t1 @ (t2.T)= tensor([[3.4131, 3.4131],
            [0.2456, 0.2456]])
    
    • 1
    • 2
    • 3
    • 4

    4 一个元素的张量可以使用tensor.item()方法转成标量

    t3 = t1.sum()
    print('t3=',t3,type(t3))
    print('t3.item()=', t3.item(),type(t3.item()))
    
    • 1
    • 2
    • 3

    输出:

    t3= tensor(3.6586) 
    t3.item()= 3.658644914627075 
    
    • 1
    • 2

    5 torch.from_numpy()和tensor.numpy()

    使用torch.from_numpy()方法将ndarray转成张量,使用tensor.numpy()方法得到对应的ndarray数组,它们共用相同内存

    a = np.random.randn(2,3)
    print('a= ', a)
    t = torch.from_numpy(a)
    print('t= ', t)
    print('t.numpy()=',t.numpy())
    
    • 1
    • 2
    • 3
    • 4
    • 5

    输出:

    a=  [[-0.17144614  0.03711562 -0.40770295]
     [ 0.64600264 -1.39858095  0.41699902]]
    t=  tensor([[-0.1714,  0.0371, -0.4077],
            [ 0.6460, -1.3986,  0.4170]], dtype=torch.float64)
    t.numpy()= [[-0.17144614  0.03711562 -0.40770295]
     [ 0.64600264 -1.39858095  0.41699902]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6 张量的变形

    tensor.size()方法和tensor.shape属性返回张量的形状。

    改变张量的形状用tensor.view()方法,相当于numpy中的reshape方法

    t = torch.randn(4,6)
    print('shape返回张量的形状: t.shape=',t.shape)
    t1 = t.view(3,8)
    print('view改变形状: t1.shape=',t1.shape)
    # 将tensor矩阵展平,-1表示长度自动计算
    t1 = t.view(-1,1)
    print('view展平: t1.shape=',t1.shape)
    
    # 使用view增加维度,总元素个数不变
    t1 = t.view(1,4,6)
    print('view增加维度: t1.shape=',t1.shape)
    
    # 当维度为1时,使用torch.squeeze()去掉长度为1的维度,相应的torch.unsqueeze()增加长度为1的维度
    print('t1.shape=',t1.shape)
    t2 = torch.squeeze(t1)  # 去掉长度为1的维度
    print('squeeze去掉1维度: t2.shape=',t2.shape)
    t3 = torch.unsqueeze(t2,0)
    print('unsqueeze增加1维度: t2.shape=',t3.shape)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出;

    shape返回张量的形状: t.shape= torch.Size([4, 6])
    view改变形状: t1.shape= torch.Size([3, 8])
    view展平: t1.shape= torch.Size([24, 1])
    view增加维度: t1.shape= torch.Size([1, 4, 6])
    t1.shape= torch.Size([1, 4, 6])
    squeeze去掉1维度: t2.shape= torch.Size([4, 6])
    unsqueeze增加1维度: t2.shape= torch.Size([1, 4, 6])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7 张量的自动微分

    requires_grad属性设置为True时,Pytorch会跟踪此张量所有计算,并可调用backward() 计算所有梯度,梯度将累加到grad属性中。
    grad_fn属性指向运算生成此张量的方法。

    t = torch.ones(2,2,requires_grad= True)
    print('是否跟踪计算梯度:', t.requires_grad)
    print('输出梯度:', t.grad)
    print('生成此张量的方法:', t.grad_fn)
    
    y = t + 5
    print('y= ', y)
    print('y.grad_fn=',y.grad_fn)
    
    z = y * 2
    out = z.mean()
    print('out=',out)
    
    # 对out微分:d(out)/d(t)
    out.backward()
    print('t.grad=',t.grad)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出:

    是否跟踪计算梯度: True
    输出梯度: None
    生成此张量的方法: None
    y=  tensor([[6., 6.],
            [6., 6.]], grad_fn=)
    y.grad_fn= 
    out= tensor(12., grad_fn=)
    t.grad= tensor([[0.5000, 0.5000],
            [0.5000, 0.5000]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    8 使用with torch.no_grad():包含上下文中使其不再跟踪计算

    print('是否跟踪计算梯度:', t.requires_grad)
    print('是否跟踪计算梯度:', (t+2).requires_grad)
    
    with torch.no_grad():
        print('是否跟踪计算梯度:', (t+2).requires_grad)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    输出:

    是否跟踪计算梯度: True
    是否跟踪计算梯度: True
    是否跟踪计算梯度: False
    
    • 1
    • 2
    • 3

    9 使用tensor.detach()分离出张量的值

    print('是否跟踪计算梯度:', out.requires_grad)
    # s1  = out.data()  #获取值
    s = out.detach()
    
    print('是否跟踪计算梯度:',s.requires_grad)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    输出:

    是否跟踪计算梯度: True
    是否跟踪计算梯度: False
    
    • 1
    • 2

    10 requirs_grad_()方法改变张量的跟踪属性,是否需要追踪计算

    print('是否跟踪计算梯度:', t.requires_grad)
    t.requires_grad_(False)
    print('是否跟踪计算梯度:', t.requires_grad)
    
    • 1
    • 2
    • 3

    输出:

    是否跟踪计算梯度: True
    是否跟踪计算梯度: False
    
    • 1
    • 2
  • 相关阅读:
    C#基础学习(二十三)_窗体与事件
    用户体验设计师是什么,一篇文章读懂!
    git标签操作
    杀戮空间2开服服务器架设教程UE3Redist
    常见的传输介质及其特性
    vulnhub靶场之THALES: 1
    无需API开发,伯俊科技实现电商与客服系统的无缝集成
    js中setTimeout定时器不准的原因,以及修正的办法
    动态负荷对电力系统摆幅曲线的影响研究(Matlab代码实现)
    性能测试场景设计之普通性能场景设计
  • 原文地址:https://blog.csdn.net/m0_46256255/article/details/132857830