第1关:MNIST 数据集下载与预处理
代码文件
import torch
import torchvision
import torchvision.transforms as transforms
######## Begin ########
# 定义预处理操作集合transform
# 1.转换成Tensor
# 2.数据归一化
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))]
)
######## End ########
######## Begin ########
# 创建训练数据集trainset与测试数据集testset
# 数据集本地已经下载好,数据集根目录:'/data/workspace/myshixun/data'
# 下载download选项请设置为False
trainset = torchvision.datasets.MNIST(root='/data/workspace/myshixun/data', train=True,
download=False, transform=transform)
testset = torchvision.datasets.MNIST(root='/data/workspace/myshixun/data', train=False,
download=False, transform=transform)
######## End ########
if __name__ == "__main__":
print(trainset)
print(testset)
题目描述
任务描述
本关任务:编写一个能实现 MNIST
数据集预处理的小程序。
相关知识
为了完成本关任务,你需要掌握:1.MNIST
数据集介绍,2.MNIST
数据集下载与预处理。
MNIST
数据集介绍
MNIST
是一个手写体数字的图片数据集,该数据集来由美国国家标准与技术研究所 (National Institute of Standards and Technology (NIST))
发起整理,一共统计了来自 250
个不同的人手写数字图片,其中 50
是高中生,50
来自人口普查局的工作人员。该数据集的收集目的是希望通过算法,实现对手写数字的识别。
数据集主要包括四个文件:
文件名 | 文件用途 |
---|---|
train-images-idx3-ubyte.gz |
训练集图像 |
train-labels-idx1-ubyte.gz |
训练集标签 |
t10k-images-idx3-ubyte.gz |
测试集图像 |
t10k-labels-idx1-ubyte.gz |
测试集标签 |
在上述文件中,训练集一共包含了 60000
张图像和标签,而测试集一共包含了 10000
张图像和标签。测试集中前 5000
个来自最初 NIST
项目的训练集,后 5000
个来自最初 NIST
项目的测试集。前 5000
个比后 5000
个要规整,这是因为前 5000
个数据来自于美国人口普查局的员工,而后 5000
个来自于大学生。
数据集可视化效果如下:
图 1 MNIST 数据集示例图
MNIST
数据集下载与预处理
数据集下载
下载方式一是从官网直接下载:
MNIST
数据集官网:http://yann.lecun.com/exdb/mnist/
在数据集官网给出了 MNIST
数据集的下载链接,我们可以通过点击链接进行下载,如下图所示:
图 2 数据集官网下载示例图(图片来自网络)
下载方式二是利用深度学习框架 Pytorch
中的 torchvision
库实现数据集的下载,这种下载方式有一个好处是torchvision
库内置了 MNIST
数据集专门的处理类,可以在下载好的同时加载好数据。
下载所要用的是 torchvision.datasets.MNIST
类,它的初始化有以下几个参数:
root
:数据集保存根目录;train
:是否是训练集;download
:是否使用在线下载;transform
:数据集预处理函数。
具体使用如下:
trainset = torchvision.datasets.MNIST(root='./data', train=True,
download=True, transform=transform)
testset = torchvision.datasets.MNIST(root='./data', train=False,
download=True, transform=transform)
其中分别返回训练集 trainset
与测试集 testset
。
数据集预处理
上述 torchvision.datasets.MNIST
类的初始化中,我们使用了 transform
预处理,现在我们来学习 transform
的具体定义。
在 Pytorch
深度学习框架中,基本数据结构是张量 Tensor
:
-
Tensor
在Pytorch
深度学习框架中负责存储基本数据,Pytorch
针对Tensor
也提供了丰富的函数和方法,Pytorch
的Tensor
与Numpy
的数组具有极高的相似性; -
Pytorch
中定义的Tensor
数据变量可以在GPU
上进行运算,而且只需对变量做一些简单的类型转换就能够实现; -
Tensor
与Numpy
数组的最大区别在于,Tensor
可以进行自动求导,这使得深度学习反向传播算法实现起来变得很方便。
图 3 Tensor 示意图
因此我们首先需要做的预处理是将图像数据转换成 Tensor
, torchvision.transforms
类中定义了 Tensor
转换预处理操作:
transforms.ToTensor()
接着由于图像数据表示的是单通道灰度值 (0−255)
,其分布数值较大不利于网络训练,因此我们还需要对转换成 Tensor
后的数据进行归一化操作:
transforms.Normalize((0.5,), (0.5,))
这里默认数据的均值与方差都是 0.5
。
最后用 transforms.Compose
将两种预处理操作组合起来构成 transform
:
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))]
)
编程要求
根据提示,在右侧编辑器补充 Begin-End
中代码,编写 MNIST
数据集预处理代码。
测试说明
平台会对你编写的代码进行测试:
测试1
测试输入:无 预期输出:训练集与测试集信息
Dataset MNIST
Number of datapoints: 60000
Root location: /data/workspace/myshixun/data
Split: Train
StandardTransform
Transform: Compose(
ToTensor()
Normalize(mean=(0.5,), std=(0.5,))
)
Dataset MNIST
Number of datapoints: 10000
Root location: /data/workspace/myshixun/data
Split: Test
StandardTransform
Transform: Compose(
ToTensor()
Normalize(mean=(0.5,), std=(0.5,))
)
开始你的任务吧,祝你成功!
第2关:MNIST 数据集打包
代码文件
import torch
import torchvision
import torchvision.transforms as transforms
# Transformations applied on each image
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
# Loading the MNIST dataset
trainset = torchvision.datasets.MNIST(root='/data/workspace/myshixun/data', train=True,
download=False, transform=transform)
testset = torchvision.datasets.MNIST(root='/data/workspace/myshixun/data', train=False,
download=False, transform=transform)
######## Begin ########
# Packing the MNIST dataset using torch.utils.data.DataLoader
# Packing the training data
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=0)
# Packing the test data
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=0)
######## End ########
# Getting some random test images
dataiter = iter(testloader)
images, labels = dataiter.next()
# Printing the required details
print(len(testloader))
print(images.shape)
print(labels)
题目描述
任务描述
本关任务:编写一个能实现对预处理后的 MNIST
数据集进行打包的小程序。
相关知识
为了完成本关任务,你需要掌握:1.torch.utils.data.DataLoader
类,2.MNIST
数据集打包。
torch.utils.data.DataLoader
类
Pytorch
深度学习框架采用 torch.utils.data.DataLoader
类将 Dataset
类加载的数据进行打包。
-
DataLoader
将Dataset
对象或自定义数据类的对象封装成一个迭代器; -
这个迭代器可以迭代输出
Dataset
的内容; -
同时可以实现多进程、打乱数据、不同采样策略,数据校对等等处理过程。
torch.utils.data.DataLoader
类的构造函数常用的参数有:
-
dataset
:这个就是pytorch
已有的数据读取接口(比如torchvision.datasets.ImageFolder
)或者自定义的数据接口的输出,该输出要么是torch.utils.data.Dataset
类的对象,要么是继承自torch.utils.data.Dataset
类的自定义类的对象。简单来说,就是上一关定义的torchvision.datasets.CIFAR10
类的数据集对象trainset
与testset
; -
batch_size
:每一批进入网络训练的数据数量; -
shuffle
:是否随机打乱顺序,一般在训练数据中会采用; -
num_workers
:0
表示数据导入在主进程中进行,大于0
的数表示通过多个进程来导入数据,可以加快数据导入速度; -
pin_memory
:加载数据时是否使用内存,默认设置为False
。
MNIST
数据集打包
在了解 torch.utils.data.DataLoader
类以后,我们接下来对上一关定义的 trainset
与 testset
数据集进行打包:
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
shuffle=True, num_workers=0)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=0)
其中打包的训练集 trainloader
每批数据含有 64
个样本,测试集 testloader
每批数据含有 4
个样本。
我们试着创建迭代器,取出第一批测试集数据:
dataiter = iter(testloader) # 创建迭代器
images, labels = dataiter.next() # 取第一批测试集数据
打印图片形状与标签:
print(images.shape)
print(labels)
输出结果:
torch.Size([4, 1, 28, 28])
tensor([7, 2, 1, 0])
可以看到图片的 tensor
形状为(4,1,28,28)
分别对应 batch
为 4
,通道数为 1
,每一张图片大小为 28×28
。
而每张图片标签的类别分别为 (7,2,1,0)
。
编程要求
根据提示,在右侧编辑器补充 Begin-End
中代码,编写 MNIST
数据集打包代码。
测试说明
平台会对你编写的代码进行测试:
测试1
测试输入:无 预期输出:
打包后测试集批数:2500
第一批测试集图像维度:torch.Size([4, 1, 28, 28])
第一批测试集标签:tensor([7, 2, 1, 0])
开始你的任务吧,祝你成功!
第3关:MNIST 数据集可视化
代码文件
import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='/data/workspace/myshixun/data', train=True,
download=False, transform=transform)
testset = torchvision.datasets.MNIST(root='/data/workspace/myshixun/data', train=False,
download=False, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
shuffle=True, num_workers=0)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=0)
classes = ('zero', 'one', 'two', 'three',
'four', 'five', 'six', 'seven', 'eight', 'nine')
######## Begin ########
# 图片可视化函数imgshow定义
def imgshow(img):
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imsave("/data/workspace/myshixun/E3/student_show/test.png", np.transpose(npimg, (1, 2, 0)))
######## End ########
# get some random test images
dataiter = iter(testloader)
images, labels = dataiter.next()
print(images.shape)
images = torchvision.utils.make_grid(images) # 拼接图片
print(images.shape)
# Call imgshow function to visualize and save the image
imgshow(images)
# 输出类别
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
题目描述
任务描述
本关任务:编写一个能实现对打包后的 MNIST
数据集进行可视化的小程序。
相关知识
为了完成本关任务,你需要掌握:1.相关库函数,2.可视化函数 imshow
编写。
相关库函数
matplotlib.pyplot.imsave
库函数
在上一节的学习中,我们已经学会如何将数据集进行打包,并在最后创建迭代器读取了第一批测试集的 4
张图片以及它们的标签。这一节我们来学习如何可视化这四张图片。
首先介绍 matplotlib.pyplot.imsave
库函数,它被用来将处理后的 Numpy
图片数组保存成图片,其函数原型为:
matplotlib.pyplot.imsave(fname, arr)
其中 fname
为想要保存的图片文件名,例如 test.png
。arr
为处理好的图片数组。
torchvision.utils.make_grid
库函数
上一节提到,最后第一批测试集图片的维度是 (4,1,28,28)
分别对应 batch
为 4
,通道数为 1
,每一张图片大小为 28×28
。
现在我们利用 torchvision.utils.make_grid
库函数将四张图片拼接到一起:
# 接上一节代码
dataiter = iter(testloader)
images, labels = dataiter.next()
print(images.shape)
images = torchvision.utils.make_grid(images) # 拼接图片
print(images.shape)
输出结果:
torch.Size([4, 1, 28, 28])
torch.Size([3, 32, 122])
可以看到拼接以后,第一个维度 batch
不见了,取而代之的是图片的行列变成了 32×122
,其中 32
中不仅包含原来的 28
,还包含了 4
个像素位置的图片底宽,同时 122
也包含了 10
个像素的底宽。
通过 torchvision.utils.make_grid
库函数,四张图片被拼成了一下,接下来我们编写 imshow
可视化函数将拼接好的图片可视化展示出来。
可视化函数 imshow
编写
对于拼接后的图片,我们首先需要对其进行反归一化操作:
img = img / 2 + 0.5 # unnormalize
接着将图片转换成 Numpy
数组:
npimg = img.numpy()
最后调用 matplotlib.pyplot.imsave
库函数进行保存:
plt.imsave("test.png", np.transpose(npimg, (1, 2, 0)))
注意:保存之前需要将 Numpy
数组的第一个通道维度放到最后也就是 np.transpose(npimg, (1, 2, 0))
操作。
保存后的结果图片:
图 1 测试数据集可视化图
可以看到 28×28
分辨率的图像放大以后还是比较模糊。
编程要求
根据提示,在右侧编辑器补充 Begin-End
中代码,编写 MNIST
数据集可视化代码。
测试说明
平台会对你编写的代码进行测试:
测试1
测试输入:无 预期输出:
拼接前图片维度:torch.Size([4, 1, 28, 28])
拼接后图片维度:torch.Size([3, 32, 122])
图片类别名: seven two one zero
开始你的任务吧,祝你成功!
第4关:Transformer图像块编码
代码文件
import torch
import torch.nn as nn
import ml_collections
class Embeddings(nn.Module):
'''
对图像进行编码,把图片当做一个句子,把图片分割成块,每一块表示一个单词
'''
def __init__(self, config, img_size, in_channels=1):
super(Embeddings, self).__init__()
img_size = img_size # 28
patch_size = config.patches["size"] # 4
# 将图片分割成多少块(28/4)*(28/4)=49
n_patches = (img_size // patch_size) * (img_size // patch_size)
# 对图片进行卷积获取图片的块,并且将每一块映射成config.hidden_size维(16)
self.patch_embeddings = nn.Conv2d(in_channels=in_channels,
out_channels=config.hidden_size,
kernel_size=patch_size,
stride=patch_size)
# 设置可学习的位置编码信息,(1,49+1,16)
self.position_embeddings = nn.Parameter(torch.zeros