部分图片可能加载不出,完整版实验报告、程序代码、所需实验数据均见本人上传资源
实验六 卷积神经网络 CNN 框架的实现与应用
一、实验目的
1. 掌握卷积神经网络 CNN 的基本原理
2. 利用 CNN 实现手写数字识别
二、实验原理
利用 LeNet-5 CNN 框架,实现手写数字识别。
1. 网络层级结构概述如图 1:7 层神经网络
Input layer: 输入数据为原始训练图像
Conv1:6 个 5*5 的卷积核,步长 Stride 为 1
Pooling1:卷积核 size 为 2*2,步长 Stride 为 2
Conv2:12 个 5*5 的卷积核,步长 Stride 为 1
Pooling2:卷积核 size 为 2*2,步长 Stride 为 2
Output layer:输出为 10 维向量
2. 实验基本流程
(1)获取训练数据和测试数据;
(2)定义网络层级结构;
(3)初始设置网络参数(权重 W,偏向 b)cnnsetup(cnn, train_x, train_y)
(4)训练超参数 opts 定义(学习率,batchsize,epoch)
(5)网络训练之前向运算 cnnff(net, batch_x)
(6)网络训练之反向传播 cnnbp(net, batch_y)
(7)网络训练之参数更新 cnnapplygrads(net, opts)
(8)重复(5)(6)(7),直至满足 epoch
(9)网络测试 cnntest(cnn, test_x, test_y)
三、实验内容
1. 数据集:MNIST 数据集,60000 张训练图像,10000 张测试图像,每张图像size 为 28*28
2. 利用 LeNet-5 CNN 框架,实现手写数字识别。
四、实验结果及分析
1. 利用交叉验证方法,分析识别结果 。
- 分析网络参数 opts 设置对最终识别结果的影响,画出相应的结果分析图
- 加载数据集,导入数据
在此之前,我下载了有关MNIST的数据集,后来通过查询相关资料,得知torchvision.datasets中有一些常用的数据集,其中就包含mnist,在此,直接进行下载并导入,定义预处理函数,这些预处理依次放在Compose函数中
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])])
下载数据集并对数据进行预处理
train_set = mnist.MNIST("./mnist_data", train=True, download=True, transform=transform)
test_set = mnist.MNIST("./mnist_data", train=False, transform=transform)
确定训练时的数据加载方式,用来把训练数据分成多个小组,此函数每次抛出一组数据。直至把所有的数据都抛出。就是做一个数据的初始化。
加载MNIST数据集:shuffle为True,则在每次epoch时重新打乱顺序
train_loader = torch.utils.data.DataLoader(train_set, batch_size=train_batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=test_batch_size, shuffle=False)
- 构建网络
LeNet5网络有7层:
- 第1层:卷积层输入:原始的图片像素矩阵(长度、宽度、通道数),大小为32×32×1;
参数:滤波器尺寸为5×5,深度为6,不使用全0填充,步长为1
输出:特征图,大小为28×28×6。
分析:因为没有使用全0填充,所以输出尺寸=32-5+1=28,深度与滤波器深度一致,为6。
- 第2层:池化层;输入:特征图,大小为28×28×6;
参数:滤波器尺寸为2×2,步长为2
输出:特征图,大小为14×14×6。
3.第3层:卷积层;输入:特征图,大小为14×14×6;
参数:滤波器尺寸为5×5,深度为16,不使用全0填充,步长为1;
输出:特征图,大小为10×10×16。
分析:因为没有使用全0填充,所以输出尺寸=14-5+1=10,深度与滤波器深度一致,为16。
4.第4层:池化层 输入:特征图,大小为10×10×16;
参数:滤波器尺寸为2×2,步长为2;
输出:特征图,大小为5×5。
5.第5层:全连接层;输入节点个数:5×5×16 = 400;
参数个数:5×5×16×120+120 = 48120;
输出节点个数:120。
6.第6层:全连接层;输入节点个数:120;
参数个数:120×84+84 = 10164;
输出节点个数:84。
7.第7层:全连接层
输入节点个数:84;
参数个数:84×10+10 = 850;
输出节点个数:10。
定义网络模型,初始化网络
class LeNet5(nn.Module):
def __init__(self, in_channel, output):
super(LeNet5, self).__init__()
Conv1:6 个 5*5 的卷积核,步长 Stride 为 1
Pooling1:卷积核 size 为 2*2,步长 Stride 为 2
self.layer1 = nn.Sequential(nn.Conv2d(in_channels=in_channel, out_channels=6, kernel_size=5, stride=1, padding=2), # (6, 28, 28)
nn.Tanh(),
nn.AvgPool2d(kernel_size=2, stride=2, padding=