卷积神经网络LeNet-5的pytorch代码实现

详解卷积神经网络LeNet-5一文中,我详细介绍了一下Lenet-5的基本原理,下面简要介绍一下Lenet-5的pytorch代码实现。
建议本文对应上文一起查看。

一、Lenet-5网络模型实现

LeNet-5 神经网络一共五层,其中卷积层和池化层可以考虑为一个整体,网络的结构为 :

输入 → 卷积 → 池化 → 卷积 → 池化 → 卷积(全连接) → 全连接 → 输出。
编程之前,先看一下相关数值:

层数in_channelout_channelkernel_sizestridepadding
卷积层C116512
池化层S266220
卷积层C3616510
池化层S41616220

【注】:池化层的in_channel和out_channel不会变。

层数输入输出
卷积层C516120
全连接层F612084
输出层8410
Step1: 引入必要的包

代码如下:

import torch
from torch import nn
import torch.nn.functional as F
Step2:搭建卷积层C1和池化层S2

代码如下:

		#输入:(6*28*28);输出:(6*14*14)
        self.conv1 = nn.Sequential(     
            nn.Conv2d(1,6,kernel_size=5,stride=1,padding=2), #新建卷积层,kernel_size表示卷积核大小,stride表示步长,padding=2,图片大小变为 28+2*2 = 32 (两边各加2列0),保证输入输出尺寸相同
            nn.ReLU(),
            #可以选择取最大值池化MaxPool2d,也可以选择取平均值池化AvgPool2d,两者参数相同
            nn.MaxPool2d(kernel_size = 2 ,stride = 2,padding=0)   #input_size=(6*28*28),output_size=(6*14*14)
        )

这段代码对应于第1个卷积层和第1个池化层。

nn.Conv2d是2D卷积的意思,in_channels定义输入通道的数量,out_channels定义输出通道的数量,kernel_size定义卷积核的尺寸,stride定义卷积步长,padding表示增加的边框尺寸。
输出的size尺寸:

size = (h - kernel_size + 2*padding)/stride + 1

接着每个激活函数后面连接一个最大池化(现在用的比较多的也是最大池化),这样,我们这两层神经网络就搭建完成了。

Step3:搭建卷积层C3和池化层S4

代码如下:

#输入:(6*14*14);输出:(16*5*5)
self.conv2 = nn.Sequential(
    nn.Conv2d(6,16,kernel_size=5,stride=1,padding=0), #input_size=(6*14*14),output_size=16*10*10
    nn.ReLU(),
    nn.MaxPool2d(kernel_size = 2,stride = 2,padding=0)    ##input_size=(16*10*10),output_size=(16*5*5)
)

这段代码对应于第2个卷积层和第2个池化层。

Step4:搭建全连接层C5、全连接层F6以及输出层

代码如下:

#全连接层
self.fc1 = nn.Sequential(
    nn.Linear(16*5*5,120),
    nn.ReLU()
)
#全连接层
self.fc2 = nn.Sequential(
    nn.Linear(120,84),
    nn.ReLU()
)
#全连接层
self.fc3 = nn.Linear(84,10)
Step5:设置网络前向传播
#网络前向传播过程
def forward(self,x):
    x = self.conv1(x)
    x = self.conv2(x)
 
    x = x.view(x.size(0), -1) #全连接层均使用的nn.Linear()线性结构,输入输出维度均为一维,故需要把数据拉为一维
    x = self.fc1(x)
    x = self.fc2(x)
    x = self.fc3(x)
    return x
Step6:查看神经网络

代码如下:

#查看网络
myNet = LeNet5()
print(myNet) 

输出结果:
在这里插入图片描述

二、Lenet-5实现MNIST手写数字识别

Step1:载入训练集和测试集

代码:

#load data
transform = torchvision.transforms.ToTensor()   #定义数据预处理方式:转换 PIL.Image 成 torch.FloatTensor
 
train_data = torchvision.datasets.MNIST(root="E:\\python_mnist\mnist\\train",    #数据目录,这里目录结构要注意。
                                        train=True,                                     #是否为训练集
                                        transform=transform,                            #加载数据预处理
                                        download=False)                                 #是否下载
test_data = torchvision.datasets.MNIST(root="E:\\python_mnist\mnist\\train",
                                        train=False,
                                        transform=transform,
                                        download=False)
#数据加载器:组合数据集和采样器 
train_loader = torch.utils.data.DataLoader(dataset = train_data,batch_size = 64,shuffle = True) 
test_loader = torch.utils.data.DataLoader(dataset = test_data,batch_size = 64,shuffle = False)

第一次训练时,就把参数download改成True,先下载再训练。

Step2:观察部分MNIST数据集

代码如下:

import numpy as np
import matplotlib.pyplot as plt
def imshow(img):
     img = img / 2 + 0.5 # unnormalize
     npimg = img.numpy()
     plt.imshow(np.transpose(npimg, (1, 2, 0)))
     plt.show()

# torchvision.utils.make_grid 将图片进行拼接
imshow(torchvision.utils.make_grid(iter(train_loader).next()[0]))

输出结果:
在这里插入图片描述

Step3:设置损失函数和优化器

代码如下:

#define loss
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")   #若检测到GPU环境则使用GPU,否则使用CPU
net = LeNet().to(device)    #实例化网络,有GPU则将网络放入GPU加速
loss_fuc = nn.CrossEntropyLoss()    #多分类问题,选择交叉熵损失函数
optimizer = optim.SGD(net.parameters(),lr = 0.001,momentum = 0.9)   #选择SGD,学习率取0.001
Step4:开始训练

代码如下:

#开始训练
EPOCH = 8   #迭代次数
for epoch in range(EPOCH):
    sum_loss = 0
    #数据读取
    for i,data in enumerate(train_loader):
        inputs,labels = data
        inputs, labels = inputs.to(device), labels.to(device)   #有GPU则将数据置入GPU加速
 
        # 梯度清零
        optimizer.zero_grad()
 
        # 传递损失 + 更新参数
        output = net(inputs)
        loss = loss_fuc(output,labels)
        loss.backward()
        optimizer.step()
 
        # 每训练100个batch打印一次平均loss
        sum_loss += loss.item()
        if i % 100 == 99:
            print('[Epoch:%d, batch:%d] train loss: %.03f' % (epoch + 1, i + 1, sum_loss / 100))
            sum_loss = 0.0
 
    correct = 0
    total = 0
 
    for data in test_loader:
        test_inputs, labels = data
        test_inputs, labels = test_inputs.to(device), labels.to(device)
        outputs_test = net(test_inputs)
        _, predicted = torch.max(outputs_test.data, 1)  #输出得分最高的类
        total += labels.size(0) #统计50个batch 图片的总个数
        correct += (predicted == labels).sum()  #统计50个batch 正确分类的个数
 
    print('第{}个epoch的识别准确率为:{}%'.format (epoch + 1, 100*correct.item()/total))

#模型保存
torch.save(net.state_dict(),'D:\\Desktop\\ckpt.mdl') 

#模型加载
#net.load_state_dict(torch.load('ckpt.mdl'))

运行结果:
在这里插入图片描述

Step5:当然,也可以设置loss曲线

加入代码:

loss_list = []
......
# 打印损失值变化曲线
import matplotlib.pyplot as plt
plt.plot(loss_list)
plt.title('traning loss')
plt.xlabel('epochs')
plt.ylabel('loss')
plt.show()

结果:
在这里插入图片描述

关于详细代码,链接在这里:
https://download.csdn.net/download/didi_ya/12805831

需要的自取。

如果觉得有帮助,记得点个赞哟~

  • 40
    点赞
  • 259
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
好的,以下是使用PyTorch框架实现MNIST数据集分类的示例代码,其中使用了经典的LeNet-5卷积神经网络结构: ```python import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms # 定义LeNet-5卷积神经网络结构 class LeNet5(nn.Module): def __init__(self): super(LeNet5, self).__init__() self.conv1 = nn.Conv2d(1, 6, kernel_size=5) self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) self.conv2 = nn.Conv2d(6, 16, kernel_size=5) self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2) self.fc1 = nn.Linear(16*5*5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = 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*5*5) x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x) return x # 定义数据预处理 transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) # 加载MNIST数据集 trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=2) testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False, num_workers=2) # 定义损失函数和优化器 net = LeNet5() criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 开始训练 for epoch in range(10): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: # 每100个batch输出一次损失 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) running_loss = 0.0 print('Finished Training') # 在测试集上测试模型准确率 correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(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: %d %%' % ( 100 * correct / total)) ``` 在上面的示例代码中,我们首先定义了LeNet-5卷积神经网络结构,然后使用PyTorch提供的`torchvision`模块加载MNIST数据集,并进行数据预处理。接着,我们定义了损失函数和优化器,并开始训练模型。最后,在测试集上测试模型准确率。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wendy_ya

您的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值