目录
一. 开发背景
Lenet 是一系列网络的合称,包括 Lenet1 - Lenet5,由 Yann LeCun 等人 在1990年《Handwritten Digit Recognition with a Back-Propagation Network》中提出,是卷积神经网络的开山之作,也是将深度学习推向繁荣的一座里程碑。
LeNet首次采用了卷积层、池化层这两个全新的神经网络组件,接收灰度图像,并输出其中包含的手写数字,在手写字符识别任务上取得了瞩目的准确率。LeNet网络的一系列的版本,以LeNet-5版本最为著名,也是LeNet系列中效果最佳的版本。
二. 网络结构
Lenet是一个 7 层的神经网络,包含 3 个卷积层,2 个池化层,1 个全连接层,1个输出层。其中所有卷积层的卷积核都为 5x5,步长=1,池化方法都为平均池化,激活函数为 Sigmoid(目前使用的Lenet已改为ReLu),网络结构如下:
网络结构详解:深度学习经典网络解析图像分类篇(一):LeNet-5
三. 模型特点
- 首次提出卷积神经网络基本框架: 卷积层,池化层,全连接层;
- 卷积层的权重共享,相较于全连接层使用更少参数,节省了计算量与内存空间;
- 卷积层的局部连接,保证图像的空间相关性;
- 使用映射到空间均值下采样,减少特征数量;
- 使用双曲线(tanh)或S型(sigmoid)形式的非线性激活函数。
四. 代码实现
- model.py:定义LeNet网络模型
- train.py:加载数据集并训练,计算loss和accuracy,保存训练好的网络参数
- predict.py:用自己的数据集进行分类测试
1. model.py
# 导入pytorch库
import torch
# 导入torch.nn模块
from torch import nn
# 定义LeNet网络模型
# MyLeNet5(子类)继承nn.Module(父类)
class MyLeNet5(nn.Module):
# 子类继承中重新定义Module类的__init__()和forward()函数
# init()函数:进行初始化,申明模型中各层的定义
def __init__(self):
# super:引入父类的初始化方法给子类进行初始化
super(MyLeNet5, self).__init__()
# 卷积层,输入大小为28*28,输出大小为28*28,输入通道为1,输出为6,卷积核为5,扩充边缘为2
self.c1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2)
# 使用sigmoid作为激活函数
self.Sigmoid = nn.Sigmoid()
# AvgPool2d:二维平均池化操作
# 池化层,输入大小为28*28,输出大小为14*14,输入通道为6,输出为6,卷积核为2,步长为2
self.s2 = nn.AvgPool2d(kernel_size=2, stride=2)
# 卷积层,输入大小为14*14,输出大小为10*10,输入通道为6,输出为16,卷积核为5
self.c3 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)
# 池化层,输入大小为10*10,输出大小为5*5,输入通道为16,输出为16,卷积核为2,步长为2
self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)
# 卷积层,输入大小为5*5,输出大小为1*1,输入通道为16,输出为120,卷积核为5
self.c5 = nn.Conv2d(in_channels=16, ou