FashionMNIST 是一个替代 MNIST 手写数字集 的图像数据集。 它是由 Zalando(一家德国的时尚科技公司)旗下的研究部门提供。其涵盖了来自 10 种类别的共 7 万个不同商品的正面图片。FashionMNIST 的大小、格式和训练集/测试集划分与原始的 MNIST 完全一致。60000/10000 的训练测试数据划分,28x28 的灰度图片(翻译自Github介绍)。Fashion-MNIST数据集GitHub链接, MNIST数据集链接。
数据集也比较小,只有几十M,一些更加详细的介绍参考:MNIST及FASHION MNIST 数据读取
torchvision包:服务于PyTorch框架,主要包括四个大类:
(1).torchvision.datasets
: 一些加载数据的函数及常用的数据集接口;
(2).torchvision.models
: 包含常用的模型结构(含预训练模型),如AlexNet、VGG、ResNet等;
(3).torchvision.transforms
: 常用的图片变换,例如裁剪、旋转等;
(4).torchvision.utils
: 其他的一些有用的方法。
1. 导入所需要的基本库
import torch
import torchvision
import torchvision.transforms as transformers
import sys
import matplotlib.pyplot as plt
import time
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
2. 获取数据并进行示例可视化
使用torchvision.datasets进行数据下载,参数train指定获取的数据为训练集或者测试集,参数transform=transforms.ToTensor()用于将数据转化为Tensor,不转换不会立马报错,但返回的PIL图像涉及到.view等操作会出现问题,transforms.ToTensor()
将尺寸为 (H x W x C) 且数据位于[0, 255]的PIL图片或者数据类型为np.uint8
的NumPy数组转换为尺寸为(C x H x W)且数据类型为torch.float32
且位于[0.0, 1.0]的Tensor
。由于像素值为0到255的整数,所以刚好是uint8所能表示的范围,包括transforms.ToTensor()
在内的一些关于图片的函数就默认输入的是uint8型,若不是,可能不会报错但可能得不到想要的结果。所以,如果用像素值(0-255整数)表示图片数据,那么一律将其类型设置成uint8,避免不必要的bug。
ps:uint8是8位的,表示十进制数0-255,如果大于255则进一位,例如256显示就变成0。
#读取图像
mnist_train = torchvision.datasets.FashionMNIST(root=r'F:\afile\wbwh_d2L_torch\datasets', train=True, download=True, transform=transformers.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root=r'F:\afile\wbwh_d2L_torch\datasets', train=False, download=True, transform=transformers.ToTensor())
print(type(mnist_train))
print(len(mnist_train), len(mnist_test))
#打印其中一张查看
feature, label = mnist_test[0]
print(feature.shape, label) #torch.Size([1, 28, 28]) tensor(9)
变量feature
对应高和宽均为28像素的图像。由于使用了transforms.ToTensor()
,所以每个像素的数值为[0.0, 1.0]的32位浮点数。需要注意的是,feature
的尺寸是 (C x H x W) 的,而不是 (H x W x C)。Fashion-MNIST中一共包括了10个类别,分别为t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。以下函数可以将数值标签转成相应的文本标签。定义函数show_fashion_mnist可视化:
def get_fashion_mnist_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[i] for i in labels]
def show_fashion_mnist(images, labels):
_, figs = plt.subplots(1, len(images), figsize=(12, 12))
for f, img, lbl in zip(figs, images, labels):
f.imshow(img.view((28, 28)).numpy())
f.set_title(lbl)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.show()
X, y = [], []
for i in range(10):
X.append(mnist_train[i][0])
y.append(mnist_train[i][1])
show_fashion_mnist(X, get_fashion_mnist_labels(y))
# show_fashion_mnist(X, y)
使用Pycharm时注意加:
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
画成两排:
def show_fashion_mnist(images, labels):
# _, figs = plt.subplots(1, len(images), figsize=(12, 12))
_, figs = plt.subplots(2, 5, figsize=(6, 6))
list_f = []
for i in figs:
for j in i:
list_f.append(j)
for f, img, lbl in zip(list_f, images, labels):
f.imshow(img.view((28, 28)).numpy())
f.set_title(lbl)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.show()
3. 读取小批量数据
mnist_train
是torch.utils.data.Dataset
的子类,所以可以将其传入torch.utils.data.DataLoader
来创建一个读取小批量数据样本的DataLoader实例。实践中,数据读取经常是训练的性能瓶颈,特别当模型较简单或者计算硬件性能较高时。PyTorch的DataLoader
中一个很方便的功能是允许使用多进程来加速数据读取。这里我们通过参数num_workers
来设置4个进程读取数据。
batch_size=256
if sys.platform.startswith('win'):
num_workers=0
else:
num_workers=4
train_iter=torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, num_workers=num_workers, shuffle=True)
test_iter=torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, num_workers=num_workers, shuffle=True)
start = time.time()
for X,y in train_iter:
continue
print('%.2f seconds' % (time.time()- start))
看起来并不难,可视化也很容易,如果要是读入自己的数据呢?值得思考,并且很有趣。想到最近在复现TransUNet,数据接口改为2Dnarray,并且准确读入标签,以及可以推理检测,费了很大功夫。