您的位置 首页 PyTorch 教程

PyTorch深度学习:60分钟入门

PyTorch入门实战教程

某天在微博上看到@爱可可-爱生活 老师推了Pytorch的入门教程,就顺手下来翻了。虽然完工的比较早但是手头菜的没有linux服务器没法子运行结果。开学以来终于在师兄的机器装上了Torch,中间的运行结果也看明白了。所以现在发一下这篇两周之前做的教程翻译。

特别注明:原教程是以ipython notebook写就,因此代码部分非常零散,我在翻译的过程中将部分代码进行了整合以保证文章的紧凑,翻译的目的是将教程说明部分表达完整,具体的代码运行步骤请移步Github下载源文件进行代码的运行。

本教程的目的:

  • 更高层级地理解PyTorch的Tensor库以及神经网络。
  • 训练一个小的神经网络来对图像进行分类。

本教程以您拥有一定的numpy基础的前提下展开

PyTorch是什么?

这是一个基于Python的科学计算包,其旨在服务两类场合:

  • 替代numpy发挥GPU潜能
  • 一个提供了高度灵活性和效率的深度学习实验性平台

我们开搞

Tensors

Tensors和numpy中的ndarrays较为相似, 因此Tensor也能够使用GPU来加速运算。

100+ Tensor的操作,包括换位、索引、切片、数学运算、线性算法和随机数等等。

Numpy桥

将Torch的Tensor和numpy的array相互转换简直就是洒洒水啦。注意Torch的Tensor和numpy的array会共享他们的存储空间,修改一个会导致另外的一个也被修改。

PyTorch中的神经网络

接下来介绍pytorch中的神经网络部分。PyTorch中所有的神经网络都来自于autograd包

首先我们来简要的看一下,之后我们将训练我们第一个的神经网络。

Autograd: 自动求导

autograd 包提供Tensor所有操作的自动求导方法。
这是一个运行时定义的框架,这意味着你的反向传播是根据你代码运行的方式来定义的,因此每一轮迭代都可以各不相同。

以这些例子来讲,让我们用更简单的术语来看看这些特性。

autograd.Variable 这是这个包中最核心的类。 它包装了一个Tensor,并且几乎支持所有的定义在其上的操作。一旦完成了你的运算,你可以调用 .backward()来自动计算出所有的梯度。

你可以通过属性 .data 来访问原始的tensor,而关于这一Variable的梯度则集中于 .grad 属性中。

还有一个在自动求导中非常重要的类 Function。

Variable 和 Function 二者相互联系并且构建了一个描述整个运算过程的无环图。每个Variable拥有一个 .creator 属性,其引用了一个创建Variable的 Function。(除了用户创建的Variable其 creator 部分是 None)。

如果你想要进行求导计算,你可以在Variable上调用.backward()。 如果Variable是一个标量(例如它包含一个单元素数据),你无需对backward()指定任何参数,然而如果它有更多的元素,你需要指定一个和tensor的形状想匹配的grad_output参数。

最终得出的结果应该是一个全是4.5的矩阵。设置输出的变量为o

你可以使用自动求导来做许多疯狂的事情。

神经网络

使用 torch.nn 包可以进行神经网络的构建。

现在你对autograd有了初步的了解,而nn建立在autograd的基础上来进行模型的定义和微分。

nn.Module中包含着神经网络的层,同时forward(input)方法能够将output进行返回。

举个例子,来看一下这个数字图像分类的神经网络。

这是一个简单的前馈神经网络。 从前面获取到输入的结果,从一层传递到另一层,最后输出最后结果。

一个典型的神经网络的训练过程是这样的:

  • 定义一个有着可学习的参数(或者权重)的神经网络
  • 对着一个输入的数据集进行迭代:
    • 用神经网络对输入进行处理
    • 计算代价值 (对输出值的修正到底有多少)
    • 将梯度传播回神经网络的参数中
    • 更新网络中的权重
      • 通常使用简单的更新规则: weight = weight + learning_rate * gradient

让我们来定义一个神经网络:


仅仅需要定义一个forward函数就可以了,backward会自动地生成。

你可以在forward函数中使用所有的Tensor中的操作。

模型中可学习的参数会由net.parameters()返回。

注意: torch.nn 只接受小批量的数据

整个torch.nn包只接受那种小批量样本的数据,而非单个样本。 例如,nn.Conv2d能够结构一个四维的TensornSamples x nChannels x Height x Width。

如果你拿的是单个样本,使用input.unsqueeze(0)来加一个假维度就可以了。

复习一下前面我们学到的:

  • torch.Tensor – 一个多维数组
  • autograd.Variable – 改变Tensor并且记录下来操作的历史记录。和Tensor拥有相同的API,以及backward()的一些API。同时包含着和张量相关的梯度。
  • nn.Module – 神经网络模块。便捷的数据封装,能够将运算移往GPU,还包括一些输入输出的东西。
  • nn.Parameter – 一种变量,当将任何值赋予Module时自动注册为一个参数。
  • autograd.Function – 实现了使用自动求导方法的前馈和后馈的定义。每个Variable的操作都会生成至少一个独立的Function节点,与生成了Variable的函数相连之后记录下操作历史。

到现在我们已经明白的部分:

  • 定义了一个神经网络。
  • 处理了输入以及实现了反馈。

仍然没整的:

  • 计算代价。
  • 更新网络中的权重。

一个代价函数接受(输出,目标)对儿的输入,并计算估计出输出与目标之间的差距。

一个简单的代价函数:nn.MSELoss计算输入和目标之间的均方误差。

举个例子:

现在,如果你跟随loss从后往前看,使用.creator属性你可以看到这样的一个计算流程图:

因此当我们调用loss.backward()时整个图通过代价来进行区分,图中所有的变量都会以.grad来累积梯度。

现在我们已经了解如何使用代价函数了。

只剩下一个没学了:

  • 更新网络的权重

最简单的更新的规则是随机梯度下降法(SGD):

weight = weight – learning_rate * gradient

我们可以用简单的python来表示:


然而在你使用神经网络的时候你想要使用不同种类的方法诸如:SGD, Nesterov-SGD, Adam, RMSProp, etc.

我们构建了一个小的包torch.optim来实现这个功能,其中包含着所有的这些方法。 用起来也非常简单:

就是这样。

但你现在也许会想。

那么数据怎么办呢?

通常来讲,当你处理图像,声音,文本,视频时需要使用python中其他独立的包来将他们转换为numpy中的数组,之后再转换为torch.*Tensor。

  • 图像的话,可以用Pillow, OpenCV。
  • 声音处理可以用scipy和librosa。
  • 文本的处理使用原生Python或者Cython以及NLTK和SpaCy都可以。

特别的对于图像,我们有torchvision这个包可用,其中包含了一些现成的数据集如:Imagenet, CIFAR10, MNIST等等。同时还有一些转换图像用的工具。 这非常的方便并且避免了写样板代码。

本教程使用CIFAR10数据集。 我们要进行的分类的类别有:’airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。 这个数据集中的图像都是3通道,32×32像素的图片。

下面是对torch神经网络使用的一个实战练习。

训练一个图片分类器

我们要按顺序做这几个步骤:

  1. 使用torchvision来读取并预处理CIFAR10数据集
  2. 定义一个卷积神经网络
  3. 定义一个代价函数
  4. 在神经网络中训练训练集数据
  5. 使用测试集数据测试神经网络

1. 读取并预处理CIFAR10

使用torchvision读取CIFAR10相当的方便。

我们来从中找几张图片看看。

结果是这样的:

2. 定义一个卷积神经网络

3. 定义代价函数和优化器

4. 训练网络

事情变得有趣起来了。 我们只需一轮一轮迭代然后不断通过输入来进行参数调整就行了。

我们已经训练了两遍了。 此时需要测试一下到底结果如何。

通过对比神经网络给出的分类和已知的类别结果,可以得出正确与否,如果预测的正确,我们可以将样本加入正确预测的结果的列表中。

好的第一步,让我们展示几张照片来熟悉一下。

结果是这样的:

好的,接下来看看神经网络如何看待这几个照片。

结果看起来挺好。

看看神经网络在整个数据集上的表现结果如何。

看上去这玩意输出的结果比随机整的要好,随机选择的话从十个中选择一个出来,准确率大概只有10%。

看上去神经网络学到了点东西。

嗯。。。那么到底哪些类别表现良好又是哪些类别不太行呢?

好吧,接下来该怎么搞了?

我们该如何将神经网络运行在GPU上呢?

在GPU上进行训练

就像你把Tensor传递给GPU进行运算一样,你也可以将神经网络传递给GPU。

这一过程将逐级进行操作,直到所有组件全部都传递到GPU上。

记住,每一步都需要把输入和目标传给GPU。

我为什么没有进行CPU运算和GPU运算的对比呢?因为神经网络实在太小了,其中的差距并不明显。

目标达成:

  • 在更高层级上理解PyTorch的Tensor库和神经网络。
  • 训练一个小的神经网络。

文章来源:知乎专栏

PyTorch入门实战教程

发表评论

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

评论列表(2)

  1. 不明白为什么上面x.grad为什么是4.5,通过求导推断病没有算出来
    out=1/4*(\sum_i=1^4{3*(x_i + 2)^2})
    对x的导数是怎么算成4.5的这一步不知道pytorch是怎么算的,求解答

返回顶部