#神经网络#

l利用LeNet模型进行手写字体的图像识别

深度神经网络网络对于计算图像技术有非常好的作用,其中LeNet为比较早期同时也比较简单的模型,对于小型数据处理有着很好的作用,本文利用搭建LeNet很好的实现手写数字图像数据的识别 模型如下:
模型如下
给出代码:

#### 导入数据包
import torch
import torch.nn as nn
import torchvision
import matplotlib.pyplot as plt
import torch.utils.data as Data
from torchvision.datasets import MNIST
from torchvision import transforms
import torch.optim as optim
from tqdm import tqdm_notebook as tqdm
import numpy as np
import matplotlib.pyplot as plt


## 加载数据包
train_mnist = MNIST(
    download= True,
    root = "./data/MNIST",
    transform=transforms.ToTensor(),
    train = True  ###表明为训练数据集
)
test_mnist = MNIST(
    download= True,
    root = "./data/MNIST",
    transform=transforms.ToTensor(),
    train = False  ###表明为测试数据集
)

##创建加载器
trainDataLoader = Data.DataLoader(
     dataset = train_mnist,
     batch_size = 48,
     shuffle = True,
     num_workers = 2  #### 线程数 zaiwindows系统下不起作用
)
testDataLoader = Data.DataLoader(
     dataset = test_mnist,
     batch_size = 48,
     shuffle = True,
     num_workers = 2  #### 线程数 zaiwindows系统下不起作用
)

## 创建网络模型
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet,self).__init__()
        self.conv = nn.Sequential(     
            ### 输入图像为28*28的灰度图
            nn.Conv2d(in_channels=1,out_channels=6,kernel_size=(5,5),stride = 1, padding=0),   ## 6*24*24
            nn.ReLU(True),
            nn.MaxPool2d(stride=2, kernel_size=2),  # 6*12*12
            nn.Conv2d(in_channels=6,out_channels=16,kernel_size=(5,5), stride=1, padding=0), ## 16*8*8
            nn.ReLU(True),
            nn.MaxPool2d(stride=2, kernel_size=2), #16*4*4
        )
        self.linear = nn.Sequential(
            nn.Linear(16*4*4,120),
            nn.ReLU(True),
            nn.Linear(120,84),
            nn.ReLU(True),
            nn.Linear(84,10)  # 0-9总共10类数字  
        )
    def forward(self,x):
        conv = self.conv(x)
        x = conv.view(conv.size(0),-1)
        output = self.linear(x)
        return output

可以将模型打印出来:
在这里插入图片描述

## 创建优化器
optimizer = torch.optim.Adam(net.parameters(),lr=0.001) # 使用Adam优化下降算法
loss_fn = nn.CrossEntropyLoss() ##设置交叉熵损失函数
### 开始训练
from tqdm import tqdm
train_loss_all = []
train_acc_all = []
test_loss_all = []
test_acc_all= []
epochs = 30
for epoch in range(epochs):
    print("{}/{}".format(epoch+1, epochs))
    net.train()
    loss = 0
    acc = 0
    try:
        with tqdm(enumerate(trainDataLoader), total=len(trainDataLoader)) as t:
            for step, (b_x,b_y) in t:## b_x.shape =[48,1,28,28]
                optimizer.zero_grad() ##梯度清零
                out = net(b_x)  #out.shape =[48,10]
                pre = torch.argmax(out,1)
                los = loss_fn(out, b_y)
                loss+= los.item() * b_x.size(0)  ##记录损失值
                acc += torch.sum(pre == b_y.data)
                los.backward()## 反向传播
                optimizer.step()  #更新权重
    except KeyboardInterrupt:
        t.close()
        raise
    t.close()
    train_loss_all.append((loss /len(train_mnist)))
    train_acc_all.append(acc.double() / len(train_mnist))
    net.eval()
    loss = 0
    acc = 0
    try:
        with tqdm(enumerate(testDataLoader),total = len(testDataLoader)) as t:## b_x.shape =[48,1,28,28]
            for step, (b_x,b_y) in t:
                optimizer.zero_grad() ##梯度清零
                out = net(b_x)  #out.shape =[48,10]
                pre = torch.argmax(out,1)
                los = loss_fn(out, b_y)
                loss+= los.item() * b_x.size(0)  ##记录损失值
                acc += torch.sum(pre == b_y.data)
    except KeyboardInterrupt:
        t.close()
        raise
    t.close()
    test_loss_all.append(loss /len(test_mnist))
    test_acc_all.append(acc.double() / len(test_mnist))

最后利用Matplotlib绘图工具绘出训练过程

plt.figure('train',figsize=(20,10))
plt.subplot(2,2,1)
plt.plot(train_loss_all)
plt.title("Train Loss")
plt.subplot(2,2,2)
plt.plot(train_acc_all)
plt.title("Train ACC")
plt.subplot(2,2,3)
plt.plot(test_loss_all)
plt.title("test Loss")
plt.subplot(2,2,4)
plt.plot(test_acc_all)
plt.title("test ACC")
plt.show()

在这里插入图片描述
可以看出由于训练过程比较理想,测试效果比较嘈杂,猜测是因为LeNet层数过低,训练数据也较少,导致模型的过度拟合,但好在整体的正确率还算满意( ^ - ^)

torch.save(net.state_dict(),"./data/LeNet.pth")  ### 保存训练完成的模型信息
model = LeNet()
model_state_dict = torch.load("./data/LeNet.pth") ### 加载模型
model.load_state_dict(model_state_dict)

然后我们随机挑选照片进行识别**

#### 进行测试
test = MNIST(
    download=False,
    train = False,
    transform=transforms.ToTensor(),
    root = "./data/MNIST"
)
mark = np.random.randint(0,500,size=(40))  ###随机抽取40张照片
####展示40张图
imageList = []
plt.figure("Image show")
for j in range(len(mark)):
    imageList.append(test.test_data[mark[j]])
    plt.subplot(8,5,j+1)
    plt.imshow(imageList[-1].numpy())
    plt.title(test.test_labels[mark[j]].numpy())
    plt.subplots_adjust(wspace=0.2,hspace=1)
    plt.axis("off")
plt.show() ## 展示图像

请添加图片描述

### 进行图像识别
label=[]
for num,data in enumerate(imageList):
    data = data.type(torch.float32)  ### 记得要转换数据类型,原始数据为uint8 需转换为float32类
    pre = model(data.unsqueeze(0).unsqueeze(0))
    label.append(torch.argmax(pre,1).numpy()[0])
print(label)

输出结果

虽然训练过程缓慢但是在预测时结果是秒出的并且通过与之前的图像比对可以发现预测的结果还是相当不错的^ - ^

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值