说明:本系列教程翻译自PyTorch官方教程《Deep Learning with PyTorch: A 60 Minute Blitz》,基于PyTorch 0.3.0.post4
教程目标
- 在高层次上理解PyTorch的
Tensor
库和神经网络 - 训练一个小型的神经网络来分类图像
前提条件
- 假设读者熟悉基础的
NumPy
库 - 确保已经安装了
torch
和torchvision
包
Posted 机器学习初学者
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(翻译)60分钟入门深度学习工具-PyTorch相关的知识,希望对你有一定的参考价值。
作者:Soumith Chintala
原文翻译自:
一、Pytorch是什么? 二、AUTOGRAD 三、神经网络 四、训练一个分类器 五、数据并行 他是一个基于Python的科学计算包,目标用户有两类
为了使用GPU来替代numpy 开始 一个深度学习研究平台:提供最大的灵活性和速度 张量(Tensors)
张量类似于numpy的ndarrays,不同之处在于张量可以使用GPU来加快计算。
__future__ print_function
torch构建一个未初始化的5*3的矩阵:
x = torch.Tensor( [ 0.0000e+00, 7.0065e-45, 0.0000e+00],
[-3.8593e+35, 7.8753e-43, 0.0000e+00],
[ 0.0000e+00, 1.8368e-40, 0.0000e+00],
[-3.8197e+35, 7.8753e-43, 0.0000e+00]])构建一个零矩阵,使用long的类型
x = torch.zeros( [0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])从数据中直接构建一个张量(tensor):
x = torch.tensor([ [1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[ 1.1701, -0.8342, -0.6769],
[-1.3060, 0.3636, 0.6758],
[ 1.9133, 0.3494, 1.1412],
[ 0.9735, -0.9492, -0.3082],
[ 0.9469, -0.6815, -1.3808]])获取张量(tensor)的大小
print(x.size())
torch.Size([5, 3])
** 注意 **
操作
torch.Size
实际上是一个元组,所以它支持元组的所有操作。张量上的操作有多重语法形式,下面我们以加法为例进行讲解。
语法1
y = torch.rand( [-0.5413, 1.1591, 1.4098],
[ 2.0421, 0.5578, 2.0645],
[ 1.7301, -0.3236, 0.4616],
[ 1.2805, -0.4026, -0.6916]])语法二
print(torch.add(x, y))
tensor([[ 1.7199, -0.1819, -0.1543],
[-0.5413, 1.1591, 1.4098],
[ 2.0421, 0.5578, 2.0645],
[ 1.7301, -0.3236, 0.4616],
[ 1.2805, -0.4026, -0.6916]])语法三:
给出一个输出张量作为参数
result = torch.empty( [-0.5413, 1.1591, 1.4098],
[ 2.0421, 0.5578, 2.0645],
[ 1.7301, -0.3236, 0.4616],
[ 1.2805, -0.4026, -0.6916]])语法四:
原地操作(in-place)
[-0.5413, 1.1591, 1.4098],
[ 2.0421, 0.5578, 2.0645],
[ 1.7301, -0.3236, 0.4616],
[ 1.2805, -0.4026, -0.6916]])注意
任何在原地(in-place)改变张量的操作都有一个
_
后缀。例如x.copy_(y)
,x.t_()
操作将改变x.你可以使用所有的
numpy
索引操作。你可以使用各种类似标准NumPy的花哨的索引功能
print(x[:, numpy np
a = np.ones(torch.cuda.is_available():
device = torch.device( y = torch.ones_like(x, device=device) x = x.to(device) z = x + y
print(z)
print(z.to(PyTorch 中所有神经网络的核心是
autograd
包.我们首先简单介绍一下这个包,然后训练我们的第一个神经网络.
autograd
包为张量上的所有操作提供了自动求导.它是一个运行时定义的框架,这意味着反向传播是根据你的代码如何运行来定义,并且每次迭代可以不同.接下来我们用一些简单的示例来看这个包:
张量(Tensor)
torch.Tensor
是包的核心类。如果将其属性.requires_grad
设置为True,则会开始跟踪其上的所有操作。完成计算后,您可以调用.backward()
并自动计算所有梯度。此张量的梯度将累积到.grad
属性中。要阻止张量跟踪历史记录,可以调用
.detach()
将其从计算历史记录中分离出来,并防止将来的计算被跟踪。要防止跟踪历史记录(和使用内存),您还可以使用torch.no_grad()包装代码块:在评估模型时,这可能特别有用,因为模型可能具有
requires_grad = True
的可训练参数,但我们不需要梯度。还有一个类对于autograd实现非常重要 - Function。
Tensor和Function互相连接并构建一个非循环图构建一个完整的计算过程。每个张量都有一个
.grad_fn
属性,该属性引用已创建Tensor的Function(除了用户创建的Tensors - 它们的grad_fn
为None
)。如果要计算导数,可以在Tensor上调用
.backward()
。如果Tensor是标量(即它包含一个元素数据),则不需要为backward()
指定任何参数,但是如果它有更多元素,则需要指定一个梯度参数,该参数是匹配形状的张量。torch
创建一个张量并设置
requires_grad = True
以跟踪它的计算x = torch.ones( [1., 1.]], requires_grad=True)
在张量上执行操作:
y = x + [3., 3.]], grad_fn=<AddBackward0>)
因为y是通过一个操作创建的,所以它有grad_fn,而x是由用户创建,所以它的grad_fn为None.
print(y.grad_fn)
print(x.grad_fn)<AddBackward0 object at 0x000001E020B794A8>
None在y上执行操作
z = y * y * [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward1>)
.requires\\_grad_(...)
就地更改现有的Tensor的requires_grad
标志。如果没有给出,输入标志默认为False。a = torch.randn( [4.5000, 4.5000]])
你应该得到一个值全为4.5的矩阵,我们把张量out称为"y.data.norm() < y = y * torch.no_grad():
print((x **可以使用
torch.nn
包来构建神经网络.你已知道
autograd
包,nn
包依赖autograd
包来定义模型并求导.一个nn.Module
包含各个层和一个forward(input)
方法,该方法返回output
.例如,我们来看一下下面这个分类数字图像的网络.
它是一个简单的前馈神经网络,它接受一个输入,然后一层接着一层的输入,直到最后得到结果。
神经网络的典型训练过程如下:
定义神经网络模型,它有一些可学习的参数(或者权重); 在数据集上迭代; 通过神经网络处理输入; 计算损失(输出结果和正确值的差距大小) 将梯度反向传播会网络的参数; 定义网络 更新网络的参数,主要使用如下简单的更新原则: weight = weight - learning_rate * gradient
我们先定义一个网络:
torch
torch.nn nn
torch.nn.functional F
super(Net, self).__init__()
self.conv1 = nn.Conv2d( self.conv2 = nn.Conv2d( self.fc1 = nn.Linear(* * self.fc2 = nn.Linear( self.fc3 = nn.Linear( x = F.max_pool2d(F.relu(self.conv1(x)), ( x = F.max_pool2d(F.relu(self.conv2(x)), x = x.view( x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
x
size = x.size()[ num_features = s size:
num_features *= s
num_features
net = Net()
print(net)Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)你只需定义
forward
函数,backward
函数(计算梯度)在使用autograd
时自动为你创建.你可以在forward
函数中使用Tensor
的任何操作。
net.parameters()
返回模型需要学习的参数。params = list(net.parameters())
print(len(params))
print(params[ 0.0867, 0.0102]], grad_fn=<AddmmBackward>)将所有参数的梯度缓存清零,然后进行随机梯度的的反向传播.
net.zero_grad()
out.backward(torch.randn(只支持小批量输入,整个torch.nn
包都只支持小批量样本,而不支持单个样本
例如,nn.Conv2d
将接受一个4维的张量,每一维分别是张量的梯度累积。
为了说明,我们反向跟踪几步:
print(loss.grad_fn) f net.parameters():
f.data.sub_(f.grad.data * learning_rate)
然而,当你使用神经网络是,你想要使用各种不同的更新规则,比如SGD,Nesterov-SGD
,Adam
, RMSPROP
等.为了能做到这一点,我们构建了一个包torch.optim
实现了所有的这些规则.使用他们非常简单:
torch.optim optim
你已经学会如何去定义一个神经网络,计算损失值和更新网络的权重。
你现在可能在思考:数据哪里来呢?
关于数据通常,当你处理图像,文本,音频和视频数据时,你可以使用标准的Python包来加载数据到一个numpy数组中.然后把这个数组转换成torch.*Tensor
。
对于图像,有诸如Pillow,OpenCV包等非常实用 对于音频,有诸如scipy和librosa包 对于文本,可以用原始Python和Cython来加载,或者使用NLTK和SpaCy
对于视觉,我们创建了一个torchvision
包,包含常见数据集的数据加载,比如Imagenet,CIFAR10,MNIST等,和图像转换器,也就是torchvision.datasets
和torch.utils.data.DataLoader
。 这提供了巨大的便利,也避免了代码的重复。
在这个教程中,我们使用CIFAR10数据集,它有如下10个类别:’airplane’,’automobile’,’bird’,’cat’,’deer’,’dog’,’frog’,’horse’,’ship’,’truck’。这个数据集中的图像大小为3*32*32,即,3通道,32*32像素。
训练一个图像分类器我们将按照下列顺序进行:
使用torchvision
加载和归一化CIFAR10训练集和测试集. 定义一个卷积神经网络 定义损失函数 在训练集上训练网络 在测试集上测试网络 1. 加载和归一化CIFAR0
使用torchvision
加载CIFAR10是非常容易的。
torch
torchvision
torchvision.transforms transforms
torchvision的输出是[0,1]的PILImage图像,我们把它转换为归一化范围为[-1, 1]的张量。
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize(( download= shuffle= download= shuffle= matplotlib.pyplot plt
numpy np
img = img / + npimg = img.numpy()
plt.imshow(np.transpose(npimg, ( plt.show()
% classes[labels[j]] j range(torch.nn nn
torch.nn.functional F
super(Net, self).__init__()
self.conv1 = nn.Conv2d( self.pool = nn.MaxPool2d( self.conv2 = nn.Conv2d( self.fc1 = nn.Linear(* * self.fc2 = nn.Linear( self.fc3 = nn.Linear( x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(* * x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
x
net = Net()
3. 定义损失函数和优化器
我们使用交叉熵作为损失函数,使用带动量的随机梯度下降。
torch.optim optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=epoch range( running_loss = i, data enumerate(trainloader, inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
i % == print(%
(epoch + running_loss = % classes[labels[j]] j range(% classes[predicted[j]]
j range(torch.no_grad():
data testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, total += labels.size( correct += (predicted == labels).sum().item()
print(% (
* correct / total))
Accuracy of the network on the 10000 test images: 54 %
结果看起来好于偶然,偶然的正确率为10%,似乎网络学习到了一些东西。
那在什么类上预测较好,什么类预测结果不好呢?
class_correct = list(i range(i range(torch.no_grad():
data testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs, c = (predicted == labels).squeeze()
i range( label = labels[i]
class_correct[label] += c[i].item()
class_total[label] += i range( print(% (
classes[i], * class_correct[i] / class_total[i]))
Accuracy of plane : 52 %
Accuracy of car : 63 %
Accuracy of bird : 43 %
Accuracy of cat : 33 %
Accuracy of deer : 36 %
Accuracy of dog : 46 %
Accuracy of frog : 68 %
Accuracy of horse : 62 %
Accuracy of ship : 80 %
Accuracy of truck : 63 %
接下来干什么?
我们如何在GPU上运行神经网络呢?
在GPU上训练你是如何把一个Tensor转换GPU上,你就如何把一个神经网络移动到GPU上训练。这个操作会递归遍历有所模块,并将其参数和缓冲区转换为CUDA张量。
device = torch.device(torch.cuda.is_available() (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
请记住,你也必须在每一步中把你的输入和目标值转换到GPU上:
inputs, labels = inputs.to(device), labels.to(device)
为什么我们没注意到GPU的速度提升很多?那是因为网络非常的小。
实践:
尝试增加你的网络的宽度(第一个nn.Conv2d
的第2个参数, 第二个nn.Conv2d
的第一个参数,他们需要是相同的数字),看看你得到了什么样的加速。
实现的目标:
深入了解了PyTorch的张量库和神经网络 训练了一个小网络来分类图片 本章的官方代码:
Jupyter notebook:
作者:Sung Kim和Jenny Kang
在这个教程里,我们将学习如何使用数据并行(DataParallel)来使用多GPU。
PyTorch非常容易的就可以使用GPU,你可以用如下方式把一个模型放到GPU上:
device = torch.device("cuda:0")
model.to(device)
然后你可以复制所有的张量到GPU上:
mytensor = my_tensor.to(device)
请注意,只调用mytensor.gpu()
并没有复制张量到GPU上。你需要把它赋值给一个新的张量并在GPU上使用这个张量。
在多GPU上执行前向和反向传播是自然而然的事。然而,PyTorch默认将只是用一个GPU。你可以使用DataParallel
让模型并行运行来轻易的让你的操作在多个GPU上运行。
model = nn.DataParallel(model)
这是这篇教程背后的核心,我们接下来将更详细的介绍它。
导入和参数导入PyTorch模块和定义参数。
torch
torch.nn nn
torch.utils.data Dataset, DataLoader
torch.cuda.is_available() self.len = length
self.data = torch.randn(length, size)
self.data[index]
self.len
rand_loader = DataLoader(dataset=RandomDataset(input_size, data_size),
batch_size=batch_size, shuffle= super(Model, self).__init__()
self.fc = nn.Linear(input_size, output_size)
output = self.fc(input)
print( output
创建一个模型和数据并行这是本教程的核心部分。首先,我们需要创建一个模型实例和检测我们是否有多个GPU。如果我们有多个GPU,我们使用nn.DataParallel
来包装我们的模型。然后通过model.to(device)
把模型放到GPU上。
model = Model(input_size, output_size)
torch.cuda.device_count() > print( model = nn.DataParallel(model)
model.to(device)
Model(
(fc): Linear(in_features=5, out_features=2, bias=True)
)
运行模型现在我们可以看输入和输出张量的大小。
data rand_loader:
input = data.to(device)
output = model(input)
print( 翻译版本github下载:
https://github.com/fengdu78/machine_learning_beginner/tree/master/PyTorch_beginner
备注:公众号菜单包含了整理了一本AI小抄,非常适合在通勤路上用学习。
往期精彩回顾
2019年公众号文章精选
适合初学者入门人工智能的路线及资料下载
机器学习在线手册
深度学习在线手册
AI基础下载(第一部分)
备注:加入本站微信群或者qq群,请回复“加群”
加入知识星球(4500+用户,ID:92416895),请回复“知识星球”
喜欢文章,点个在看
说明:本系列教程翻译自PyTorch官方教程《Deep Learning with PyTorch: A 60 Minute Blitz》,基于PyTorch 0.3.0.post4
Tensor
库和神经网络NumPy
库torch
和torchvision
包以上是关于(翻译)60分钟入门深度学习工具-PyTorch的主要内容,如果未能解决你的问题,请参考以下文章
PyTorch深度学习60分钟快速入门 Part1:PyTorch是什么?
PyTorch 60 分钟入门教程:PyTorch 深度学习官方入门中文教程
PyTorch深度学习60分钟快速入门 Part2:Autograd自动化微分