这一系列文章是对pytorch 入门教程的翻译和学习总结。英文原版可以从以下网址获得:
https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html
目标:
理解Pytorch Tensor 库和神经网络训练一个小的神经网络来分类图片。本手册假定你对numpy库有一个基本的了解。
注意:
确保你的测试环境已经安装了torch 和 torchvision 包
Pytoch是一个基于Python的科学计算的包,目标使用者有两类:
替换NumPy以达到使用GPU算力的目的一个深度学习的研究平台,能够提供最大的灵活性和速度Tensors 类似于 NumPy库中的ndarrays, 而且,Tensor还能够使用GPU做计算加速。
使用torch,首先import torch包,如下
$ python3
from __future__ import print_function
import torch
x = torch.empty(5, 3)
print(x)
输出:
tensor([[1.9160e-11, 0.0000e+00, 8.5305e+02], [1.0894e+27, 8.9683e-44, 0.0000e+00], [4.4842e-44, 0.0000e+00, 1.9160e-11], [0.0000e+00, 1.7857e+05, 3.9586e+12], [1.3452e-43, 0.0000e+00, 4.4842e-44]])注意:
创建一个未初始化的矩阵后,矩阵中的值是不确定的, 使用分配内存时,内存中的值作为初始值。
x = torch.rand(5, 3)
print(x)
输出:
tensor([[1.9160e-11, 0.0000e+00, 8.5305e+02], [1.0894e+27, 8.9683e-44, 0.0000e+00], [4.4842e-44, 0.0000e+00, 1.9160e-11], [0.0000e+00, 1.7857e+05, 3.9586e+12], [1.3452e-43, 0.0000e+00, 4.4842e-44]])创建的矩阵是经过初始化的,初始化为随机值。
x = torch.zeros(5, 3, dtype=torch.long)
print(x)
输出:
tensor([[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]])
创建一个张量并赋值
x = torch.tensor([[2.2, 1.2], [2.1, 1.5], [4.5, 3.1]])
print(x)
输出:
tensor([[2.2000, 1.2000], [2.1000, 1.5000], [4.5000, 3.1000]])
使用new_ones时,新的tensor会继承原来tensor的属性(例如tdype,device等),除非用户指定了新属性。
x = x.new_ones(5, 3, dtype=torch.double) # new_* methods take in sizes
print(x)
x = torch.randn_like(x, dtype=torch.float) # override dtype!
rint(x)
输出:
tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], dtype=torch.float64) tensor([[-0.4050, -0.8701, -0.3150], [ 0.0908, -0.3928, 0.0118], [ 1.0196, 0.0511, 1.0521], [ 0.3389, -0.1678, -0.3757], [-0.2501, 0.4394, 0.2627]])
获取张量的大小:
print(x.size())
输出:
torch.Size([5, 3])
torch.Size()是一个元组,支持所有的元组操作。
torch中有很多运算语法,这里看一下加法运算
x = torch.tensor([1.2, 2.0])
y = torch.tensor([2.1, 3.0])
print(x + y)
print(torch.add(x,y))
输出:
>>> print(x + y) tensor([3.3000, 5.0000])
>>> print(torch.add(x,y)) tensor([3.3000, 5.0000])
result = torch.empty(1, 2)
torch.add(x, y, out=result)
print(result)
输出:
tensor([3.3000, 5.0000])
在变量上加:
y.add(x)
print(y)
y.add_(x)
print(y)
输出:
>>> y.add(x) tensor([3.3000, 5.0000])
>>> print(y) tensor([2.1000, 3.0000])
>>> y.add_(x) tensor([3.3000, 5.0000])
>>> print(y) tensor([3.3000, 5.0000])
注意: 加上“_”的操作会改变变量自己的值,不加"_"的操作,不改变变量的值。
例如x.copy_(y), x.t_(), 将会改变 x的值
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
输出:
>>> x = torch.randn(4,4)
>>> print(x) tensor([[-1.8123, 0.4619, -1.0568, -0.3072], [-0.4922, -0.7467, -0.6142, 0.7062], [-0.3275, 0.3135, 0.1623, 0.2957], [ 0.3594, 0.6116, 0.7314, -0.2364]])
>>> y = x.view(16)
>>> print(y)
tensor([-1.8123, 0.4619, -1.0568, -0.3072, -0.4922, -0.7467, -0.6142, 0.7062, -0.3275, 0.3135, 0.1623, 0.2957, 0.3594, 0.6116, 0.7314, -0.2364])
>>> z = x.view(-1, 8)
>>> print(z)
tensor([[-1.8123, 0.4619, -1.0568, -0.3072, -0.4922, -0.7467, -0.6142, 0.7062], [-0.3275, 0.3135, 0.1623, 0.2957, 0.3594, 0.6116, 0.7314, -0.2364]])
>>> print(x.size(), y.size(), z.size())
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
x = torch.randn(1)
print(x)
print(x.item())
x = torch.randn(2,2)
print(x[1,1].item())
输出:
>>> x = torch.randn(1)
>>> print(x)
tensor([0.0017])
>>> print(x.item())
0.0016834917478263378
>>> x = torch.randn(2,2)
>>> print(x[1,1].item())
0.9299264550209045
可以将一个Torch Tensor转为NumPy array, 也可以将一个NumPy array转为Torch Tensor, 非常方便。
转换之后,Torch Tensor 和 NumPy array底层存储仍然共用相同的内存地址(Tensor在CPU上的情况下), 所以,改变一个值,另一个也会相应改变。
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
输出:
>>> a = torch.ones(5)
>>> print(a)
tensor([1., 1., 1., 1., 1.])
>>> b = a.numpy()
>>> print(b)
[1. 1. 1. 1. 1.]
a的值改变后,b的值也会变:
a.add_(1)
print(a)
print(b)
输出:
>>> a.add_(1)
tensor([2., 2., 2., 2., 2.])
>>> print(b)
[2. 2. 2. 2. 2.]
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
输出:
>>> import numpy as np
>>> a = np.ones(5)
>>> b = torch.from_numpy(a)
>>> np.add(a,1,out=a)
array([2., 2., 2., 2., 2.])
>>> print(b)
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
除了CharTensor之外,CPU上的所有tensors都支持与numpy间的相互转换。
Tensors 可以使用.to() 方法移动到任何device上。
# let us run this cell only if CUDA is available # We will use ``torch.device`` objects to move tensors in and out of GPU if torch.cuda.is_available(): device = torch.device("cuda") # a CUDA device object y = torch.ones_like(x, device=device) # directly create a tensor on GPU x = x.to(device) # or just use strings ``.to("cuda")`` z = x + y print(z) print(z.to("cpu", torch.double)) # ``.to`` can also change dtype together!
输出:
>>> torch.cuda.is_available()
True
>>> device = torch.device("cuda")
>>> y = torch.ones_like(x, device=device)
>>> print(x)
tensor([[ 0.2147, -1.1994], [-0.6267, 0.9299]])
>>> print(y)
tensor([[1., 1.], [1., 1.]], device='cuda:0')
>>> x = x.to(device)
>>> print(x)
tensor([[ 0.2147, -1.1994], [-0.6267, 0.9299]], device='cuda:0')
>>> z = x+y
>>> print(z) tensor([[ 1.2147, -0.1994], [ 0.3733, 1.9299]], device='cuda:0')
>>> print(z.to("cpu", torch.double))
tensor([[ 1.2147, -0.1994], [ 0.3733, 1.9299]], dtype=torch.float64)
完整的用法,见:
https://pytorch.org/docs/stable/torch.html