CNN卷积神经网络手写数字识别实例及代码详解

本文详细介绍了使用Matlab实现的CNN手写数字识别,包括数据预处理、网络结构、训练过程和测试。通过解决在训练过程中遇到的错误,如expand函数应用、sigm和flipall函数定义问题,实现了对MNIST数据集的高效识别。文章还提供了完整的代码流程,包括cnnsetup、cnntrain、cnnff和cnnbp等关键函数,最终达到约0.01%的测试错误率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文的代码来自githup的Deep Learningtoolbox,是用Matlab实现的。感谢该toolbox的作者付出和分享。

我在应该该代码进行训练时,出现一些报错,如expand函数应用不对,sigm函数和flipall函数未定义等问题,对这些问题进行了修正,完成网络训练和验证。

本文mnist_uint8.mat的获取可以参照我的另一篇博客:MNIST数据库处理--matlab生成mnist_uint8.mat   http://blog.csdn.net/fuwenyan/article/details/53954615


本文作者:非文艺小燕儿,VivienFu,

欢迎大家转载适用,请注明出处。http://blog.csdn.net/fuwenyan?viewmode=contents http://blog.csdn.net/fuwenyan?viewmode=contents



学习该代码需要一定的CNN理论基础。

目的:实现手写数字识别

数据集:MNIST数据集,60000张训练图像,10000张测试图像,每张图像size为28*28

网络层级结构概述:5层神经网络

Input layer: 输入数据为原始训练图像

Conv1:6个5*5的卷积核,步长Stride为1

Pooling1:卷积核size为2*2,步长Stride为2

Conv2:12个5*5的卷积核,步长Stride为1

Pooling2:卷积核size为2*2,步长Stride为2

Output layer:输出为10维向量

网络层级结构示意图如下:

 

 

 

 

 

代码流程概述

(1)获取训练数据和测试数据;

(2)定义网络层级结构;

(3)初始设置网络参数(权重W,偏向b)cnnsetup(cnn, train_x, train_y)

4)训练超参数opts定义(学习率,batchsizeepoch

5)网络训练之前向运算cnnff(net, batch_x)

6)网络训练之反向传播cnnbp(net, batch_y)

7)网络训练之参数更新cnnapplygrads(net, opts)

8)重复(5)(6)(7),直至满足epoch

9)网络测试cnntest(cnn, test_x, test_y)

 

 

 详细代码及我的注释

 

cnnexamples.m

clear all; close all; clc;    
load mnist_uint8;  
  
train_x = double(reshape(train_x',28,28,60000))/255;  %数据归一化至[0 1]之间
test_x = double(reshape(test_x',28,28,10000))/255;  %数据归一化至[0 1]之间
train_y = double(train_y');  
test_y = double(test_y');  
 
%% ex1   
%will run 1 epoch in about 200 second and get around 11% error.   
%With 100 epochs you'll get around 1.2% error  
  
cnn.layers = {  
    struct('type', 'i') %input layer  
    struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer,6个5*5的卷积核,可以得到6个outputmaps  
    struct('type', 's', 'scale', 2) %sub sampling layer  ,2*2的下采样卷积核
    struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer ,12个5*5的卷积核,可以得到12个outputmaps  


    struct('type', 's', 'scale', 2) %subsampling layer    ,2*2的下采样卷积核
};  %定义了一个5层神经网络,还有一个输出层,并未在这里定义。
  
cnn = cnnsetup(cnn, train_x, train_y);  %通过该函数,对网络初始权重矩阵和偏向进行初始化
  
opts.alpha = 1;  % 学习率
 
opts.batchsize = 50; %每batchsize张图像一起训练一轮,调整一次权值。  
% 训练次数,用同样的样本集。我训练的时候:  
% 1的时候 11.41% error  
% 5的时候 4.2% error  
% 10的时候 2.73% error  
opts.numepochs = 10;  %每个epoch内,对所有训练数据进行训练,更新(训练图像个数/batchsize)次网络参数
  
cnn = cnntrain(cnn,

卷积神经网络(Convolutional Neural Networks,CNN)是一种深度学习神经网络,广泛应用于图像识别、语音识别、自然语言处理等领域。在本文中,我们将使用PyTorch实现一个简单的CNN,并对其进行详细的解释和应用实例。 ## CNN的基本结构 CNN由多个卷积层、池化层和全连接层组成。其中,卷积层和池化层是CNN最重要的部分。 ### 卷积层 卷积层是CNN中最基本的层,它通过将输入数据与一组卷积核进行卷积操作,提取出数据特征。卷积层的输入为一个三维张量,维度分别为(通道数,高度,宽度),卷积核也是一个三维张量,维度分别为(输入通道数,卷积核高度,卷积核宽度),卷积层的输出为一个三维张量,维度同输入。 在PyTorch中,我们可以通过使用`nn.Conv2d`类来创建卷积层,例如: ``` import torch.nn as nn # 创建一个输入通道数为3,输出通道数为16,卷积核大小为3x3的卷积层 conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3) ``` ### 池化层 池化层是CNN中用于降低特征图尺寸的一种方式。它通过对特征图进行下采样,减少特征图尺寸,同时保留重要的特征信息。常用的池化方式有最大池化和平均池化。 在PyTorch中,我们可以通过使用`nn.MaxPool2d`和`nn.AvgPool2d`类来创建最大池化层和平均池化层,例如: ``` # 创建一个2x2的最大池化层 max_pool_layer = nn.MaxPool2d(kernel_size=2) # 创建一个2x2的平均池化层 avg_pool_layer = nn.AvgPool2d(kernel_size=2) ``` ### 全连接层 全连接层是CNN中最后一层,它将卷积层和池化层提取出的特征图转换为一个一维向量,并连接到一个或多个全连接层进行分类或回归。在PyTorch中,我们可以使用`nn.Linear`类来创建全连接层,例如: ``` # 创建一个输入维度为256,输出维度为10的全连接层 fc_layer = nn.Linear(in_features=256, out_features=10) ``` ## CNN的应用实例 接下来,我们将使用PyTorch实现一个简单的CNN,并对其进行应用实例,以MNIST数据集为例,进行手写数字识别。 首先,我们需要导入必要的库: ``` import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms ``` 然后,我们需要定义CNN的结构。在本例中,我们定义一个包含两个卷积层和两个最大池化层的CNN,以及一个全连接层进行分类。其中,每个卷积层的卷积核大小为3x3,池化层的池化大小为2x2。 ``` class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3) self.pool1 = nn.MaxPool2d(kernel_size=2) self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3) self.pool2 = nn.MaxPool2d(kernel_size=2) self.fc1 = nn.Linear(in_features=32 * 5 * 5, out_features=120) self.fc2 = nn.Linear(in_features=120, out_features=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, 32 * 5 * 5) x = torch.relu(self.fc1(x)) x = self.fc2(x) return x ``` 接下来,我们需要对训练数据进行预处理。在本例中,我们对数据进行了归一化,并将其转换为张量。 ``` transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) 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) ``` 然后,我们定义损失函数和优化器。 ``` 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: print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) running_loss = 0.0 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)) ``` 经过10次迭代的训练,最终得到的测试集准确率约为98%。 ## 总结 本文介绍了CNN的基本结构和应用实例,并使用PyTorch实现了一个简单的CNN进行手写数字识别CNN是深度学习中非常重要的一种神经网络,广泛应用于图像识别、语音识别、自然语言处理等领域,希望本文对您有所帮助。
评论 87
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值