《Gradient-Based Learning Applied to Document Recognition》(《基于梯度学习在文档识别中的应用》)是卷积神经网络的开山之作,主要有LeNet-1~LeNet-5系列。这里主要实现LeNet-5。
摘要:将反向传播算法的多层神经网络应用在图像上,提出卷积神经网络。应用在两个方面:①在线手写识别的系统、②读取银行支票的图形转换器。
卷积神经网络------用来处理图像问题。
LeNet-5是一个简单的卷积神经网络,有卷积层,降采样层,全连接层,输出层组成。
降采样(下采样):即为池化,将图像缩小。AlexNet将其更名为池化层。
记住:通道数=卷积核个数
输入图像的尺寸统一归一化为32×32。
输入图片:32×32
卷积核大小:5×5
卷积核个数:6
输出feature map大小:28×28,(32-5+1)=28
stride:1
输入图片:28×28
采样区域:2×2
采样方式:4个输入相加,乘以一个可训练参数,再加上一个可偏置训练。结果通过sigmoid
过滤器个数:6
输出feature map大小:14×14,(28/2)
stride:2,选择最大池化层
输入:14×14
卷积核大小:5×5
卷积核个数16
输出feature map大小:10×10,(14-5+1)=10
stride:1
输入:10×10
采样区域:2×2
采样方式:4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。结果通过sigmoid
过滤器个数:16
输出feature map大小:5×5,(10/2)
stride:2,选择最大池化层
输入:16×5×5
输入:120
输入:120
输出:84
全连接层:输入:84,输出:10(分成了10类)
加softmax层
class LeNet5(nn.Module):
def __init__(self,num_classes,grayscale=False) -> None:
super().__init__()
self.grayscale=grayscale
self.num_classes=num_classes
if self.grayscale:
in_channels=1
else:
in_channels=3
self.feature=nn.Sequential(
nn.Conv2d(in_channels=in_channels,out_channels=6,
kernel_size=5,stride=1),
nn.MaxPool2d(kernel_size=2,stride=2),
nn.Conv2d(6,16,5,1),
nn.MaxPool2d(kernel_size=2,stride=2)
)
self.classifier=nn.Sequential(
nn.Linear(16*5*5,120),
nn.Linear(120,84),
nn.Linear(84,num_classes),
nn.Softmax(dim=1) # 输出10个可能的概率
)
def forward(self,x):
x=self.feature(x) #输出16*5*5的feature map
x=torch.flatten(x,1) #展平(1,16*5*5)
x=self.classifier(x) #输出10个
return x
num_classes=10 #分类数目
grayscale=True #是否为灰度数
model=LeNet5(num_classes,grayscale)
input_data=torch.randint(10,size=(1,1,32,32),dtype=torch.float32)
print('输入图片的形状:{}'.format(input_data))
output_data=model(input_data)
print('测试输出图片的形状:{}'.format(output_data))
使用pytorch提供的数据集:
train_data=torchvision.datasets.MNIST(root="./MNIST",train=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.Resize((32,32)),torchvision.transforms.ToTensor(),
]),
download=True)
test_data=torchvision.datasets.MNIST(root="./MNIST",train=False,
transform=torchvision.transforms.Compose([
torchvision.transforms.Resize((32, 32)),torchvision.transforms.ToTensor(),
]),
download=True)
train_dataloader=DataLoader(dataset=train_data,batch_size=100,drop_last=False)
test_dataloader=DataLoader(dataset=test_data,batch_size=100,drop_last=False)
print('训练集的长度:{}'.format(len(train_data)))
print('测试集的长度:{}'.format(len(test_data)))
#print('第一张图片的信息:{}'.format(train_data[0]))
img,label=train_data[0]
print('第一张图片的信息:{},第一张图片的label:{}'.format(img,label))
print('------------------------------------------------------')
print(img.shape)
输出结果:图片的类型为tensor数据类型,label为int数据类型。是符合pytorch网络的输入输出的。
loss_fn=nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()
learning_rate=1e-4
optimizer=torch.optim.Adam(model.parameters(),learning_rate)
total_train_step=0
total_test_step=0
epoch=20
for i in range(epoch):
print("-------------------第{}轮训练开始------------------".format(i))
model.train()
for data in train_dataloader:
imgs,targets=data
imgs=imgs.cuda()
targets=targets.cuda()
outputs=model(imgs)
loss=loss_fn(outputs,targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step=total_train_step+1
print("在训练集上的训练次数:{},loss:{}".format(total_train_step,loss.item()))
model.eval()
total_accuracy=0
with torch.no_grad():
for data in test_dataloader:
imgs,targets=data
imgs=imgs.cuda()
targets=targets.cuda()
outputs=model(imgs)
loss=loss_fn(outputs,targets)
accuracy=(outputs.argmax(1)==targets).sum()
total_accuracy=total_accuracy+accuracy
print("整体测试集上的正确率:{}".format(total_accuracy/len(test_data)))
total_test_step=total_test_step+1
结果:结果还不错!
这个网络是世界上第一个卷积神经网络,网络比较小,手写数字数据集也小,如果用在大型数据集上,效果就不好了!