【CNN】LeNet网络架构
1.MLP
多层感知机MLP(Multilayer Perceptron),也是人工神经网络(ANN,Artificial Neural Network),是一种全连接
多层感知机(Multilayer Perceptron, MLP)是一种前馈神经网络,它由输入层、若干隐藏层和输出层组成。每一层都由多个神经元(或称为节点)组成。
输入层(Input Layer):输入层接收外部输入的数据,将其传递到下一层。每个输入特征都对应一个神经元。
隐藏层(Hidden Layer):隐藏层是位于输入层和输出层之间的一层或多层神经元。每个隐藏层的神经元接收上一层传来的输入,并通过权重和激活函数进行计算,然后将结果传递到下一层。隐藏层的存在可以使多层感知机具备更强的非线性拟合能力。
输出层(Output Layer):输出层接收隐藏层的输出,并产生最终的输出结果。输出层的神经元数目通常与任务的输出类别数目一致。对于分类任务,输出层通常使用softmax激活函数来计算每个类别的概率分布;对于回归任务,输出层可以使用线性激活函数。
多层感知机的各层之间是全连接的,也就是说,每个神经元都与上一层的每个神经元相连。每个连接都有一个与之相关的权重和一个偏置。
2.LeNet简介
LeNet-5模型是由杨立昆(Yann LeCun)教授于1998年在论文Gradient-Based Learning Applied to Document Recognition中提出的,是一种用于手写体字符识别的非常高效的卷积神经网络,其实现过程如下图所示。
原论文的经典的LeNet-5网络结构如下:
各个结构作用:
卷积层:提取特征图的特征,浅层的卷积提取的是一些纹路、轮廓等浅层的空间特征,对于深层的卷积,可以提取出深层次的空间特征。
池化层: 1、降低维度 2、最大池化或者平均池化,在本网络结构中使用的是最大池化。
全连接层: 1、输出结果 2、位置:一般位于CNN网络的末端。 3、操作:需要将特征图reshape成一维向量,再送入全连接层中进行分类或者回归。
下来我们使用代码详解推理一下各卷积层参数的变化:
import torch
import torch.nn as nnx = torch.randn([1,1,32,32])conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5)
c1 = conv1(x)
print(c1.shape)pool = nn.MaxPool2d(2)s1 = pool(c1)
print(s1.shape)conv2 = nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5)c2 = conv2(s1)
print(c2.shape)
s2 = pool(c2)
print(s2.shape)
pytorch实现最简单的LeNet模型
import torch
import torch.nn as nn
import torch.nn.functional as Fclass LeNet(nn.Module):def __init__(self):super(LeNet, self).__init__()self.conv1 = nn.Conv2d(1, 6, 5,stride=1)self.conv2 = nn.Conv2d(6, 16, 5,stride=1)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120,84)self.fc3 = nn.Linear(84,10)self.relu = nn.ReLU()def forward(self,x):x = self.relu(self.conv1(x))x = F.avg_pool2d(x,kernel_size=2,stride=2)s = self.relu(self.conv2(x))x = F.avg_pool2d(s,kernel_size=2,stride=2)x = torch.flatten(x,1)x = self.relu(self.fc1(x))x = self.relu(self.fc2(x))x = self.fc3(x)return xmodel = LeNet()print(model)
3.Mnist数据集
3.1MNIST数据集简介
该数据集包含60,000个用于训练的示例和10,000个用于测试的示例。
数据集包含了0-9共10类手写数字图片,每张图片都做了尺寸归一化,都是28x28大小的灰度图。
MNIST数据集包含四个部分: 训练集图像:train-images-idx3-ubyte.gz(9.9MB,包含60000个样本) 训练集标签:train-labels-idx1-ubyte.gz(29KB,包含60000个标签) 测试集图像:t10k-images-idx3-ubyte.gz(1.6MB,包含10000个样本) 测试集标签:t10k-labels-idx1-ubyte.gz(5KB,包含10000个标签)
3.2 MNIST数据集的预处理
import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
import structtransform = transforms.Compose([transforms.ToTensor(),transforms.Lambda(lambda x: x.view(-1,1))
])train_dataset = datasets.MNIST(root = "./dataset",train = True,transform = transform,download = True
)
test_dataset = datasets.MNIST(root = "./dataset",train = False,transform = transform,download = True
)train_loader = DataLoader(dataset = train_dataset,batch_size = 64,shuffle = True,
)
test_loader = DataLoader(dataset = test_dataset,batch_size = 64,shuffle = False,
)print(F"训练集样本数量:{len(train_dataset)}")
print(F"测试集样本数量:{len(test_dataset)}")print("=" * 140)
print("图像矩阵的十六进制表示(非0用红色表示):")
data = train_dataset[0][0].squeeze().numpy()
rows = 28
colums = 28
counter = 0
# for i in range(rows):
# row = data[i * colums:(i + 1) * colums]
# for value in row:
# integer_part = int(value * 100)
# integer_part = max(0,min(65535,integer_part))
# hex_bytes = struct.pack("H", integer_part)
# hex_string = hex_bytes.hex()
# if hex_string == '0000':
# print(' ', end='')
# else:
# print(F"\033[31m{hex_string}\033[0m", end="")
# counter += 1
# if counter % 28 == 0: print()
print("=" * 140)
for images,labels in train_loader:print("Batch Image Shape:",images.shape)print("Batch Label Shape:",labels.shape)#输出三张图片,我想把四张图输出在一个图中for i in range(4):plt.subplot(2,2,i+1)img = images[i].reshape(28,28).numpy()plt.imshow(img,cmap='gray')plt.title(F"Label:{labels[i].item()}")plt.show()print(labels[i])# img = images[0].reshape(28,28).numpy()# plt.imshow(img,cmap='gray')# plt.title(F"Label:{labels[0].item()}")# plt.axis('off')# plt.show()break