提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
一、LeNet-5简介
二、网路模型搭建及实例
1.网络模型搭建(net.py)
1.1方式一
1.2方式二(nn.Sequential)
1.3验证
2.模型训练(train.py)
2.1数据类型转换
2.2加载训练数据集
2.3加载测试集
2.4调用网络并采用GPU
2.5定义交叉熵损失函数
2.6优化器
2.7调整学习率
2.8定义训练函数
2.9验证
2.10开始训练
2.11输出
3.模型测试
3.1载入数据集
3.2调用网络和GPU
3.3获取结果
3.4可视化
3.5进行验证
3.6输出
提示:这里可以添加本文要记录的大概内容:
LeNet-5卷积神经网络是用于图像识别的经典神经网络,本文从零复现整个模型,同时采用相应的数据集进行训练和测试。
提示:以下是本篇文章正文内容,下面案例可供参考
LeNet-5由LeCun首次提出,是卷积神经网络里最经典的网络结构,LeNet-5最初被运用于MNIST数据库的手写的数字识别,对输入图像为32×32数字手写体进行10分类,LeNet-5不包含输入,由7层组成,目前,LeNet-5卷积神经网络是运用于图像识别的经典模型。
LeNet-5卷积神经网络包含1层输入层、2层卷积层、2层池化层、2层全连接层和1层输出层,其中卷积层和池化层交替计算进行,最后一层池化层连接全连接层,全连接层将二维特征图转化为一维特征向量。该网络的输入是32×32的图像。
C1层是由6个特征图组成的卷积层。每个神经元与输入图像的一个5×5的领域相连接,因此每个特征图的大小为28×28;
S2层是由6个大小为14×14的特征图组成的次抽样层,由C1池化得到(抽样),特征图的每个神经元与C1层的一个大小为2×2的领域连接;
C3层由16个大小为10×10的特征图组成的卷积层。特征图的每个神经元与S2网络层的若干个特征图的5×5的领域连接;
S4层是由16个大小为5×5的特征图组成的次抽样层。特征图的每个神经元与C3层的一个大小为2×2大小的领域相连接;
C5层由120个特征图组成的卷积层。每个神经元与S4网络层的所有特征图的5×5大小的领域相连接。
F6层,含84个神经元,与C5层进行全连接;
输出层含10个神经元,由径向基函数单元(RBF)组成,输出层的每个神经元对应一个字符类别;
import torch
from torch import nn
代码如下(示例):
class MyLeNet5(nn.Module):
#初始化网络
def __init__(self):
super(MyLeNet5,self).__init__()
self.Sigmoid = nn.Sigmoid()
self.conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,padding=2)
self.subs2 = nn.AvgPool2d(kernel_size=2,stride=2)
self.conv3 = nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5)
self.subs4 = nn.AvgPool2d(kernel_size=2,stride=2)
self.conv5 = nn.Conv2d(in_channels=16,out_channels=120,kernel_size=5)
self.flatten = nn.Flatten()
self.linear1 = nn.Linear(120,84)
self.linear2 = nn.Linear(84,10)
def forward(self,x):
x = self.conv1(x)
x = self.Sigmoid(x)
x = self.subs2(x)
x = self.conv3(x)
x = self.Sigmoid(x)
x = self.subs4(x)
x = self.conv5(x)
x = self.flatten(x)
x = self.linear1(x)
x = self.linear2(x)
return x
代码如下(示例):
class Tudui(nn.Module):
def __init__(self):
super(Tudui,self).__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,padding=2)
nn.Sigmoid()
nn.AvgPool2d(kernel_size=2,stride=2)
nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5)
nn.Sigmoid()
nn.AvgPool2d(kernel_size=2,stride=2)
nn.Conv2d(in_channels=16,out_channels=120,kernel_size=5)
nn.Flatten()
nn.Linear(120,84)
nn.Linear(84,10)
)
def forward(self,x):
x = self.model(x)
return x
if __name__ == "__main__":
x = torch.rand([1,1,28,28])
model = MyLeNet5()
y = model(x)
print(y)
输出为:
tensor([[ 0.0802, -0.0733, -0.1367, 0.0934, 0.0542, -0.0968, 0.0525, -0.0470,
0.0083, 0.0429]], grad_fn=)
import torch
from torch import nn
from torch.utils.data import DataLoader
from net import MyLeNet5
from torch.optim import lr_scheduler
from torchvision import datasets,transforms
import os
#数据转化为tensor格式
data_transform = transforms.Compose([
transforms.ToTensor()
])
#加载训练数据集
train_dataset = datasets.MNIST(root = './data',train =
True,transform=data_transform,download=True)
train_dataloader = DataLoader(train_dataset,batch_size=16,shuffle=True)
#加载测试集
test_dataset = datasets.MNIST(root = './data',train =
False,transform=data_transform,download=True)
test_dataloader = DataLoader(test_dataset,batch_size=16,shuffle=True)
#GPU
device = "cuda" if torch.cuda.is_available() else 'cpu'
#调用网络
model = MyLeNet5().to(device)
#交叉熵函数lossfunction
loss_fun = nn.CrossEntropyLoss()
#优化器
learning_rate = 1e-3
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,momentum=0.9)
#学习率每隔十轮变为之前的0.1
lr_scheduler = lr_scheduler.StepLR(optimizer,step_size=10,gamma=0.1)
#训练函数
def train(dataloader,model,loss_fun,optimiter):
loss,current,n = 0.0,0.0,0
for batch,(X,y) in enumerate(dataloader):
#前向传播
X,y = X.to(device),y.to(device)
output = model(X)
cur_loss= loss_fun(output,y)
_,pred = torch.max(output,axis = 1)
cur_acc = torch.sum(y == pred)/output.shape[0]#精确度
optimiter.zero_grad()
cur_loss.backward()
optimiter.step()
loss += cur_loss.item()
current += cur_acc.item()
n = n +1
print("train_loss"+str(loss/n))
print("train_acc"+str(current/n))
#验证
def val(dataloader,model,loss_fun):
model.eval()
loss,current,n = 0.0, 0.0,0
with torch.no_grad():
for batch, (X, y) in enumerate(dataloader):
# 前向传播
X, y = X.to(device), y.to(device)
output = model(X)
cur_loss = loss_fun(output, y)
_, pred = torch.max(output, axis=1)
cur_acc = torch.sum(y == pred)/output.shape[0]#精确度
loss += cur_loss.item()
current += cur_acc.item()
n = n +1
return current/n
#开始训练
epoch = 50
min_acc = 0
for t in range(epoch):
print(f'epoch{t+1}\n---------------')
train(train_dataloader,model,loss_fun,optimizer)
val(test_dataloader,model,loss_fun)
a = val(test_dataloader,model,loss_fun)
#保存最好的模型权重
if a > min_acc:
folder = 'save_model'
if not os.path.exists(folder):
os.mkdir('save_model')
min_acc =a
print('save best model')
torch.save(model.state_dict(),'save_model/best_model.pth')
print('Done!')
epoch1
---------------
train_loss2.3030501666386924
train_acc0.10741666666666666
save best model
epoch2
---------------
train_loss2.300391905848185
train_acc0.11306666666666666
save best model
epoch3
---------------
import torch
from torch.utils.data import DataLoader
from net import MyLeNet5
from torch.autograd import Variable
from torchvision import datasets,transforms
from torchvision.transforms import ToPILImage
#数据转化为tensor格式
data_transform = transforms.Compose([
transforms.ToTensor()
])
#加载数据集
train_dataset = datasets.MNIST(root = './data',train =
True,transform=data_transform,download=True)
train_dataloader = DataLoader(train_dataset,batch_size=16,shuffle=True)
#加载测试集
test_dataset = datasets.MNIST(root = './data',train =
False,transform=data_transform,download=True)
test_dataloader = DataLoader(test_dataset,batch_size=16,shuffle=True)
#GPU
device = "cuda" if torch.cuda.is_available() else 'cpu'
#调用网络
model = MyLeNet5().to(device)
model.load_state_dict(torch.load('C:\\Users\\86199\\Desktop\\LeNeT5\\save_model\\best_model.pth'))
#获取结果
classes = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
]
#tensor->PIL(可视化)
show = ToPILImage()
#进入验证
for i in range(20):
X,y = test_dataset[i][0],test_dataset[i][1]
show(X).show()
X = Variable(torch.unsqueeze(X,dim=0).float(),requires_grad = False).to(device)
with torch.no_grad():
pred = model(X)
predicted,actual = classes[torch.argmax(pred[0])],classes[y]
print(f'predicted:"{predicted}",actual:"{actual}"')
predicted:"7",actual:"7"
predicted:"2",actual:"2"
predicted:"1",actual:"1"
predicted:"0",actual:"0"
predicted:"4",actual:"4"
predicted:"1",actual:"1"
predicted:"4",actual:"4"
predicted:"9",actual:"9"
predicted:"5",actual:"5"
predicted:"9",actual:"9"
predicted:"0",actual:"0"
predicted:"6",actual:"6"
predicted:"9",actual:"9"
predicted:"0",actual:"0"
predicted:"1",actual:"1"
predicted:"5",actual:"5"
predicted:"9",actual:"9"
predicted:"7",actual:"7"
predicted:"3",actual:"3"
predicted:"4",actual:"4"
Process finished with exit code 0