PyTorch基本概念

在进行实际动手编程前,我们先需要了解PyTorch的一些基本概念。

Tensor

一句话来说,Tensor是一个多维数组,并且PyTorch提供了丰富的对Tensor的计算,这些计算可以在CPU或者GPU上进行计算。

Tensor的生成

我们先来随机生成一个tensor:

import torch
print(torch.rand(3,4))

你可以看到PyTorch帮我们随机生成了一个tensor。

tensor([[0.9840, 0.1846, 0.5857, 0.2941],
        [0.2826, 0.6252, 0.4713, 0.5295],
        [0.2293, 0.5696, 0.3149, 0.5688]])

Tensor的操作与Numpy的Ndarray非常类似,除了提供随机生成外,还有全1元素,全0元素,正态分布元素生成。

print(torch.ones(2,2))
print(torch.zeros(3,3))
print(torch.randn(2,3))

结果如下:

tensor([[1., 1.],
        [1., 1.]])
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
tensor([[ 0.4709, -1.7431,  1.0348],
        [-0.0726, -0.9833,  0.6386]])

你也可以从现有的类数组数据(array_like data)来创建一个tensor,比如list,tuple,Numpy的ndarray。

torch.tensor(data)

或者

torch.as_tensor(data)

前者总会发生数据拷贝,而后者如果数据类型和设备一致,则不需要拷贝。比如一个ndarray,如果要转化为一个同类型的在cpu上计算的tensor,则不需要进行数据拷贝。

import numpy as np
print(torch.tensor([[2,3],[3,4]]))
print(torch.tensor(np.array([2,2])))
print(torch.as_tensor([[2,3],[3,4]]))
print(torch.as_tensor(np.array([2,2])))

Tensor的维度

对于标量来说,它可以用一个维度为0的tensor来表示。对于一个向量,它可以用一个维度为1的tensor来表示。对于一个矩阵,它可以用一个维度为2的tensor来表示。对于一个3维,4维,或者更高维的数组,我们都可以用对应维度的tensor来表示。我们可以用

tensor.dim()

来查看一个tensor的维度。

x = torch.tensor(np.array([[2,3],[3,4]]))
x.dim()

Tenosr的操作

首先我们看如何获取和修改tensor里的元素:

x = torch.tensor(np.array([[2,3],[3,4]]))
item = x[1,1].item()
print(item)
x[1,1]=5
print(x[1,1].item())

如何让一个tensor是在GPU计算还是CPU计算呢?首先我们可以用tensor.device来查看它目前所运算的设备,我们可以通过tensor.to(deviceType)来改变。deviceType支持‘cuda’和‘cpu’两种。

print(x.device)
y = x.to('cuda')
print(y.device)

可以看到结果:

cpu
cuda:0

需要注意的是,如果我们对一个tensor进行操作,返回的新的tensor和原来的tensor所在的设备是一样的。
tensor.to(dtype)来改变一个tensor的存储类型:

x = torch.tensor([[1,2],[3,4]])
print(x.type())
y = x.to(dtype=torch.float32)
print(y.type())

可以看到结果:

torch.LongTensor
torch.FloatTensor

对于tensor大部分的方法来说,都是对当前tensor的数据进行处理并且返回一个新的tensor,这样你就有两个tensor,一个保存着处理之前的数据,一个保存着处理之后的数据。如果数据量大的话,这会造成不必要的内存或者显存的消耗。

x = torch.randn(2,3)
y = x.abs()
print("x:\n",x)
print("y:\n",y)

可以看到结果:

x:
 tensor([[ 0.7494,  1.0709, -0.6402],
        [-0.1680, -0.7371,  0.6683]])
y:
 tensor([[0.7494, 1.0709, 0.6402],
        [0.1680, 0.7371, 0.6683]])

如果能在原有tensor上直接修改数据的方法就好了,这点pytorch也考虑到了。很多方法都有两个版本,一个是返回新tensor的版本,一个是直接修改原来tensor的版本。比如tensor.abs()这个返回新tensor的函数对应有一个tensor.abs_() 版本的函数。以下划线结尾的函数一般是对tensor直接操作的函数。

x = torch.randn(2,3)
print("x:\n",x)
x.abs_()
print("x.abs_():\n",x)

可以看到结果:

x:
 tensor([[-0.1273,  0.1589,  0.8652],
        [ 1.1848, -0.3229, -1.3787]])
x.abs_():
 tensor([[0.1273, 0.1589, 0.8652],
        [1.1848, 0.3229, 1.3787]])

对tensor的计算除了调用tensor的函数,pytorch还重载了+,-,*,/. 需要注意的是这里的 * 是tensor对应位置的元素相乘,而不是矩阵乘法。 真正的矩阵乘法是tensor.mm(tensor).

x = torch.rand(2,2)
y = torch.rand(2,2)
print("x:\n",x)
print("y:\n",y)
print("x+y:\n",x+y)
print("x-y:\n",x-y)
print("x</em>y:\n",x<em>y)
print("x/y:\n",x/y)
print("x.mm(y):\n",x.mm(y))

可以看到结果:

x:
 tensor([[0.6877, 0.5608],
        [0.3776, 0.7787]])
y:
 tensor([[0.3667, 0.4225],
        [0.9677, 0.2962]])
x+y:
 tensor([[1.0544, 0.9833],
        [1.3453, 1.0749]])
x-y:
 tensor([[ 0.3210,  0.1383],
        [-0.5901,  0.4826]])
x</em>y:
 tensor([[0.2522, 0.2369],
        [0.3654, 0.2306]])
x/y:
 tensor([[1.8751, 1.3273],
        [0.3902, 2.6293]])
x.mm(y):
 tensor([[0.7949, 0.4567],
        [0.8920, 0.3902]])

与numpy相似,tensor也有broadcast功能,pytorch会把低维度的tensor通过复制,达到与高纬度tensor一样的维度,然后进行计算。具体规则:
1. 高纬度的tensor可以和一个标量的tensor(维度为0)进行计算。
2. 维度相同,shape不同的两个tensor,允许其中任一个tensor在一个维度上size为1.
3. 维度不同,从尾部对齐各个维度的size。最前边补1.
如果你不太清楚,可以参考这篇文章
我们看一些broadcast的例子:

x = torch.ones(3,3)
y = x+torch.FloatTensor([1,1,1])
z = x-torch.ones(3,1)
q = x*2
print("x:\n",x)
print("y:\n",y)
print("z:\n",z)
print("q:\n",q)

可以看到结果:

x:
 tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
y:
 tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
z:
 tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
q:
 tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])

我们经常需要改变一个tensor的形状,这时我们可以使用tensor.reshape函数:

x = torch.randn(2,6)
print("x(2,6):\n",x)
y = x.reshape(3,4)
print("y(3,4):\n",y)

可以看到结果:

x(2,6):
 tensor([[ 1.4981, -0.9614,  0.5853,  1.1521,  1.2854, -1.0931],
        [-0.1848, -1.3775,  0.8403, -0.8640,  0.8397,  0.1298]])
y(3,4):
 tensor([[ 1.4981, -0.9614,  0.5853,  1.1521],
        [ 1.2854, -1.0931, -0.1848, -1.3775],
        [ 0.8403, -0.8640,  0.8397,  0.1298]])

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: