MNIST数据集

本文详细介绍了MNIST数据集的组成和下载方式,并使用PyTorch加载与处理MNIST数据集的步骤,包括数据预处理、数据加载器的使用,以及如何自定义Dataset类读取数据。同时,展示了如何通过 torchvision 库进行数据增强和展示,为深度学习模型训练做好准备。
摘要由CSDN通过智能技术生成

一、MNIST数据集介绍

MNIST数据集是NIST(National Institute of Standards and Technology,美国国家标准与技术研究所)数据集的一个子集,MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取,主要包括四个文件:
在这里插入图片描述
在上述文件中,训练集train一共包含了 60000 张图像和标签,而测试集一共包含了 10000 张图像和标签。

idx3表示3维,ubyte表示是以字节的形式进行存储的,t10k表示10000张测试图片(test10000)。

每张图片是一个28*28像素点的0 ~ 9的灰质手写数字图片,黑底白字,图像像素值为0 ~ 255,越大该点越白。

二、数据下载和读取

导入PyTorch的两个核心库torch和torchvision,这两个库基本包含了PyTorch会用到的许多方法和函数,其他库为下面所需要的一些辅助库。

import gzip
import os

import torch
import torchvision
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, Dataset

注:

  • import datasets是为了方便自动下载数据集,可以下载多种数据集,如MNIST、ImageNet、CIFAR10等。
  • import transforms是pytorch中的图像预处理库,一般用Compose把多个步骤整合到一起。 相关详情见:transforms.Compose()函数

1、使用Pytorch自带的库函数

导入MNIST数据集代码:

train_data = datasets.MNIST(
            root="./data/",
            train=True,
            transform=transforms.ToTensor(),
            download=True)

test_data = datasets.MNIST(
            root="./data/",
            train=False,
            transform=transforms.ToTensor(),
            download=True)

其中:

  1. root 指定MNIST数据集存放的路径

  2. train 设置为True表示导入的是训练集合,否则为测试集合

  3. transform 指定导入数据集时需要进行何种变换操作

    此处ToTensor()shape(H, W, C)nump.ndarrayimg转为shape(C, H, W)tensor,其将每一个数值归一化到[0,1],其归一化方法比较简单,直接除以255即可

  4. download 设置为True表示当root参数指定的数据集存放的路径下没有数据时,则自动从网络上下载MNIST数据集,否则就不自动下载

注意: 返回值为一个二元组(data,target),一般是与torch.utils.data.DataLoader配合使用,也可自己对数据进行处理,见二、2

加载MNIST数据集代码:

train_data_loader = torch.utils.data.DataLoader(
        dataset=train_data,
        batch_size=64,
        shuffle=True,
        drop_last=True)

test_data_loader = torch.utils.data.DataLoader(
        dataset=test_data,
        batch_size=64,
        shuffle=False,
        drop_last=False)

其中:

  1. dataset 指定欲装载的MNIST数据集
  2. batch_size 设置了每批次装载的数据图片为64个(自行设置)
  3. shuffle 设置为True表示在装载数据时随机乱序,常用于进行多批次的模型训练
  4. drop_last 设置为True表示当数据集size不能整除batch_size时,则删除最后一个batch_size,否则就不删除

在加载完成后,可以选取其中一个批次的数据进行预览:

********************
images, labels = next(iter(train_data_loader))	# images:Tensor(64,1,28,28)、labels:Tensor(64,)
********************
img = torchvision.utils.make_grid(images)	# 把64张图片拼接为1张图片

# pytorch网络输入图像的格式为(C, H, W),而numpy中的图像的shape为(H,W,C)。故需要变换通道才能有效输出
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()

下图展示的是一个batch数据集(64张图片)的显示:
在这里插入图片描述
对其中某一个图片进行像素化展示:

# images:Tensor(64,1,28,28)、labels:Tensor(64,)	
images, labels = next(iter(train_data_loader))  #(1,28,28)表示该图像的 height、width、color(颜色通道,即单通道)
images = images.reshape(64, 28, 28) 
img = images[0, :, :]	# 取batch_size中的第一张图像
np.savetxt('img.txt', img.cpu().numpy(), fmt="%f", encoding='UTF-8')	# 将像素值写入txt文件,以便查看
img = img.cpu().numpy()	#转为numpy类型,方便有效输出

fig = plt.figure(figsize=(12, 12))
ax = fig.add_subplot(111)
ax.imshow(img, cmap='gray')
width, height = img.shape
thresh = img.max()/2.5

for x in range(width):
    for y in range(height):
        val = round(img[x][y], 2) if img[x][y] !=0 else 0
        ax.annotate(str(val), xy=(y, x),
                    horizontalalignment='center',
                    verticalalignment='center',
                    color='white' if img[x][y] < thresh else 'black')
plt.show()

在这里插入图片描述

2、通过重构Dataset类读取特定的MNIST数据或者制作自己的MNIST数据集

定义一个子类,继承Dataset类, 重写 len()getitem() 方法。
getitem 是获取样本对,模型直接通过这一函数获得一对样本对{ x:y }
len 是指数据集长度

① 读取MNIST文件夹下processed文件中的training.pt、test.pt数据集

class Data_Loader(Dataset):
    def __init__(self, root, transform=None):
        self.data, self.targets = torch.load(root)	#采用torch.load进行读取,读取之后的结果为torch.Tensor形式
		self.transform = transform
		
    def __getitem__(self, index):
        img, target = self.data[index], int(self.targets[index])
        img = Image.fromarray(img.numpy(), mode='L')

        if self.transform is not None:
            img = self.transform(img)
        img = transforms.ToTensor()(img)
        
        return img, target

    def __len__(self):
        return len(self.data)

接下来,调用我们自定义的Data_Loader类来读取数据集:

# root 为training.pt、test.pt文件所在的绝对路径
train_data = Data_Loader(root='./mnist/MNIST/processed/training.pt', transform= None)
test_data = Data_Loader(root='./mnist/MNIST/processed/test.pt', transform= None)

再使用torch.utils.data.DataLoadertrain_datatest_data进行加载,展示。

② 读取MNIST文件夹下raw文件中的数据集

class Data_Loader(Dataset):
    def __init__(self, folder, data_name, label_name, transform=None):
        (train_set, train_labels) = load_data(folder, data_name, label_name)
        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

接下来,调用我们自定义的Data_Loader类来读取数据集:

#	folder:MNIST数据集中raw文件的绝对路径

# 读取MNIST数据集中的训练集
train_data = Data_Loader('./MNIST/MNIST/raw', "train-images-idx3-ubyte.gz",
                           "train-labels-idx1-ubyte.gz", transform=transforms.ToTensor())

# 读取MNIST数据集中的测试集
test_data = Data_Loader('./MNIST/MNIST/raw', "t10k-images-idx3-ubyte.gz",
                           "t10k-labels-idx1-ubyte.gz", transform=transforms.ToTensor())

再使用torch.utils.data.DataLoadertrain_datatest_data进行加载,展示。

③ 直接读取MNIST数据集

def data_loader(path):
    # Train Data
    mnist_train = torchvision.datasets.MNIST(root=path, train=True, download=False)
    train_data = mnist_train.data.view([-1, 784]).float()/255.	# mnist_train.data 获取数字
    train_labels = mnist_train.targets	# mnist_train.targets 获取标签

    # Test Data
    mnist_test = torchvision.datasets.MNIST(root=path, train=False, download=False)
    test_data = mnist_test.data.view([-1, 784]).float()/255.
    test_labels = mnist_test.targets
	
	# translate the numeric label [0-9] into a vector label[0, ..., 1, ..0, 0]
	train_labelvec = torch.zeros([10, 60000]).int()
    train_labelvec[train_labels.cpu().numpy(), np.arange(60000)] = 1

    test_labelvec = torch.zeros([10, 10000]).int()
    test_labelvec[test_labels.cpu().numpy(), np.arange(10000)] = 1
    
	return train_data, train_labelvec, test_data, test_labelvec

通过调用该函数可以获取数据:

"""
    Load data and preprocess
    DataTrain:Tensor(60000,784) LabelsTrain:Tensor(10,60000)
    DataTest:Tensor(10000,784)  LabelsTest:Tensor(10,10000)
    """
    DataTrain, LabelsTrain, DataTest, LabelsTest = data_loader(args.datapath)
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值