pytorch加载的cifar10数据集过程详解

 更新时间:2023年11月08日 10:01:01   作者:PleaseBrave  
这篇文章主要介绍了pytorch加载的cifar10数据集,到底有没有经过归一化,本文对这一问题给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

pytorch怎么加载cifar10数据集

torchvision.datasets.CIFAR10

pytorch里面的torchvision.datasets中提供了大多数计算机视觉领域相关任务的数据集,可以根据实际需要加载相关数据集——需要cifar10就用torchvision.datasets.CIFAR10(),需要SVHN就调用torchvision.datasets.SVHN()。

针对cifar10数据集而言,调用torchvision.datasets.CIFAR10(),其中root是下载数据集后保存的位置;train是一个bool变量,为true就是训练数据集,false就是测试数据集;download也是一个bool变量,表示是否下载;transform是对数据集中的"image"进行一些操作,比如归一化、随机裁剪、各种数据增强操作等;target_transform是针对数据集中的"label"进行一些操作。

示例代码如下:

# 加载训练数据集
train_data = datasets.CIFAR10(root='../_datasets', train=True, download=True,
                                  transform= transforms.Compose([  
                                                 transforms.ToTensor(),  
                                                 transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])  # 归一化  
                                                 ])  )
# 加载测试数据集
test_data = datasets.CIFAR10(root='../_datasets', train=False,download=True, 
                             transform= transforms.Compose([  
                                               transforms.ToTensor(),  
                                               transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])  # 归一化  
                                               ])  )

transforms.Normalize()进行归一化到底在哪里起作用?【CIFAR10源码分析】

上面的代码中,我们用transforms.Compose([……])组合了一系列的对image的操作,其中trandforms.ToTensor()transforms.Normalize()都涉及到归一化操作:

  • 原始的cifar10数据集是numpy array的形式,其中数据范围是[0,255],pytorch加载时,并没有改变数据范围,依旧是[0,255],加载后的数据维度是(H, W, C),源码部分:

  • __getitem__()函数中进行transforms操作,进行了归一化:实际上传入的transform在__getitem__()函数中被调用,其中transforms.Totensor()会将data(也就是image)的维度变成(C,H, W)的形式,并且归一化到[0.0,1.0];

  • transforms.Normalize()会根据z = (x-mean) / std 对数据进行归一化,上述代码中mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]是可以将3个通道单独进行归一化,3个通道可以设置不同的mean和std,最终数据范围变成[-0.5,+0.5] 。

所以如果通过pytorch的cifar10加载数据集后,针对traindataset.data,依旧是没有进行归一化的;但是比如traindataset[index].data,其中[index]这样的按下标取元素的操作会直接调用的__getitem__()函数,此时的data就是经过了归一化的。
除traindataset[index]会隐式自动调用__getitem__()函数外,还有什么时候会调用这个函数呢?毕竟……只有调用了这个函数才会调用transforms中的归一化处理。——答案是与dataloader搭配使用!

torchvision.datasets加载的数据集搭配Dataloader使用

torchvision.datasets实际上是torch.utils.data.Dataset的子类,那么就能传入Dataloader中,迭代的按batch-size获取批量数据,用于训练或者测试。其中dataloader加载dataset中的数据时,就是用到了其__getitem__()函数,所以用dataloader加载数据集,得到的是经过归一化后的数据。

在这里插入图片描述

model.train()和model.eval()

我发现上面的问题,是我用dataloader加载了训练数据集用于训练resnet18模型,训练过程中,我训练好并保存后,顺便测试了一下在测试数据集上的准确度。但是在测试的过程中,我没有用dataloader加载测试数据集,而是直接用的dataset.data来进行的测试。并且!由于是并没有将model设置成model.eval()【其实我设置了,但是我对自己很无语,我写的model.eval,忘记加括号了,无语呜呜】……也就是即便我的测试数据集没有经过归一化,由于模型还是在model.train()模式下,因此模型的BN层会自己调整,使得模型性能不受影响,因此在测试数据集上的accuracy达到了0.86,我就没有多想。
后来我用模型的时候,设置了model.eval()后,依旧是直接用的dataset.data(也就是没有归一化),不管是在测试数据集上还是在训练数据集上,accuracy都只有0.10+,我表示非常的迷茫疑惑啊!然后才发现是归一化的问题。

  • model.train()模式下进行预测时,PyTorch会默认启用一些训练相关的操作,例如Batch Normalization和Dropout,并且模型的参数是可变的,能够根据输入进行调整。这些操作在训练模式下可以帮助模型更好地适应训练数据,并产生较高的准确度。
  • model.eval()模式下进行预测时,PyTorch会将模型切换到评估模式,这会导致一些训练相关的操作行为发生变化。具体而言,Batch Normalization层会使用训练集上的统计信息进行归一化,而不是使用当前批次的统计信息。因此,如果输入数据没有进行归一化,模型在评估模式下的准确度可能会显著下降。

以下是我没有用dataloader加载数据集,进行预测的代码:

def correctness(model,data,target, device):
    batchsize = 1000
    batch_num = int(len(data) / batchsize)   
    # 对原始的数据进行操作 从H.W.C变成C.H.W 
    data = torch.tensor(data).permute(0,3,1,2).type(torch.FloatTensor).to(device)
    # 手动归一化
    data = data/255
    data = (data - 0.5) / 0.5 
    # 求一个batch的correctness
    def _batch_correctness(i):
        images, labels = data[i*batchsize : (i+1)*batchsize], target[i*batchsize : (i+1)*batchsize]
        predict = model(images).detach().cpu()    
        correctness = np.array(torch.argmax(predict, dim = 1).numpy() == np.array(labels) , dtype= np.float32)
        return correctness
    result = np.array([_batch_correctness(i) for i in range(batch_num)])
    return result.flatten().sum()/data.shape[0]

我后面用上面的代码测试了四种情况:

  • model.eval() + 没有归一化:train_accuracy = 0.10,test_accuracy = 0.10;
  • model.eval() + 手动归一化:train_accuracy = 0.95,test_accuracy = 0.84;
  • model.train() + 没有归一化:train_accuracy = 0.95,test_accuracy = 0.83;
  • model.train() + 手动归一化:train_accuracy = 0.94,test_accuracy = 0.84;

由此可见,在model.eval()模式下,数据归一化对最终的测试结果有很大影响。

到此这篇关于pytorch加载的cifar10数据集,到底有没有经过归一化的文章就介绍到这了,更多相关pytorch加载cifar10数据集内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python获取时间的操作示例详解

    Python获取时间的操作示例详解

    这篇文章主要为大家详细介绍了一些Python中获取时间的操作,例如:获取时间戳、获取当前时间、获取昨天日期等,感兴趣的可以参考一下
    2022-07-07
  • Python常用爬虫代码总结方便查询

    Python常用爬虫代码总结方便查询

    今天小编就为大家分享一篇关于Python常用爬虫代码总结方便查询,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • python+pyqt5实现KFC点餐收银系统

    python+pyqt5实现KFC点餐收银系统

    这篇文章主要为大家详细介绍了python+pyqt5实现KFC点餐收银系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 浅谈matplotlib默认字体设置探索

    浅谈matplotlib默认字体设置探索

    这篇文章主要介绍了matplotlib默认字体设置探索,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 解决Keras中CNN输入维度报错问题

    解决Keras中CNN输入维度报错问题

    这篇文章主要介绍了解决Keras中CNN输入维度报错问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06
  • Python cv2 图像自适应灰度直方图均衡化处理方法

    Python cv2 图像自适应灰度直方图均衡化处理方法

    今天小编就为大家分享一篇Python cv2 图像自适应灰度直方图均衡化处理方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • python tkinter控件布局项目实例

    python tkinter控件布局项目实例

    这篇文章主要介绍了python tkinter控件布局项目实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Python字符串通过''+''和join函数拼接新字符串的性能测试比较

    Python字符串通过''+''和join函数拼接新字符串的性能测试比较

    今天小编就为大家分享一篇关于Python字符串通过'+'和join函数拼接新字符串的性能测试比较,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Python 3中的yield from语法详解

    Python 3中的yield from语法详解

    在python 3.3里,generator新增了一个语法 yield from,这个yield from的作用是什么?语法是什么呢?下面通过这篇文章主要给大家详细介绍了Python 3中yield from语法的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • django xadmin中form_layout添加字段显示方式

    django xadmin中form_layout添加字段显示方式

    这篇文章主要介绍了django xadmin中form_layout添加字段显示方式,具有很好的 参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03

最新评论