#

pytorch深度学习基础


pytorch深度学习基础

Tensor对象及其运算

Tensor对象是一个维度任意的矩阵,但是一个Tensor中所有元素的数据类型必须一致。torch包含的数据类型和普遍编程语言的数据类型类似,包含浮点型,有符号整型和无符号整形,这些类型既可以定义在CPU上,也可以定义在GPU上。在使用Tensor数据类型时,可以通过dtype属性指定它的数据类型,device指定它的设备(CPU或者GPU)。

import torch
import numpy as np

a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[1, 2], [3, 4]])
print(a*b)

print(torch.mm(a, b))

显示:

tensor([[ 1,  4],
        [ 9, 16]])
tensor([[ 7, 10],
        [15, 22]])

torch.clamp起的是分段函数的作用,可用于去掉矩阵中过小或者过大的元素。

PyTorch提供了大量的对Tensor进行操作的函数或方法,这些函数内部使用指针实现对矩阵的形状变换,拼接,拆分等操作,使得我们无须关心Tensor在内存的物理结构或者管理指针就可以方便且快速的执行这些操作。Tensor.nelement()Tensor.ndimension()ndimension.size()可分别用来查看矩阵元素的个数,轴的个数以及维度,属性Tensor.shape也可以用来查看Tensor的维度。

Tensor的变换、拼接和拆分

在PyTorch中,Tensor.reshapeTensor.view都能被用来更改Tensor的维度。它们的区别在于,Tensor.view要求Tensor的物理存储必须是连续的,否则将报错,而Tensor.reshape则没有这种要求。但是,Tensor.view返回的一定是一个索引,更改返回值,则原始值同样被更改,Tensor.reshape返回的是引用还是拷贝是不确定的。它们的相同之处都接收要输出的维度作为参数,切输出的矩阵元素个数不能改变,可以在维度中输入-1,PyTorch会自动推断它的数值。

在PyTorch中,Tensor.reshape和Tensor.view都能被用来更改Tensor的维度。它们的区别在于,Tensor.view要求Tensor的物理存储必须是连续的,否则将报错,而Tensor.reshape则没有这种要求。但是,Tensor.view返回的一定是一个索引,更改返回值,则原始值同样被更改,Tensor.reshape返回的是引用还是拷贝是不确定的。它们的相同之处都接收要输出的维度作为参数,切输出的矩阵元素个数不能改变,可以在维度中输入-1,PyTorch会自动推断它的数值。

b =torch.squeeze(a)
print(b.shape)

返回值:

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

二维转置用torch.t,多维度可以用permute()函数实现:

a = torch.rand([1,  224, 224, 3])
print(a)
print(a.shape)
b = a.permute(0,3,1,2)
print(b.shape)

返回值为:

tensor([[[[3.6860e-01, 2.8806e-01, 2.1226e-01],
          [8.5628e-04, 8.3488e-01, 5.4180e-01],
          [5.0457e-01, 7.1150e-01, 1.8034e-02],
          ...,
          [1.0439e-01, 9.6792e-01, 5.4312e-02],
          [5.9024e-01, 9.3023e-01, 7.6815e-01],
          [2.8887e-01, 9.4723e-01, 6.4809e-01]],

         [[6.3776e-03, 4.4275e-01, 9.9699e-01],
          [1.6847e-01, 4.9107e-01, 9.8282e-01],
          [5.7448e-01, 9.2207e-01, 5.1265e-01],
          ...,
          [6.8215e-02, 2.9971e-01, 2.2088e-01],
          [1.5893e-02, 8.3497e-01, 4.0665e-01],
          [3.9007e-01, 3.7976e-01, 3.4293e-01]],

         [[3.9511e-01, 5.3699e-01, 8.7523e-01],
          [2.0365e-02, 7.8796e-01, 3.4477e-01],
          [1.0294e-01, 4.3773e-01, 1.5031e-01],
          ...,
          [1.4725e-01, 4.1975e-01, 8.9547e-01],
          [2.3337e-01, 7.7988e-01, 7.1522e-01],
          [2.7721e-01, 1.6050e-01, 1.0747e-02]],

         ...,

         [[4.0493e-01, 6.1730e-01, 9.4033e-01],
          [3.5808e-01, 3.7298e-01, 9.8320e-01],
          [3.7041e-02, 4.1414e-01, 6.6998e-01],
          ...,
          [9.5621e-01, 4.2584e-01, 5.6640e-01],
          [3.5720e-02, 2.0758e-01, 6.1817e-01],
          [6.9376e-01, 1.1626e-01, 2.9182e-01]],

         [[5.5343e-01, 5.2249e-01, 6.6126e-02],
          [5.8498e-01, 2.5871e-02, 2.3405e-01],
          [6.4199e-02, 3.0509e-01, 5.7775e-01],
          ...,
          [6.1127e-01, 4.3303e-01, 3.7878e-01],
          [1.3533e-02, 5.4714e-01, 9.1301e-01],
          [3.5130e-01, 7.8249e-01, 9.5742e-01]],

         [[8.2594e-01, 1.8202e-01, 9.5836e-01],
          [4.6360e-01, 8.8640e-01, 8.6581e-01],
          [6.4844e-01, 8.8921e-01, 5.9467e-01],
          ...,
          [3.8022e-01, 8.0356e-01, 3.2146e-01],
          [6.1877e-01, 2.7097e-01, 3.7226e-02],
          [1.4843e-01, 6.5034e-01, 7.2513e-02]]]])
torch.Size([1, 224, 224, 3])
torch.Size([1, 3, 224, 224])

PyTorch提供了torch.cattorch.stack用于拼接矩阵,不同的是,torch.cat在已有的轴dim上拼接矩阵,给定轴的维度可以不同,而其他轴的维度必须相同。torch.stack在新的轴上拼接,它要求被拼接的矩阵所有维度都相同。

a =torch.randn(2,3)
b =torch.randn(3,3)

#默认维度为dim=0
c=torch.cat((a,b))
d=torch.cat((b,b,b),dim=1)

print(c.shape)
print(d.shape)

返回:

torch.Size([5, 3])
torch.Size([3, 9])
c=torch.stack((b,b), dim=1)
d=torch.stack((b,b), dim=0)

print(c.shape)
print(d.shape)

返回:

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

除了拼接矩阵,PyTorch还提供了torch.splittorch.chunk用于拆分矩阵。它们的不同之处在于,torch.split传入的是拆分后每个矩阵的大小,可以传入list,也可以传入整数,而torch.chunk传入的是拆分的矩阵个数。

Reduction运算的特点是它往往对一个Tensor内的元素做归约操作,比如torch.max找极大值,torch.cumsum计算累加,它还提供了dim参数来指定沿矩阵的哪个维度执行操作。

Tensorrequires_grad属性设置为True时,PyTorch的torch.autograd会自动的追踪它的计算轨迹,当需要计算微分的时候,只需要对最终计算结果的Tensor调用backward方法,中间所有计算结点的微分就会被保存在grad属性中了。

x = torch.arange(9).view(3,3)
print(x.requires_grad)
print('*******************************************')
x = torch.rand(3, 3, requires_grad = True)
print(x)
print('*******************************************')
w = torch.ones(3, 3, requires_grad=True)
y = torch.sum(torch.mm(w,x))
print(y)
print('*******************************************')
y.backward()
print(y.grad)
print(x.grad)
print(w.grad)

返回:

False
*******************************************
tensor([[0.6608, 0.0725, 0.9230],
        [0.8255, 0.2638, 0.0431],
        [0.6806, 0.4232, 0.4164]], requires_grad=True)
*******************************************
tensor(12.9265, grad_fn=<SumBackward0>)
*******************************************
None
tensor([[3., 3., 3.],
        [3., 3., 3.],
        [3., 3., 3.]])
tensor([[1.6564, 1.1323, 1.5202],
        [1.6564, 1.1323, 1.5202],
        [1.6564, 1.1323, 1.5202]])

Process finished with exit code 0


文章作者: 王胜鹏
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 王胜鹏 !
评论
 上一篇
PyTorch训练神经网络 PyTorch训练神经网络
PyTorch训练神经网络 可以使用torch.nn包来构建神经网络。 nn包则依赖于autograd包来定义模型并对它们求导。一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。 如图这个神经网
2021-08-14
下一篇 
机器学习基础知识 机器学习基础知识
机器学习基础知识 模型评估与参数选择 若对于给定的输入xxx,若某个模型的输出y^=f(x)\hat{y}=f(x)y^​=f(x)偏离真实目标值yyy,那么就说明模型存在误差;y^\hat{y}y^​偏离yyy的程度可以用关于y^\hat
2021-08-12
  目录