十分钟搞懂Pytorch如何读取MNIST数据集

前言本文用于记录使用pytorch读取minist数据集的过程,以及一些思考和疑惑吧…正文在阅读教程书籍《深度学习入门之Pytorch》时,文中是如此加载MNIST手写数字训练集的:train_dataset=datasets.MNIST(root=’./MNIST’,train=True,transform=data_tf,download=True)解释一下参数datasets.MNIST是Pytorch的内置函数torchvision.datasets.MNIST,通过这个可以导入数

大家好,又见面了,我是你们的朋友全栈君。

前言

本文用于记录使用pytorch读取minist数据集的过程,以及一些思考和疑惑吧…

正文

在阅读教程书籍《深度学习入门之Pytorch》时,文中是如此加载MNIST手写数字训练集的:

train_dataset = datasets.MNIST(root='./MNIST',train=True,transform=data_tf,download=True)

解释一下参数

datasets.MNIST是Pytorch的内置函数torchvision.datasets.MNIST,通过这个可以导入数据集。

train=True 代表我们读入的数据作为训练集(如果为true则从training.pt创建数据集,否则从test.pt创建数据集)

transform则是读入我们自己定义的数据预处理操作

download=True则是当我们的根目录(root)下没有数据集时,便自动下载。

如果这时候我们通过联网自动下载方式download我们的数据后,它的文件路径是以下形式:

在这里插入图片描述

其中我们所需要的文件主要在raw文件夹下

train-images-idx3-ubyte.gz: training set images (9912422 bytes) 
train-labels-idx1-ubyte.gz: training set labels (28881 bytes) 

t10k-images-idx3-ubyte.gz: test set images (1648877 bytes) 
t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes) 

接下来,书中是如此加载数据集的

train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=5,
                                           shuffle=True)

由于DataLoader为Pytorch内部封装好的函数,所以对于它的调用方法需要自行去查阅。

我在最开始疑惑的点:传入的根目录在下载好数据集后,为MNIST下两个文件夹,而processed和raw文件夹下还有诸多文件,所以到底是如何读入数据的呢?所以我决定将数据集下载后,通过读取本地的MINIST数据集并进行装载。

首先,自定义数据类来继承和重写Dataset抽象类

class DealDataset(Dataset):
    """ 读取数据、初始化数据 """
    def __init__(self, folder, data_name, label_name,transform=None):
        (train_set, train_labels) = self.load_data(folder, data_name, label_name) # 其实也可以直接使用torch.load(),读取之后的结果为torch.Tensor形式
        self.train_set = train_set
        self.train_labels = train_labels
        self.transform = transform

    def __getitem__(self, index):

        img, target = self.train_set[index], int(self.train_labels[index])
        if self.transform is not None:
            img = self.transform(img)
        return img, target

    def __len__(self):
        return len(self.train_set)
    ''' load_data也是我们自定义的函数,用途:读取数据集中的数据 ( 图片数据+标签label '''
    def load_data(self,data_folder, data_name, label_name):
    with gzip.open(os.path.join(data_folder,label_name), 'rb') as lbpath: # rb表示的是读取二进制数据
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(os.path.join(data_folder,data_name), 'rb') as imgpath:
        x_train = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)
    return (x_train, y_train)

接下来,调用我们自定义的数据类来加载数据集

trainDataset = DealDataset('./MNIST/MNIST/raw', "train-images-idx3-ubyte.gz","train-labels-idx1-ubyte.gz",transform=transforms.ToTensor())

# 训练数据和测试数据的装载
train_loader = torch.utils.data.DataLoader(
    dataset=trainDataset,
    batch_size=10, # 一个批次可以认为是一个包,每个包中含有10张图片
    shuffle=False,
)

通过这种方式便可以大概了解了读取数据集的过程。

接下来,我们来验证以下我们数据是否正确加载

# 实现单张图片可视化
images, labels = next(iter(train_loader))
img = torchvision.utils.make_grid(images)

img = img.numpy().transpose(1, 2, 0)
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
img = img * std + mean
print(labels)
plt.imshow(img)
plt.show()

p.s.:其实这里是用cv2.imshow来展示图片,但是我的代码是在jupyter notebook上写的,所以只能通过plt来代替加载。
在这里插入图片描述

数据加载成功~

深入探索

可以看到,在load_data函数中

y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

这个offset=8又是为啥呢?
我们进入MNIST数据集的官方页面进行查看
在这里插入图片描述

通过文档介绍,可以看到
offset的0000-0003是 magic number,所以跳过不读,
offset的0004-0007是items数目
接下来这些代表的就是标签

同理对于

x_train = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_train)

在这里插入图片描述

根据刚才的分析方法,也可以明白为什么offset=16了

完整代码

1.直接使用pytorch自带的mnist数据集加载

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
import torchvision
from torch.autograd import Variable
from torch.utils.data import DataLoader
import cv2
import matplotlib.pyplot as plt

data_tf = transforms.Compose(
    [transforms.ToTensor(),
    transforms.Normalize([0.5],[0.5])]
)

train_dataset = datasets.MNIST(root='./coding/learning/lrdata/MNIST',train=True,transform=data_tf,download=True)

train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=5,
                                           shuffle=True)
# 实现单张图片可视化
images, labels = next(iter(train_loader))
img = torchvision.utils.make_grid(images)

img = img.numpy().transpose(1, 2, 0)
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
img = img * std + mean
print(labels)
plt.imshow(img)
plt.show()

p.s.:记得自己修改root根目录。

2.使用自定义的数据类加载本地MNIST数据集

import numpy as np
import torch
from torch.utils.data import DataLoader,Dataset
from torchvision import transforms
import gzip
import os
import torchvision
import cv2
import matplotlib.pyplot as plt

class DealDataset(Dataset):
    """ 读取数据、初始化数据 """
    def __init__(self, folder, data_name, label_name,transform=None):
        (train_set, train_labels) = load_data(folder, data_name, label_name) # 其实也可以直接使用torch.load(),读取之后的结果为torch.Tensor形式
        self.train_set = train_set
        self.train_labels = train_labels
        self.transform = transform

    def __getitem__(self, index):

        img, target = self.train_set[index], int(self.train_labels[index])
        if self.transform is not None:
            img = self.transform(img)
        return img, target

    def __len__(self):
        return len(self.train_set)
  
 def load_data(data_folder, data_name, label_name):
    with gzip.open(os.path.join(data_folder,label_name), 'rb') as lbpath: # rb表示的是读取二进制数据
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(os.path.join(data_folder,data_name), 'rb') as imgpath:
        x_train = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)
    return (x_train, y_train)

trainDataset = DealDataset('./coding/learning/lrdata/MNIST/MNIST/raw', "train-images-idx3-ubyte.gz","train-labels-idx1-ubyte.gz",transform=transforms.ToTensor())

# 训练数据和测试数据的装载
train_loader = torch.utils.data.DataLoader(
    dataset=trainDataset,
    batch_size=10, # 一个批次可以认为是一个包,每个包中含有10张图片
    shuffle=False,
)

# 实现单张图片可视化
images, labels = next(iter(train_loader))
img = torchvision.utils.make_grid(images)

img = img.numpy().transpose(1, 2, 0)
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
img = img * std + mean
print(labels)
plt.imshow(img)
plt.show()

参考

1.《深度学习入门之Pytorch》- 廖星宇
2.使用Pytorch进行读取本地的MINIST数据集并进行装载
3.顺藤摸瓜-mnist数据集的补充

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126858.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • protostuff基本使用[通俗易懂]

    protostuff基本使用[通俗易懂][toc]protostuff基本使用protostuff基于GoogleProtobuf,好处就是不用自己写.proto文件即可实现对象的序列化与反序列化,下面给出示例代码。程序代码User.javapackagecn.xpleaf.pojo;publicclassUser{privateStringname;privateintage;…

    2022年5月20日
    68
  • OpenNebula 4.0 Beta 新特性介绍

    OpenNebula 4.0 Beta 新特性介绍

    2021年8月31日
    59
  • Idea激活码最新教程2023.3.7版本,永久有效激活码,亲测可用,记得收藏

    Idea激活码最新教程2023.3.7版本,永久有效激活码,亲测可用,记得收藏Idea 激活码教程永久有效 2023 3 7 激活码教程 Windows 版永久激活 持续更新 Idea 激活码 2023 3 7 成功激活

    2025年5月28日
    3
  • ray tracing in one weekend_rocket用法

    ray tracing in one weekend_rocket用法RayTracing文章目录RayTracing光线追踪Whitted-StyleRayTracing求交点加速求交点BoundingVolumes包围盒BVHBasicradiometry(辐射度量学)RadiantfluxintensityIrradianceRadianceBRDF双向反射分布函数概率论回顾蒙特卡洛路径追踪蒙特卡洛积分路径追踪光线追踪1.光沿直线传播2.光线不会发生碰撞3.光路可逆性Whitted-StyleRayTracing递归算法,包括了光

    2025年7月16日
    4
  • Python格式化字符串f-string概览

    Python格式化字符串f-string概览简介f-string,亦称为格式化字符串常量(formattedstringliterals),是Python3.6新引入的一种字符串格式化方法,该方法源于PEP498–LiteralStringInterpolation,主要目的是使格式化字符串的操作更加简便。f-string在形式上是以f或F修饰符引领的字符串(f’xxx’或F’xxx’),以大括号对{}标明…

    2022年6月10日
    67
  • 树莓派小车C语言循迹,自动循迹小车_单片机/STM32/树莓派/Arduino/开发板创意项目-聚丰项目-电子发烧友网…[通俗易懂]

    树莓派小车C语言循迹,自动循迹小车_单片机/STM32/树莓派/Arduino/开发板创意项目-聚丰项目-电子发烧友网…[通俗易懂]1金属探测模块采集与计算金属探测LDC1314是根据电磁感应原理制成的,将一金属置于变化的磁场当中时,根据电磁感应原理就会在金属内部产生涡流,涡流产生的磁场反过来又影响原磁场,这种变化可以转换为电压幅值的变化,供相关电路进行检测。通过改变金属和线圈之间的距离得到不同的值,对前端探测到的数据进行再处理和分析,当其中一个线圈探测到铁丝则让小车向相反方向前进,若发现附近有硬币存在该探测器发出声音警报。L…

    2022年5月6日
    64

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号