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.reshape
和Tensor.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.cat
和torch.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.split
和torch.chunk
用于拆分矩阵。它们的不同之处在于,torch.split
传入的是拆分后每个矩阵的大小,可以传入list
,也可以传入整数,而torch.chunk
传入的是拆分的矩阵个数。
Reduction运算的特点是它往往对一个Tensor
内的元素做归约操作,比如torch.max
找极大值,torch.cumsum
计算累加,它还提供了dim参数来指定沿矩阵的哪个维度执行操作。
将Tensor
的requires_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