美文网首页
2019-04-30 手把手教你用pytorch实现迁移学习(第

2019-04-30 手把手教你用pytorch实现迁移学习(第

作者: QQsoso | 来源:发表于2019-05-02 21:46 被阅读0次

    一.任务概述

    在开始进行数据处理之前需要先总体说一下我们在这一节要做的一些工作:

    1.理解数据加载器(Dataloader)的概念以及Pytorch的数据加载器API(Dataloader);

    2.将图像划分为训练集/验证集和测试集;

    3.创建Pytorch Dataloader来在训练/验证和预测时按照某种规则提供图像;

    4.使用Pytorch Transforms API来预处理数据集以便进行更高效的训练;

    5.使用 Pytorch API来将所有的图像转换为Pytorch张量;

    6.使用图像平均值和标准差来正则化数据集。

    二.数据加载器-Datalaoder

    Pytorch中的Dataloader是功能和Python生成器一样的对象,在训练和验证期间,他们按照批次(Batch)提供数据。我们可以实例化Dataloader对象并且将数据集传给它。Dataloader在内部存储数据集对象。

    当程序请求下一批(batch)数据时,Dataloader使用其存储的数据集作为Python迭代器来获取下一个数据元素(在我们的例子中是下一行或者下一个图像),然后它收集一批次(batch)数据并将其返回给程序。

    以下是调用Dataloader的实例:

    调用Dataloader

    通过上面的语句,我们为我们的训练数据集创造了一个Batch为50的dataloader对象,Sampler参数指定了我们在构建Batch数据时要使用的数据采样策略。torch.utils.data.sampler中提供了不同的采样器。您可以在pytorch文档中的相关页面阅读它们。本文中的SubsetRandomSampler代表无放回地按照给定的索引列表采样样本元素。

    num_workers参数指定加载数据时要使用多少进程,这在加载大型数据集时提供了并行性。默认值为0,表示加载主进程中的所有数据。

    Dataloader长度

    Dataloader以Batch数目表示其长度。因为我们创建了Batch size大小为50的Dataloader,并且在我们的训练数据集中有50000个图像,所以我们的Dataloader长度为1000个Batch。

    三 划分数据集

    接下来,让我们写一个函数将其拆分为训练集/验证集和测试集,并创建相应的Datalaoder。

    让我们先设想一下这个函数是什么样子的,它需要以训练数据和测试数据作为输入参数,测试数据可以设置默认值为None,因为我们可以直接将训练数据分为训练/测试/验证三个数据集,这样就不需要测试数据的参与了。但是如果测试数据不是None的话,我们就只需要把训练数据分成训练集和验证集,然后从测试数据中构造一个独立的Dataloader。

    图像数据集划分函数

    接下来,让我们调用这个函数来获取Dataloader:

    现在我们就有了一个800Batch的训练集和200Batch的验证集了,测试集是根据测试数据单独定义的。

    四 CNN

    尽管我们假设你对CNN已经有了基本的认识,但是如果你想要回顾CNN的核心概念,可以查看以下教程:Neural Networks CS231n Stanford| |CNN Tutorial: AnalyticsVidhya| |A Very Comprehensive Tutorial on ANN and CNN by Kaggle

    五 数据集的预处理和转换

    在定义网络和开始训练之前,我们还需要对数据集进行预处理,具体步骤如下:

            将图像调整到适合模型的大小;

            执行一些基本并且最常见的数据填充;

            将图像的dat转换为Pytorch张量;

            标准化图像数据。

    先来解决第一个问题:为什么我们需要将图像调整到合适的大小?

    大多数迁移学习模型都要求数据大小至少为224x224。这种限制的原因是,这些模型设计有大量的卷积和池化层,最后是一个全连接(线性)层,以生成分类输出。当输入图像到达最后一层时,由于卷积和池化的过程,它的大小已经大大减小。如果输入图像已经太小(如我们的例子中的32x32 CIFAR10图像),那么对于网络来说,它实在是太小以至于无法产生任何有效的输出。因此,这些模型会限制我们必须要输入一个大于等于224x224的图像。

    但是如果我们的图像已经超过224x224,比如在ImageNet数据集中,或者我们需要使用我们自己的CNN架构时,在通过层时不会过多地减小图像尺寸,这时我们就不需要调整大小。尽管将较小的图像调整为较大的图像(如我们的示例)会创建一些理想情况下不希望模型学习的内容,但是由于图像实在太小并且使用的迁移模型有这个需求,所以我们必须调整大小。

    对于具有较大图像的数据集,我们的GPU或CPU内存约束可能成为一个因素。因此,我们将缩小规模与增加Batch size相结合(直到达到Batch size限制),以优化模型性能并平衡缩小规模的影响。

    接下来介绍数据扩充(Data Augmentation)的一些概念:

    数据扩充(Data Augmentation)是一种常见的深度学习技术,我们在训练的同时对图像进行实时修改,以使神经网络看到以不同轴和角度旋转的图像。这通常会增强训练性能,因为网络可以看到同一图像的多个视图,并且能够更好地最小化损失函数并分类。

    需要注意的是,增加的图像不会添加到数据集中,它们只是在生成Batches时创建的,因此在训练期间看到的实际图像会增加,但数据集中的图像数量不会增加。数据长度以及其他计算图像数量的函数也不会有所改变。我们经常使用以下两种数据扩充方式:

        1.随机水平翻转(RandomHorizontaFlip):以概率p(默认值为0.5)围绕垂直轴翻转某些图像,也就是翻转50%的图像。

        2.随机翻转(RadomRotation):以某一特定的角度(一般是10度)按照概率p(默认0.5)进行图像旋转,也就是大概50%的图像以10度的角度随机旋转。

    对图像进行大小调整和数据扩充

    数据标准化(data normalization)

    为了使训练性能更好并且可以更快收敛,我们需要对图像中的像素值进行统计标准化。一种常见的标准化方法是对每个像素,减去数据集的像素平均值,然后除以数据集像素的标准差。

    在迁移学习中,最常见的方法是使用原始迁移学习模型所训练的数据集的均值和标准差。当我们不再希望重新训练原始模型时,这可能是一个很好的策略。但是如果数据集很大,或者我们希望重新训练模型的某个部分或者全部时,我们最好使用要迁移领域数据集的标准差和均值进行标准化(在这个例子中是CIFRA10)。然而在大多数的迁移学习教程中,都会使用ImageNet的均值和标准差。

    接下来,我将展示给您两个计算均值和标准差的pytorch函数:

    第一个函数是,“calculate_img_stats_avg”,这是基于Dataloader的韩式,它可以计算从数据集对象中检索到的每个Batch的数据均值(mean)和标准差(std)。虽然这个函数只是给了我们一个近似的值,但是对那些不能同时装入内存的大型数据集,我们可以合理使用它。

    第二个函数 "calculate_img_stats_full"要一次性处理整个数据集来计算数据均值和标准差,它的值肯定更为准确,但是对大数据来说,可能会耗尽内存。对于cifar10来说,这个函数需要28GB的RAM,我的机器实在是望尘莫及。

    您可以尝试在特定的数据集上运行第二个函数,如果遇到内存问题,则返回到第一个函数以获得良好的近似值。然而,在cifar10的情况下,许多人已经计算了数据集的均值和标准差,并且这些值是众所周知的,imagenet也是如此。因此我们在下面的代码中会直接使用这些值。我没有尝试使用第一个函数给出的近似值,但欢迎您进行尝试。

    将数据集转换为tensor

    在上图代码中,我们先是创建了一个包含所有数据的数据集,然后创建了一个Dataloader来在接下来的循环中分批次(每次50张图片)来给模型喂数据。

    需要注意的一点是,为了让Dataloader能够正常工作,图片必须转换为tensor,所以我们在第一句中要定义一个transform转换函数。

    接下来我们直接定义函数来计算每个批次(Batch)的均值和标准差,然后将它们按照批次不断累积,最后除以总数得到总均值。

    计算数据集均值和标准差

    当然,在这里我们也编写了一个计算总体均值和标准差的函数:

    在这个一次性计算的函数中,我们用了torch.stack函数沿着给定的维度(在我们这个例子汇中是3维)来堆叠数据。然后接下来的view操作将Tensor视为3x(所有其他维度的乘积),这个操作在保持第一维为3的时候flatten其他函数。

    把一个模糊函数中正在发生的事情形象化的最好方法是复制隔离语句,并向它们提供一些虚拟的张量来观察正在发生的事情。我把它留给你做练习。

    当然,最终我们用的均值和标准差都是网上有大神计算出来的:

    现在,所有的操作都已经讲解完了,我们可以从头开始创建数据集,应用到上面所讲的所有转换/数据扩充以及数据标准化操作,并将其拆分为训练集与测试集,获得最终的Dataloader。我们在定义Dataloader中使用的Batch size依然是50.

    可以看到,我们的数据扩充操作只是在训练集中用了。我们通常不对测试集应用数据扩充,因为我们希望测试数据尽可能接近真实数据。例如,我们的模型可能错误地分类了一个测试图像,但在翻转和旋转的版本中,它的分类却是正确的。这种操作可能错误地提高了整体准确性,会对结果产生误导。

    尽管如此,有一种称为测试时间扩充(Test Time Augmentation (TTA) )的技术可以在测试过程中,在显示训练模型与原始图像的所有(扩充)变化后,对测试数据进行扩充,并对预测进行平均。这可能会带来更高的准确性。我们不会在本教程中使用它,但您可以在this tutorial中了解更多信息。

    数据预处理和准备工作就到此为止啦,在接下来教程中,我们将要学习为创建神经网络做准备!

    目录见:主页

    上一篇见:

    在Pytorch中导入Cifar-10 数据集

    相关文章

      网友评论

          本文标题:2019-04-30 手把手教你用pytorch实现迁移学习(第

          本文链接:https://www.haomeiwen.com/subject/badvnqtx.html