LinMao's Blog
学习科研记录与分享!

PyTorch Get Started

创建数据集

PyTorch 有两种方式来处理数据,一种 torch.utils.data.Datasettorch.utils.data.DataLoader,前者存储数据集和对应的label,后者封装数一个数据集的可迭代对象。

PyTorch 提供一些不同领域特有的库,比如 torchtexttorchvision,和 torchaudio。这些库包含对应的领域的常见数据集,模型,和操作。torchvision.datasets 包含许多计算机视觉方向的数据集,比如,CIFAR,COCO,等等(包含的所有数据集)。每一个 torchvision dataset 包含两个选项:transformtarget_transform 来修改数据和label。

接下来,将 dataset 作为参数传到 DataLoader。DataLoader 提供一个可迭代对象,能够自动的 batching,sampling,shuffling,和 multiprocess data loading。

显示数据集

为了比较直观看看数据集的样子,下面代码显示数据集图标和标签,这一步在训练的时候是不需要的。

创建模型

在 PyTorch 中,通过继承类 torch.nn.Module 来定义一个网络模型,神经网络的层定义在 __init__ 函数中,并通过 forward 函数来指定数据是如何在网络中传递的。如果平台允许,可以将网络移动到 GPU 来加速神经网络的计算。

 

模型参数优化(训练)

为了训练神经网络,需要定一个损失函数(loss function)和优化器(optimizer)。 损失函数:用来评估模型的预测值 f(x) 与真实值 Y 的不一致程度,是一个非负的实值函数,通常用 L(Y, f(x)) 来表示,损失函数越小,模型越好。

优化器:在深度学习反向传播过程中,指引损失函数(目标函数)的各个参数往正确的方向更新合适的大小,使得更新后的各个参数让损失函数值不断逼近全局最小。

在一次模型训练迭代中,模型以 batch 为单位的训练集上进行预测,然后反向传播预测的错误来调整模型的参数。

训练过程通常会进行多个iterations(epochs)。在每个epochs,模型学习新的参数来达到更好的预测效果。上面代码中打印每一个 epochs 里面准确率和误差,随着 epochs 的增加,通常希望看到准确率增加,误差减少。

模型保存与加载

保存模型

当模型训练完了,需要将模型保存到文件,便于下次接着训练,或者在部署时使用。保存模型通常就是序列化地保存内部状态字典(internal state dictionary),内部状态字典包含模型的权重。

加载模型

加载模型包含重新创建模型结构和加载状态字典(权重)。

使用模型

将上面加载的模型来做预测。

 

总结

之前只有过用 Darknet 训练目标识别神经网络的经历,对于 PyTorch 训练神经网络的过程其实一直不是很熟悉。用 Darknet 训练的过程:首先是制作数据集,制作数据集的时候要手动的把照片和标签放到指定的文件夹,然后写清楚类别和数据集信息;然后是训练,选择合适网络配置文件(cfg 文件),设置里面的各种超参数,和指定生成的权重文件;最后是测试,读取训练的权重然后测试输入的图片。其实 PyTorch 和这个过程本质上是一样的:PyTorch 首先也是创建数据集,与 Darknet 需要手动创建不同,PyTorch 可以通过代码来提供数据集,并且常见的数据集都包含在 torchvisiontorchtext,和torchaudio里面,这就给开发者极大的方便,另外,这三个库不仅包含相应领域常见的数据集,还包括了相应领域的常见操作的库。另外,数据集通过 DataLoader 封装成可迭代的对象,极大的方便了使用数据集,并且不同数据集的使用方式是统一的。与Darknet 里面通过 cfg 文件来定义模型不一样,PyTorch 里面通过继承 torch.nn.Module 类来定义模型,模型结构定义在类中的 __init__ 函数中,这一点也比较灵活。接着就是 PyTorch 的训练,感觉训练与 Darknet 的区别很大,PyTorch 模型结构定义与损失函数和优化器定义是分开的。感觉 Darknet 里面好像并没有着重讨论这个部分,我猜测可能是把这部分和模型绑定直接写到了 cfg 文件了,也有可能是当时的模型比较简单,使用的损失函数和优化器种类有限,所以没有提供自定义的选项。PyTorch 里面提供这些,可以让模型研究者灵活调用,很容易设计出他们自己的模型,可能这就是 PyTorch 能够如此成功的原因吧。另外还有一个,PyTorch 提供链式求导和使用优化器更新参数,就需要调用 loss.backward()optimizer.step() 两个 API 就把反向传播,梯度下降,权重更新给完成了,不可谓不神奇,这一部分如果要是自己实现,是又麻烦又容易出错。另外,在训练的时候,数据集在创建 DataLoader 的时候根据 batch size 生成对应的迭代对象,然后在训练时只需要遍历迭代对象就可以,每次取出的 batch size 个 数据标签对,放到模型中计算。整体感觉 PyTorch 让定义一个模型的过程变得更加快捷简单,并且内置了丰富的数据集,让对模型的验证也变得非常简单,经过这个过程,确实更加深刻的理解了 PyTorch 的优势了。

另外,对于几个概念也有了一个认识,PyTorch 里面的 batch size 是作用于 DataLoader,从而让一次训练迭代输入更大的数据。所有数据完整训练一遍称之为一个 epoch。另外,对于模型而言,有一个概念之前一直没有搞明白,就是 iteraion。我不知道深度学习里面是不是真的有这个概念,但是我之前 project 讨论的时候经常提到这个概念:就是对于给定输入,神经网络走完一遍网络计算图(正向或者反向)的过程。有一个疑问是,这个过程中,对于给定的 batch size,是 batch size 张图片同时输入并参与一次正向传播,还是这些图片一张一张参与正向。这是一个非常存疑的问题,我倾向于前者,但是后者似乎也能说得通。mark一下,后续解决。

赞(9) 打赏
转载请注明出处:LinMao's Blog(林茂的博客) » PyTorch Get Started

评论 3

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    感谢博主,让我PyTorch入了门!

    Xiaohui10个月前 (07-03)回复
    • 哈哈哈,咋还回复上了,现在才看到…

      linmao7个月前 (10-14)回复
  2. #2

    对于iteration,从网络的训练的角度就是step,但是也叫iteration(https://pytorch.org/tutorials/intermediate/tensorboard_profiler_tutorial.html#use-profiler-to-record-execution-events)

    linmao10个月前 (07-04)回复

LinMao's Blog(林茂的博客)

了解更多联系我们

觉得文章有用就打赏一下作者吧~

支付宝扫一扫打赏

微信扫一扫打赏