作为目前越来越受欢迎的深度学习框架,pytorch 基本上成了新人进入深度学习领域最常用的框架。相比于 TensorFlow,pytorch 更易学,更快上手,也可以更容易的实现自己想要的 demo。今天的文章就从 pytorch 的基础开始,帮助大家实现成功入门。
首先,本篇文章需要大家对深度学习的理论知识有一定的了解,知道基本的 CNN,RNN 等概念,知道前向传播和反向传播等流程,毕竟本文重点是一篇实操性的教程。
其次,这篇文章我更想从一个总体性的视角展开,大家在学习的过程中更注重的应该是在接触新知识时,如何设计学习路线的一种思路分享。这种思路不一定适合所有人,但是肯定可以对你有所借鉴,你也可以基于此总结出来更适合自己的方法。
接下来我们从以下几个步骤去帮助大家入门 pytorch 的实战教程。
开始一个简单的分类器
在 MNIST 上实现一个 cnn
常用网络层介绍
tensorboard 可视化
以 vgg 为例实现深层网络的一些小技巧
GPU 加速和保存加载模型
RNN 和 LSTM 实现分类和回归
番外: 一个并行生成数据的例子告诉你,pytorch 未来的路该怎么做
这八个步骤,对应了我的八篇学习笔记的文章,本文是从一个串讲的思路来介绍学习路径,对应步骤的更多细节会在具体的文章中展示。在每个步骤介绍的最后和全文的结尾,我们也会给出文章的链接,大家可以针对性食用~
开始一个简单的分类器
我个人在学习一门新语言,一个新框架,一个新技术时,最优先要保证的就是成就感反馈。以学习 pytorch 为例,很多教程从张量开始。我自己也按照这种教程学习过,的确内容非常全尽,但是有两个原因,我自己不太推荐以这种方式入门:1)前期学习过于枯燥,没有成就感;2)有的知识内容属于深度学习的基本功,过于赘述。
所以我觉得入门一个新知识的知识,最好是先搭起来结构,然后再去慢慢补充细节。因此我在这篇文章的第一部分,先选择构建一个简单的分类器,让大家知道一个 pytorch 下的代码流程应该是什么样子。
学过 c 语言的朋友肯定知道,我们先学第一个代码的时候,肯定是先来一个 hello world,而不是去研究第一行的 #include。
对于第一个 pytorch 程序而言,我们要做的是首先跑通整个流程,如果是一个简单的分类器,数据集也就不能太复杂。因此,我们从三方面考虑:1)自定义生成一些点,分为两类;2)学习如何构建一个浅层的神经网络;3)尝试 pytorch 中的训练和测试过程。
1.1 自定义生成数据集
首先,自定义生成我们的数据集。利用 torch 自带的 zeros,ones 这些方法,我们生成一些随机的点,分为两类。比如分别以(2,2)和(-2,-2)为均值,随机生成一些随机数,作为两类,这样子我们就得到了我们想要的数据集。
1.2 学会构建网络的流程
其次,就是构建一个浅层的神经网络,这里我们给出一个代码示例,大家了解一下最基础的 pytorch 的网络应该如何构建:
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.n_hidden = torch.nn.Linear(n_feature, n_hidden)
self.out = torch.nn.Linear(n_hidden, n_output)
def forward(self, x_layer):
x_layer = torch.relu(self.n_hidden(x_layer))
x_layer = self.out(x_layer)
x_layer = torch.nn.functional.softmax(x_layer)
return x_layer
net = Net(n_feature=2, n_hidden=10, n_output=2)
# print(net)
optimizer = torch.optim.SGD(net.parameters(), lr=0.02)
loss_func = torch.nn.CrossEntropyLoss()
这个 Net 类,就是我们构建的代码框架,用它生成的对象就是一个我们可以用来训练和测试的网络。这个类中,初始化函数中表示了每个网络层的结构设置,而 forward() 方法表示了每个层之间的交互顺序和关系。
而 optimizer 就是优化器,包含了需要优化的参数有哪些,loss_func 就是我们设置的损失函数。
这个就像我们写一个 hello,world 一样,我们只需要知道自己该如何构造一个网络。当我们需要调整的时候,就将其中对应的模块替换掉。
1.3 训练与测试
接下来就是训练与测试的阶段。训练我们需要知道三句代码是核心:
optimizer.zero_grad()
loss.backward()
optimizer.step()
这里的核心思路是,梯度清空,反向传播,参数更新。分别对应了这三句代码的作用。在pytorch 中,梯度会保留,所以需要用 zero_grad() 来清空,然后利用损失函数反向传播计算梯度,最后就是用我们定义的优化器将每个需要优化的参数进行更新。
测试阶段就很简单了,直接将输入丢进去就可以看到预测结果。现在我们重新随机生成一些数据点作为测试集,可以看到训练集对它的分类结果就很明显。
至此,我们就完成了一个对于简单分类器的描述。