利⽤LeNet-5实现MNIST⼿写数字识别(Pytorch)西电-计算机视觉-实验三
⼀、实验要求
⼆、实验分析
1.LeNet⽹络结构如下:
2.MNIST数据集简介:
(1)数据集包括60000个⽤于训练的⽰例和10000个⽤于测试的⽰例;
(2)数据集包括0-9共10类⼿写数字图⽚,每张图⽚都做了尺⼨归⼀化,都是28*28⼤⼩。
3.⼿写字体识别流程:
(1)定义超参数 ;
(2)构建transforms(主要是对图像做变换);
(3)下载、加载数据集MNIST;
(4)构建⽹络模型;
(5)定义优化器;
(6)定义训练⽅法;
(7)定义测试⽅法;
(8)训练模型并输出预测结果。
三、代码实现
#!/usr/bin/env python
# @Date: 2021/12/10
# @Desc: ⼿写字体识别
import torch
as nn
functional as F
functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# --------------step1: 定义超参数-------------------------
DEVICE = torch.device("cuda"if torch.cuda.is_available()else"cpu")# 是否⽤GPU
EPOCHS =10# 数据集的训练次数
BATCH_SIZE =16# 每批处理的数据 16/32/64/128
# -------------step2: 构建transform(对图像做处理)---------
transform = transforms.Compose([
transforms.ToTensor(),# 将图⽚转成成tensor
transforms.Normalize((0.1307,),(0.3081,))# 标准化 => x' = (x-µ)/σ
])
# -------------step3: 下载并加载数据集------------------
# 下载数据集
train_set = datasets.MNIST("data_sets", train=True, download=True, transform=transform)
test_set = datasets.MNIST("data_sets", train=False, download=True, transform=transform)
# 加载数据集
train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_set, batch_size=BATCH_SIZE, shuffle=True)
# -------------step4: 构建⽹络模型--------------------
class LeNet(nn.Module):
"""
A neural network with:
2 Conbolutions
3 Full connnection
"""
def__init__(self):
super().__init__()
self.fc1 = nn.Linear(16*5*5,120)# 16*5*5:输⼊通道, 120:输出通道
self.fc2 = nn.Linear(120,84)# 输⼊通道:120, 输出通道:84
self.fc3 = nn.Linear(84,10)# 输⼊通道:84, 输出通道:10
def forward(self, x):
手写字体
x = v1(x)# 输⼊:batch*1*28*28 输出:batch*6*28*28 (28+2*2-5+1=28)
x = F.relu(x)# 激活层输出:batch**6*28*28
x = F.max_pool2d(x,2,2)# 池化层/下采样输⼊:batch*6*28*28 输出:batch*6*14*14
x = v2(x)# 输⼊:batch*6*14*14 输出:batch*16*10*10  (14+2*0-5+1=10)
x = F.relu(x)# 激活层输出:batch*16*10*10
x = F.max_pool2d(x,2,2)# 池化层/下采样输⼊:batch*16*10*10 输出:16*5*5
x = x.view(x.size(0),-1)# 拉平(-1指⾃动计算维度) 16*5*5
x = self.fc1(x)# 输⼊:batch*16*5*5  输出: batch*120
x = F.relu(x)# 激活层输出:batch*120
x = self.fc2(x)# 输⼊:batch*120  输出:batch*84
x = F.relu(x)# 激活层输出:batch*84
x = self.fc3(x)# 输⼊:batch*84  输出:batch*10
output = F.softmax(x, dim=1)# 计算分类后每个数字的概率值
return output
# ----------------step:5 定义优化器--------------------------
model = LeNet().to(DEVICE)
optimizer = optim.Adam(model.parameters())
# ----------------step6: 定义训练⽅法-----------------------
def train_model(my_model, device, trains_loader, optimizers, epoches):
# 模型训练
ain()
for batch_idx,(data, target)in enumerate(trains_loader):
# 将data和target部署到DEVICE上去
data, target = (device), (device)
# 将梯度初始化为0
<_grad()
# 训练所得的结果
output = my_model(data)
# 计算交叉熵损失
loss = F.cross_entropy(output, target)
# 反向传播
loss.backward()
# 更新参数
optimizers.step()
# 每100batch_size打印⼀次log
if batch_idx %1000==0:
print("Training Epoch:{} \t Loss:{:.5f}".format(epoches, loss.item()))
# ----------------step7: 定义测试⽅法------------------------
def test_model(my_model, device, test_loder):
my_model.eval()# 模型验证
correct =0.0# 正确率
test_loss =0.0# 测试损失
_grad():# 测试时不计算梯度,也不进⾏反向传播
for data, target in test_loder:
# 将data和target部署到device上
data, target = (device), (device)
# 测试所得的结果
output = my_model(data)
# 计算交叉熵损失
test_loss += F.cross_entropy(output, target).item()
# 到概率最⼤的下标
predict = output.argmax(dim=1)
# predict = torch.max(output, dim=1)
correct += predict.eq(target.view_as(predict)).sum().item()# 累计正确的值# 计算平均损失
avg_loss = test_loss /len(test_loder.dataset)
# 计算准确率
correct_ratio =100* correct /len(test_loder.dataset)
print("Average_loss in test:{:.5f}\t Accuracy:{:.5f}\n".format(
avg_loss, correct_ratio
))
# --------------step8: 训练模型----------------------------
for epoch in range(1, EPOCHS+1):
train_model(model, DEVICE, train_loader, optimizer, epoch)
test_model(model, DEVICE, test_loader)
四、实验结果(部分)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。