卷积神经网络(LeNet)

卷积神经网络(LeNet)

一、前言

卷积神经网络(Convolutional Neural Network,CNN)是一种深度神经网络,广泛应用于图像处理、自然语言处理等领域。LeNet是最早的卷积神经网络之一,由Yann LeCun等人在1998年提出,用于手写数字的识别。本文将介绍LeNet的结构、原理和实现。

二、LeNet结构

LeNet的结构如下图所示:

输入层
卷积层
池化层
卷积层
池化层
全连接层
全连接层
输出层

LeNet包含7层网络结构,其中第1、2层是卷积层,第3、4层是池化层,第5、6层是全连接层,第7层是输出层。

三、LeNet原理

1. 卷积层

卷积层是LeNet的核心部分,它通过卷积操作提取图像的特征。卷积操作可以看做是一个滤波器(Filter)在图像上滑动,对每个位置的像素值进行加权求和。卷积操作的公式如下:

y i , j = ∑ m ∑ n x i + m , j + n w m , n y_{i,j} = \sum_{m}\sum_{n}x_{i+m,j+n}w_{m,n} yi,j=mnxi+m,j+nwm,n

其中, x x x是输入图像, w w w是滤波器, y y y是输出特征图, i , j i,j i,j表示输出特征图的坐标, m , n m,n m,n表示滤波器的坐标。

卷积操作的优点是可以共享权值,减少参数数量,同时可以提取局部特征,增强网络的稳定性。

2. 池化层

池化层是对卷积层输出的特征图进行降维操作,减少参数数量,同时可以提取特征的不变性。常见的池化操作有最大池化和平均池化。

最大池化的公式如下:

y i , j = max ⁡ m , n x i + m , j + n y_{i,j} = \max_{m,n}x_{i+m,j+n} yi,j=m,nmaxxi+m,j+n

平均池化的公式如下:

y i , j = 1 m × n ∑ m ∑ n x i + m , j + n y_{i,j} = \frac{1}{m\times n}\sum_{m}\sum_{n}x_{i+m,j+n} yi,j=m×n1mnxi+m,j+n

其中, x x x是输入特征图, y y y是输出特征图, i , j i,j i,j表示输出特征图的坐标, m , n m,n m,n表示池化窗口的大小。

3. 全连接层

全连接层是将池化层输出的特征图展开成一维向量,然后通过全连接层进行分类操作。全连接层的公式如下:

y = W x + b y = Wx + b y=Wx+b

其中, x x x是输入向量, W W W是权值矩阵, b b b是偏置向量, y y y是输出向量。

四、LeNet实现

下面使用PyTorch实现LeNet,并使用MNIST数据集进行训练和测试。

1. 数据准备

首先,我们需要下载MNIST数据集,可以使用torchvision库中的datasets模块进行下载:

import torch
import torchvision

train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=torchvision.transforms.ToTensor(), download=True)

2. 模型定义

定义LeNet模型,包括两个卷积层、两个池化层和两个全连接层:

class LeNet(torch.nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 6, kernel_size=5)
        self.pool1 = torch.nn.MaxPool2d(kernel_size=2)
        self.conv2 = torch.nn.Conv2d(6, 16, kernel_size=5)
        self.pool2 = torch.nn.MaxPool2d(kernel_size=2)
        self.fc1 = torch.nn.Linear(16*4*4, 120)
        self.fc2 = torch.nn.Linear(120, 84)
        self.fc3 = torch.nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool1(torch.relu(self.conv1(x)))
        x = self.pool2(torch.relu(self.conv2(x)))
        x = x.view(-1, 16*4*4)
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

3. 模型训练

定义损失函数和优化器:

model = LeNet()
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

进行模型训练:

for epoch in range(10):
    for i, (images, labels) in enumerate(train_loader):
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        if (i+1) % 100 == 0:
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch+1, 10, i+1, len(train_loader), loss.item()))

4. 模型测试

使用测试数据集进行模型测试:

correct = 0
total = 0
with torch.no_grad():
    for images, labels in test_loader:
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: {} %'.format(100 * correct / total))

五、总结

本文介绍了LeNet的结构、原理和实现,LeNet是卷积神经网络的基础,其结构简单、效果明显,是深度学习入门的良好选择。