广西民族大学高级人工智能课程—头歌实践教学实践平台—Transformer自注意力网络

本系列教程详细介绍了如何使用Transformer模型处理MNIST数据集,包括数据预处理、打包、可视化、图像块编码、自注意力网络实现、全连接层、编码块、编码器、整体结构以及模型训练与测试。通过12个关卡逐步深入,涵盖数据下载、预处理、编码、注意力机制、模型训练和评估等关键步骤。
摘要由CSDN通过智能技术生成

第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


图 1 MNIST 数据集示例图

MNIST 数据集下载与预处理
数据集下载

下载方式一是从官网直接下载:

MNIST 数据集官网:http://yann.lecun.com/exdb/mnist/

在数据集官网给出了 MNIST 数据集的下载链接,我们可以通过点击链接进行下载,如下图所示:

图  2


图 2 数据集官网下载示例图(图片来自网络)

下载方式二是利用深度学习框架 Pytorch 中的 torchvision 库实现数据集的下载,这种下载方式有一个好处是torchvision 库内置了 MNIST 数据集专门的处理类,可以在下载好的同时加载好数据。

下载所要用的是 torchvision.datasets.MNIST 类,它的初始化有以下几个参数:

  • root:数据集保存根目录;
  • train:是否是训练集;
  • download:是否使用在线下载;
  • transform:数据集预处理函数。

具体使用如下:

 
  1. trainset = torchvision.datasets.MNIST(root='./data', train=True,
  2. download=True, transform=transform)
  3. testset = torchvision.datasets.MNIST(root='./data', train=False,
  4. download=True, transform=transform)

其中分别返回训练集 trainset 与测试集 testset

数据集预处理

上述 torchvision.datasets.MNIST 类的初始化中,我们使用了 transform 预处理,现在我们来学习 transform 的具体定义。

Pytorch 深度学习框架中,基本数据结构是张量 Tensor

  • TensorPytorch 深度学习框架中负责存储基本数据,Pytorch 针对 Tensor 也提供了丰富的函数和方法,PytorchTensorNumpy 的数组具有极高的相似性;

  • Pytorch 中定义的 Tensor 数据变量可以在 GPU 上进行运算,而且只需对变量做一些简单的类型转换就能够实现;

  • TensorNumpy 数组的最大区别在于,Tensor 可以进行自动求导,这使得深度学习反向传播算法实现起来变得很方便。

图  3


图 3 Tensor 示意图

因此我们首先需要做的预处理是将图像数据转换成 Tensor, torchvision.transforms 类中定义了 Tensor 转换预处理操作:

 
  1. transforms.ToTensor()

接着由于图像数据表示的是单通道灰度值 (0−255),其分布数值较大不利于网络训练,因此我们还需要对转换成 Tensor 后的数据进行归一化操作:

 
  1. transforms.Normalize((0.5,), (0.5,))

这里默认数据的均值与方差都是 0.5

最后用 transforms.Compose 将两种预处理操作组合起来构成 transform

 
  1. transform = transforms.Compose(
  2. [transforms.ToTensor(),
  3. transforms.Normalize((0.5,), (0.5,))]
  4. )

编程要求

根据提示,在右侧编辑器补充 Begin-End 中代码,编写 MNIST 数据集预处理代码。

测试说明

平台会对你编写的代码进行测试:

测试1

测试输入:无 预期输出:训练集与测试集信息

 
  1. Dataset MNIST
  2. Number of datapoints: 60000
  3. Root location: /data/workspace/myshixun/data
  4. Split: Train
  5. StandardTransform
  6. Transform: Compose(
  7. ToTensor()
  8. Normalize(mean=(0.5,), std=(0.5,))
  9. )
  10. Dataset MNIST
  11. Number of datapoints: 10000
  12. Root location: /data/workspace/myshixun/data
  13. Split: Test
  14. StandardTransform
  15. Transform: Compose(
  16. ToTensor()
  17. Normalize(mean=(0.5,), std=(0.5,))
  18. )

开始你的任务吧,祝你成功!

第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 类加载的数据进行打包。

  • DataLoaderDataset 对象或自定义数据类的对象封装成一个迭代器;

  • 这个迭代器可以迭代输出 Dataset 的内容;

  • 同时可以实现多进程、打乱数据、不同采样策略,数据校对等等处理过程。

torch.utils.data.DataLoader 类的构造函数常用的参数有:

  • dataset:这个就是 pytorch 已有的数据读取接口(比如 torchvision.datasets.ImageFolder )或者自定义的数据接口的输出,该输出要么是 torch.utils.data.Dataset 类的对象,要么是继承自 torch.utils.data.Dataset 类的自定义类的对象。简单来说,就是上一关定义的 torchvision.datasets.CIFAR10 类的数据集对象 trainsettestset

  • batch_size:每一批进入网络训练的数据数量;

  • shuffle:是否随机打乱顺序,一般在训练数据中会采用;

  • num_workers0 表示数据导入在主进程中进行,大于 0 的数表示通过多个进程来导入数据,可以加快数据导入速度;

  • pin_memory:加载数据时是否使用内存,默认设置为 False

MNIST 数据集打包

在了解 torch.utils.data.DataLoader 类以后,我们接下来对上一关定义的 trainsettestset 数据集进行打包:

 
  1. trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
  2. shuffle=True, num_workers=0)
  3. testloader = torch.utils.data.DataLoader(testset, batch_size=4,
  4. shuffle=False, num_workers=0)

其中打包的训练集 trainloader 每批数据含有 64 个样本,测试集 testloader 每批数据含有 4 个样本。

我们试着创建迭代器,取出第一批测试集数据:

 
  1. dataiter = iter(testloader) # 创建迭代器
  2. images, labels = dataiter.next() # 取第一批测试集数据

打印图片形状与标签:

 
  1. print(images.shape)
  2. print(labels)

输出结果:

 
  1. torch.Size([4, 1, 28, 28])
  2. tensor([7, 2, 1, 0])

可以看到图片的 tensor 形状为(4,1,28,28)分别对应 batch4,通道数为 1,每一张图片大小为 28×28

而每张图片标签的类别分别为 (7,2,1,0)

编程要求

根据提示,在右侧编辑器补充 Begin-End 中代码,编写 MNIST 数据集打包代码。

测试说明

平台会对你编写的代码进行测试:

测试1

测试输入:无 预期输出:

 
  1. 打包后测试集批数:2500
  2. 第一批测试集图像维度:torch.Size([4, 1, 28, 28])
  3. 第一批测试集标签: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 图片数组保存成图片,其函数原型为:

 
  1. matplotlib.pyplot.imsave(fname, arr)

其中 fname 为想要保存的图片文件名,例如 test.pngarr 为处理好的图片数组。

torchvision.utils.make_grid 库函数

上一节提到,最后第一批测试集图片的维度是 (4,1,28,28) 分别对应 batch4,通道数为 1,每一张图片大小为 28×28

现在我们利用 torchvision.utils.make_grid 库函数将四张图片拼接到一起:

 
  1. # 接上一节代码
  2. dataiter = iter(testloader)
  3. images, labels = dataiter.next()
  4. print(images.shape)
  5. images = torchvision.utils.make_grid(images) # 拼接图片
  6. print(images.shape)

输出结果:

 
  1. torch.Size([4, 1, 28, 28])
  2. torch.Size([3, 32, 122])

可以看到拼接以后,第一个维度 batch 不见了,取而代之的是图片的行列变成了 32×122,其中 32 中不仅包含原来的 28,还包含了 4 个像素位置的图片底宽,同时 122 也包含了 10 个像素的底宽。

通过 torchvision.utils.make_grid 库函数,四张图片被拼成了一下,接下来我们编写 imshow 可视化函数将拼接好的图片可视化展示出来。

可视化函数 imshow 编写

对于拼接后的图片,我们首先需要对其进行反归一化操作:

 
  1. img = img / 2 + 0.5 # unnormalize

接着将图片转换成 Numpy 数组:

 
  1. npimg = img.numpy()

最后调用 matplotlib.pyplot.imsave 库函数进行保存:

 
  1. plt.imsave("test.png", np.transpose(npimg, (1, 2, 0)))

注意:保存之前需要将 Numpy 数组的第一个通道维度放到最后也就是 np.transpose(npimg, (1, 2, 0)) 操作。

保存后的结果图片:

图  3


图 1 测试数据集可视化图

可以看到 28×28 分辨率的图像放大以后还是比较模糊。

编程要求

根据提示,在右侧编辑器补充 Begin-End 中代码,编写 MNIST 数据集可视化代码。

测试说明

平台会对你编写的代码进行测试:

测试1

测试输入:无 预期输出:

 
  1. 拼接前图片维度:torch.Size([4, 1, 28, 28])
  2. 拼接后图片维度:torch.Size([3, 32, 122])
  3. 图片类别名: 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
  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值