Pytorch实践中的几个重要概念

自动微分

Pytorch支持自动微分,即自动计算梯度,无需人工参与,既可以自动计算一个函数关于一个变量在某一取值下的导数。通过该功能,就可以使用基于梯度的方法对参数(变量)进行优化(也叫学习或训练)。使用Pytorch计算梯度非常容易,仅需要执行tensor.backward()函数,就可以通过反向传播算法自动完成。

需要注意,为了计算一个函数关于某一个变量的导数,Pytorch要求显示设置该变量(张量)是可求导的,否则默认不能对该变量求导。具体设置方法为:在张量生成时,设置requires_grad=True

因此,计算 z = ( x + y ) × ( y − 2 ) z=(x+y)\times (y-2) z=(x+y)×(y2)中,当 x = 2 , y = 3 x=2,y=3 x=2,y=3时,求 d z / d x dz/dx dz/dx d z / d y dz/dy dz/dy的值:

import torch

x=torch.tensor([2.],requires_grad=True)
y=torch.tensor([3.],requires_grad=True)

z=(x+y)*(y-2)
print(z)
# tensor([5.], grad_fn=<MulBackward0>)

z.backward()
print(x.grad,y.grad)
# tensor([1.]) tensor([6.])

我们手动验证: d z d x = y − 2 , d z d y = x + 2 y − 2 \frac{dz}{dx}=y-2,\frac{dz}{dy}=x+2y-2 dxdz=y2,dydz=x+2y2 x = 2 , y = 3 x=2,y=3 x=2,y=3时,梯度确实为 1 1 1 6 6 6

张量调整形状

参与运算的张量需要满足一定的形状,比如两个矩阵相乘,前一个矩阵的第二维应该和后一个矩阵的第一维相同。Pytorch一共有4种调整张量形状的函数,分别为view,reshape,transpose,permute

view函数的参数用于设置新的张量形状,因此,需要保证张量总的元素个数不变:

x=torch.tensor([1,2,3,4,5,6])
print(x.shape) # torch.Size([6])
y=x.view(-1,3)
print(y.size()) # torch.Size([2, 3])

进行view操作的张量要求是连续的(Contiguous),可以调用is_conuous函数判断一个张量是否为连续的。如果张量非连续,则需要先调用contiguous函数将其变为连续的,才能使用view。为了克服这个缺点,Pytorch提供了reshape,可以对非连续张量调整形状,reshape与view的功能一致。

transpose(转置)函数用于交换张量中的两个维度,参数分别为相应的维序号:

x=torch.tensor([[1,2,3],[4,5,6]])
print(x)
"""
torch.Size([2, 3])
tensor([[1, 2, 3],
        [4, 5, 6]])
"""
y=x.transpose(0,1) # 交换第1维和第2维
print(y)
"""
torch.Size([3, 2])
tensor([[1, 4],
        [2, 5],
        [3, 6]])
"""

transpose只能同时交换两个维度,若要交换更多维度,需要多次调用该函数,为了便捷,Pytorch提供了permute函数,其需要提供全部维度信息作为参数(即使有些维度无须交换也要提供):

x=torch.tensor([[[1,2,3],[4,5,6]]])
print(x,x.shape)
"""
tensor([[[1, 2, 3],
         [4, 5, 6]]]) torch.Size([1, 2, 3])
"""
y=x.permute(2,0,1)
print(y,y.shape)
"""
tensor([[[1, 4]],
        [[2, 5]],
        [[3, 6]]]) torch.Size([3, 1, 2])
"""

广播机制

在上面的张量运算中,都是假设两个参与运算的张量形状相同。在有些情况下,即使两个张量的形状不同,也可以通过广播机制执行按元素计算。具体的执行规则为:

  • 首先,对其中一个或同时对两个张量的元素进行复制,使得两个张量形状相同;
  • 然后,在扩展之后的张量上再执行按元素运算。

通常是沿着长度为1的维度进行扩展,示例如下:

x=torch.arange(1,4).view(3,1)
y=torch.arange(4,6).view(1,2)
print(x)
"""
tensor([[1],
        [2],
        [3]])
"""
print(y)
"""
tensor([[4, 5]])
"""

生成两个张量,形状分别为(3,1)和(1,2),显然,它们不能直接执行按元素运算。因此,在执行按元素运算之前,需要将它们扩展(广播)为形状(3,2)的张量,具体扩展方法为将x的第1列复制到第2列,将y的第1行复制到第2行,第3行。

比如,执行加法:

print(x+y)
"""
tensor([[5, 6],
        [6, 7],
        [7, 8]])
"""

索引与切片

与Python列表类似,Pytorch中也可以对张量进行索引和切片操作,规则也与Python基本一致,即索引值是从0开始的,切片[m:n]的范围是从m开始到n前一个元素结束(左闭右开)。与Python不同,Pytorch可以对张量的任意一个维度进行索引或切片:

x=torch.arange(12).view(3,4)
print(x)
"""
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
"""
print(x[1,3]) # 取第2行第4列的元素
"""
tensor(7)
"""
print(x[1]) # 取第2行全部元素
"""
tensor([4, 5, 6, 7])
"""
print(x[1:3]) # 取第2,3两行的元素
"""
tensor([[ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
"""
print(x[:,2]) # 取第3列全部元素
"""
tensor([ 2,  6, 10])
"""
print(x[:,2:4]) # 取第3,4两列的元素
"""
tensor([[ 2,  3],
        [ 6,  7],
        [10, 11]])
"""
x[:,2:4]=100 # 第3,4两列元素全部赋值100
print(x)
"""
tensor([[  0,   1, 100, 100],
        [  4,   5, 100, 100],
        [  8,   9, 100, 100]])
"""

降维与升维

升维通过调用torch.unsqueeze(input,dim,out=None)函数,对输入张量的dim位置插入维度1,并返回一个新的张量。与索引相同,dim的值可以为负数。

降维恰好相反,使用torch.squeeze(input,dim,out=None)函数:

  • 在不指定dim时,张量中形状为1的所有维都将被去除。比如输入形状为 ( A , 1 , B , 1 , C , 1 , D ) (A,1,B,1,C,1,D) (A,1,B,1,C,1,D)的张量,输出形状变成 ( A , B , C , D ) (A,B,C,D) (A,B,C,D)
  • 当给定dim时,降维操作只在给定维度上,比如输入形状为 ( A , 1 , B ) (A,1,B) (A,1,B),如果设置squeeze(input,dim=0),张量形状将保持不变,只有设置squeeze(input,dim=1),形状才会变成 ( A , B ) (A,B) (A,B)
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值