LeNet-5经典卷积神经网络模型搭建及应用实例

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言

一、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简介

LeNet-5由LeCun首次提出,是卷积神经网络里最经典的网络结构,LeNet-5最初被运用于MNIST数据库的手写的数字识别,对输入图像为32×32数字手写体进行10分类,LeNet-5不包含输入,由7层组成,目前,LeNet-5卷积神经网络是运用于图像识别的经典模型。

LeNet-5经典卷积神经网络模型搭建及应用实例_第1张图片

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)组成,输出层的每个神经元对应一个字符类别;

二、网路模型搭建及实例

1.网络模型搭建(net.py)

import torch
from torch import nn

1.1方式一

代码如下(示例):

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

1.2方式二(nn.Sequential)

代码如下(示例):

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

1.3验证

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=)

2.模型训练(train.py)

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

2.1数据类型转换

#数据转化为tensor格式
data_transform = transforms.Compose([
    transforms.ToTensor()
     ])

2.2加载训练数据集

#加载训练数据集
train_dataset = datasets.MNIST(root = './data',train = 
            True,transform=data_transform,download=True)
train_dataloader = DataLoader(train_dataset,batch_size=16,shuffle=True)

2.3加载测试集

#加载测试集
test_dataset = datasets.MNIST(root = './data',train = 
            False,transform=data_transform,download=True)
test_dataloader = DataLoader(test_dataset,batch_size=16,shuffle=True)

2.4调用网络并采用GPU

#GPU
device = "cuda" if torch.cuda.is_available() else 'cpu'
#调用网络
model = MyLeNet5().to(device)

2.5定义交叉熵损失函数

#交叉熵函数lossfunction
loss_fun = nn.CrossEntropyLoss()

2.6优化器

#优化器
learning_rate = 1e-3
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,momentum=0.9)

2.7调整学习率

#学习率每隔十轮变为之前的0.1
lr_scheduler = lr_scheduler.StepLR(optimizer,step_size=10,gamma=0.1)

2.8定义训练函数

#训练函数
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))

2.9验证

#验证
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

2.10开始训练

#开始训练
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!')

2.11输出

epoch1
---------------
train_loss2.3030501666386924
train_acc0.10741666666666666
save best model
epoch2
---------------
train_loss2.300391905848185
train_acc0.11306666666666666
save best model
epoch3
---------------

3.模型测试

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

3.1载入数据集

#数据转化为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)

3.2调用网络和GPU

#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'))

3.3获取结果

#获取结果
classes = [
    "0",
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
]

3.4可视化

#tensor->PIL(可视化)
show = ToPILImage()

3.5进行验证

#进入验证
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}"')

3.6输出

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

你可能感兴趣的:(图像识别,深度学习,cnn,深度学习,人工智能)