经典神经网络的学习--LeNet-5

一、LeNet-5网络的介绍
这里参考论文:《Gradient-Based Learning Applied to Document Recognition》(LeNet-5)(具体论文可以自己去网上找)
LeNet-5网络结构如下所示:
在这里插入图片描述
网络结构的具体介绍请看代码里面关于网络的注释。

二、实现代码(代码里面有详细的介绍)

import time

import torch
from matplotlib import pyplot as plt
from torch import nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import torch.nn.functional as F


#1.1(注意:先下载数据集datasets,再加载)下载并加载数据集datasets,并进行预处理torch.utils.data.DataLoader
#数据预处理
#   MNIST是一个手写体数字识别数据集,里面每张图片都是单通道的,大小为28*28
train_transforms=transforms.Compose([
    #随机旋转
    transforms.RandomHorizontalFlip(),
    #MNIST里面图片大小为单通道的28*28
    transforms.Resize((32,32)),
    #将图片变成张量
    transforms.ToTensor(),
    #正则化,防止模型出现过拟合现象,不同数据集正则化的均值和反差都是不同的且是确定的
    transforms.Normalize((0.1307,), (0.3081,))

])

test_transforms=transforms.Compose([
    #MNIST里面图片大小为单通道的28*28
    transforms.Resize((32,32)),
    #将图片变成张量
    transforms.ToTensor(),
    #正则化,防止模型出现过拟合现象,不同数据集正则化的均值和反差都是不同的且是确定的
    transforms.Normalize((0.1307,), (0.3081,))

])

#下载数据集datasets
train_set=datasets.MNIST(root='./MNIST_data',train=True,transform=train_transforms,download=True)
test_set=datasets.MNIST(root='./MNIST_data',train=False,transform=test_transforms,download=True)
#加载数据集dataloader
train_dataloader=torch.utils.data.DataLoader(dataset=train_set,batch_size=64,shuffle=True)
test_dataloader=torch.utils.data.DataLoader(dataset=test_set,batch_size=32,shuffle=False)


#1.2创建LeNet-5神经网络,并定义前向传播的过程
'''
C:卷积层;S:池化层(包括下采样和激活层);F:全连接层
卷积->激活->池化
input:输入一张32*32的单通道二维图片
C1:kernel=6个5*5(采用多卷积核的特征映射),padding=0(零填充为0),stride=1,得到6个(32-5+1=28)28*28的特征图
S2:用kernel=6个2*2的卷积核进行池化,padding=0;stride=2,得到6个14*14大小的特征图。(池化后,用sigmoid进行非线性输出)
C3:kernel=16个5*5*n的卷积核(这里的卷积用了多通道多卷积核的方式,每个卷积核的每个通道都是不一样的)
S4:kernel=16个2*2的卷积核,padding=0,stride=2,得到16个5*5的特征图
C5:(相当于一个线性层)kernel=120个5*5*16(即5*5的16通道卷积核),padding=0,stride=1,得到120个1*1的特征图,即相当于120个神经元的全连接层
F6:共84个神经元,全连接层
output层:全连接层,Caussian Connections,采用了RBF径向基函数,计算输入向量与参数向量之间的欧式距离
'''
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet,self).__init__()
        self.conv1=nn.Conv2d(1,6,5)#(in_channel,out_channel,kernel_size,strite,padding)
        self.relu=nn.ReLU()
        self.maxpool1=nn.MaxPool2d(2,2)#(kernel,stride,padding)
        self.conv2=nn.Conv2d(6,16,5)
        self.maxpool2=nn.MaxPool2d(2,2)
        self.f1=nn.Linear(16*5*5,120)#全连接层,输入输出的神经元个数
        self.f2=nn.Linear(120,84)
        self.f3=nn.Linear(84,10)#这是一个10分类问题0-9数字的识别,所以最后输出的是10个神经元

    def forward(self,x):
        x=self.conv1(x)
        x=self.relu(x)
        x=self.maxpool1(x)
        x=self.conv2(x)
        x=self.maxpool2(x)
        #由于线性层f1的输入神经元数量为16*5*5,所以要对maxpool2后的数据进行处理
        x=x.view(-1,16*5*5)
        x=F.relu(self.f1(x))
        x=F.relu(self.f2(x))
        x=self.f3(x)
        output=F.log_softmax(x,dim=1)#最后经过一个归一化的softmax()激活函数dim=1表示对行进行归一化
        return output



#1.3网络模型model初始化,将定义好的网络结构搭载到GPU上面,并定义优化器
model=LeNet()
device=torch.device('cuda'if torch.cuda.is_available() else'cpu')
model=model.to(device)
optimzer=optim.Adam(model.parameters(),lr=0.001)#优化器里面应该包含要优化的模型参数和学习率




#1.4定义训练过程model.train(),并进行参数优化
def train_running(model,device,train_dataloader,optimzer,epoch):
    model.train()#表示这里是训练过程
    correct=0
    total=0
    #迭代已经加载的训练集,同时获取训练集的下标和数据(data,label)
    #每次加载的是一个batch
    #batch_size=64
    for i,data in enumerate(train_dataloader,0):
        inputs,labels=data
        #把数据加载到cuda上面
        inputs,labels=inputs.to(device),labels.to(device)
        outputs=model(inputs)

        #初始梯度
        optimzer.zero_grad()
        #计算损失函数,这里使用交叉熵
        loss=F.cross_entropy(outputs,labels)

        #取输出outputs的最大值作为预测
        predict=outputs.argmax(dim=1)#表示输出行的最大值
        correct+=(predict==labels).sum().item()#求预测正确的标签数量
        total+=labels.size(0)

        #反向传播
        loss.backward()
        #优化器参数更新
        optimzer.step()

        #每1000个batch输出一次当前的损失,和正确率
        #损失是当前的损失,正确率是现在的平均正确率
        if i%1000 ==0:
            #loss.item()表示当前的损失值
            print("Train_epoch{}\t Loss:{:.6f},accuracy:{:.6f}%".format(epoch,loss.item(),100*(correct/total)))
            #把每1000次的损失和正确率记录到Loss和Accuracy
            Loss.append(loss.item())
            Accuracy.append(correct/total)
    #返回一次迭代epoch后的损失和正确率
    #即返回完整迭代一次后的损失和正确率
    return loss.item(),correct/total



#1.5定义测试过程model.eval()
#由于验证不需要优化,因此不需要优化器optimzer
def test_running(model,test_dataloader,device):
    #表示这里模型是用于验证,不进行梯度计算
    '''
     model.eval()
     with torch.no_grad():
     这两个是成对出现的
    :param model:
    :param test_dataloader:
    :param device:
    :return:
    '''
    model.eval()
    test_loss=0.0#测试集里面数据的总损失
    total=0#测试集里的总数据量
    correct=0.0
    #直接取出测试集里面的数据(data,label)
    with torch.no_grad():
        for data,label in test_dataloader:
            data,label=data.to(device),label.to(device)
            output=model(data)
            test_loss+=F.cross_entropy(output,label).item()
            predict=output.argmax(dim=1)
            #计算正确率
            total+=label.size(0)
            correct+=(predict==label).sum().item()
        print("test_avarage_loss:{:.6f},arruracy:{:.6f}%".format(test_loss/total,100*(correct/total)))





#1.6运行
epoch=5#训练集整体迭代次数
Loss=[]
Accuracy=[]
for epoch in range(1,epoch+1):
    #输出一轮训练开始时间
    print("start_time:",time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
    loss,acc=train_running(model,device,train_dataloader,optimzer,epoch)
    Loss.append(loss)
    Accuracy.append(acc)
    test_running(model,test_dataloader,device)
    #输出一轮训练+测试后结束的时间
    print("end_time:", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())),'\n')

print('Finished Training!')

#画图

plt.subplot(2,1,1)
plt.plot(Loss)
plt.title("Loss")
plt.show()

plt.subplot(2,1,2)
plt.plot(Accuracy)
plt.title("Accuracy")
plt.show()

在这里插入图片描述
在这里插入图片描述

注意:当在pycharm里面plt.show()无法显示图片时,在pycharm中设置解决步骤如下:Setting->Tools->Python Scientific->Show plots in Toolwindow ,然后取消勾选就可以了,然后就可以弹出显示图形了
这里参考大佬的解决方法:https://blog.csdn.net/weixin_40893448/article/details/115264440?ops_request_misc=&request_id=&biz_id=102&utm_term=plt%E4%B8%8D%E5%9C%A8pycharm%E9%87%8C%E9%9D%A2%E6%98%BE%E7%A4%BA&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-115264440.142v31pc_rank_34,185v2control&spm=1018.2226.3001.4187

侵删!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeNet-5神经网络 C源代码,这个写的比较好,可以用gcc编译去跑,结合理论可以对深度学习有更深刻的了解 介绍 根据YANN LECUN的论文《Gradient-based Learning Applied To Document Recognition》设计的LeNet-5神经网络,C语言写成,不依赖任何第三方库。 MNIST手写字符集初代训练识别率97%,多代训练识别率98%。 DEMO main.c文件为MNIST数据集的识别DEMO,直接编译即可运行,训练集60000张,测试集10000张。 项目环境 该项目为VISUAL STUDIO 2015项目,用VISUAL STUDIO 2015 UPDATE1及以上直接打开即可编译。采用ANSI C编写,因此源码无须修改即可在其它平台上编译。 如果因缺少openmp无法编译,请将lenet.c中的#include和#pragma omp parallel for删除掉即可。 API #####批量训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 inputs: 要训练的多个图片对应unsigned char二维数组的数组,指向的二维数组的batchSize倍大小内存空间指针。在MNIST测试DEMO中二维数组为28x28,每个二维数组数值分别为对应位置图像像素灰度值 resMat:结果向量矩阵 labels:要训练的多个图片分别对应的标签数组。大小为batchSize batchSize:批量训练输入图像(二维数组)的数量 void TrainBatch(LeNet5 *lenet, image *inputs, const char(*resMat)[OUTPUT],uint8 *labels, int batchSize); #####单个训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 要训练的图片对应二维数组 resMat:结果向量矩阵 label: 要训练的图片对应的标签 void Train(LeNet5 *lenet, image input, const char(*resMat)[OUTPUT],uint8 label); #####预测 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 输入的图像的数据 labels: 结果向量矩阵指针 count: 结果向量个数 return 返回值为预测的结果 int Predict(LeNet5 *lenet, image input, const char(*labels)[LAYER6], int count); #####初始化 lenet: LeNet5的权值的指针,LeNet5神经网络的核心

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值