(神经网络)MNIST手写体数字识别MATLAB完整代码

这篇具有很好参考价值的文章主要介绍了(神经网络)MNIST手写体数字识别MATLAB完整代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、摘要         

        在此次实验中,笔者针对 MNIST 数据集,利用卷积神经网络进行训练与测试,提
出了一系列的改进方法,并对这些改进的方法进行了逐一验证,比较了改进方法与浅层
神经网络的优劣。
        首先,笔者对实验中所用的 MNIST 数据集进行了简单的介绍;接着,介绍了数据
处理的方法,实验中采用的数据处理方法主要为将图片对应的像素矩阵进行归一化;然
后,利用单隐藏层卷积神经网络模型进行了训练与测试,并进一步引入 ROI 机制对输入
图像的尺寸进行调整,加快了训练速度;最后,笔者又基于动量算法、小批量算法以及
双隐藏层神经网络模型提出了改进方法,并进行了模型的训练与对比测试。
        在进入正文之前,先对模型训练与测试的基本思路进行讲解,在后续的改进实验中,
也是基于该框架进行调整。图 1 为使用 SGD 算法训练网络的流程图。笔者先从官网上下
载了 MNIST 数据集,接着对训练集、测试集中的图片进行标签,为了方便网络训练,需
要对图片进行归一化处理。然后,就进入网络结构的设计,先考虑单隐藏层神经网络结
构,笔者在特征提取网络中设计了一层卷积层和一层池化层,在分类网络中也只使用一
层隐藏层。最后,训练网络之后对测试集上分类错误的图片进行记录保存。
(神经网络)MNIST手写体数字识别MATLAB完整代码,matlab,开发语言

二、数据集介绍

           MNIST 数据集是手写数字图像集,MNIST 是机器学习领域最有名的数据集之一,

被应用于从简单的实验到发表研究论文等各种场合。 MNIST 数据集是由 0 9 的数字
图像构成,训练图像有 6 万张,测试图像有 1 万张,这些图像可以用于学习和推理。
MNIST 数据集标准与技术研究所 , National Institute of Standards and Technology (NIST)
训练集 (training set) 由来自 250 个不同人手写的数字构成 , 其中 50% 是高中学生 , 50%
自人口普查局 (the Census Bureau) 的工作人员。测试集 (test set) 也是同样比例的手写数
字数据。
        MNIST 数据集的一般使用方法是,先用训练图像进行学习,再用学习到的模型对
测试图像进行正确的分类。

三、数据预处理

        文章来源地址https://www.toymoban.com/news/detail-773856.html

在进行训练之前,需要对图像进行简单处理,采取的方法为将图片数据进行归一化。
MATLAB 中,读取的每一张图片都会以灰度值矩阵的形式存在,在本次训练中,输入
图像的大小是 28*28 的,那么每张图片就对应 784 个灰度值,每个灰度值都介于 0-255
之间。需要将这些值调整到 [0,1] 之间,具体的操作是直接除以 255 。但为了进一步提高
模型的泛化能力和训练速度,再对归一化的数值进行四舍五入操作,这样一来,每个图
片的数据就只储存在 0 1 之中。数据归一化的好处如下:
1 加速训练: 神经网络的训练通常依赖于梯度下降等优化算法,这些算法对输入
数据的范围和分布敏感。通过将数据归一化到一个较小的范围(通常是 [0, 1] [-1, 1] ),
可以提高训练的稳定性和收敛速度。这有助于避免梯度消失或爆炸等训练中的问题。
2 梯度下降的收敛性: 归一化有助于确保不同特征的权重更新在相似的尺度上,
使训练更容易收敛。如果特征具有不同的尺度,可能需要更小的学习率来训练模型,或
者可能需要更多的训练时间。
3 防止模型过拟合: 归一化可以帮助模型更好地泛化到新的数据。过大的输入值
范围可能导致模型过拟合,因为模型可能过于依赖特定训练数据的细节。
4 让模型更易于调试: 在归一化后,输入数据的分布更容易可视化和理解,因此
在调试和分析模型时更加方便。

四、网络介绍

4 所示为基于但隐藏层卷积神经网络的手写体数字识别模型,网络总共可以分为
特征提取网络和分类网络两部分。在特征提取网络中,主要由一层卷积层和一层池化层
组成。在卷积层中,使用 ReLU 激活函数处理卷积之后得到的矩阵。在分类网络中,由
一层输入层、一层隐藏层以及一层输出层组成。输入层由 2000 个节点组成;隐藏层由
100 个节点组成,使用的激活函数为 ReLU 激活函数;输出层由 10 个节点组成,对应手
写体数字的 10 个类别,使用的激活函数为 Softmax 激活函数。
(神经网络)MNIST手写体数字识别MATLAB完整代码,matlab,开发语言

五、相关代码

%sigmoid函数
function r = sigmoid(x)
    r = 1 ./ (1 + exp(-x));
end
function r = softmax(x)
    S = sum(exp(x));
    r = zeros(length(x), 1);
    for i = 1:length(x)
        r(i) = exp(x(i)) / S;
    end
end
% 反向传播代码
function [W1, W2, W3, error, accuracy] = BP(W1, W2, W3, alpha, D, imageData, accuracy)
    %卷积
    img_conv1 = zeros(20, 20, 20);
    for k = 1:20
        img_conv1(:, :, k) = filter2(W1(:, :, k), imageData, 'valid'); 
    end
    %ReLU激活
    img_act = max(0, img_conv1);
    %池化
    img_pool = (img_act(1:2:end, 1:2:end, :) + img_act(2:2:end, 2:2:end, :) +     
    img_act(1:2:end, 2:2:end, :) +img_act(2:2:end, 1:2:end, :)) / 4;
    %将img_pool转换成列向量(2000*1)
    img_input = reshape(img_pool, [], 1);
    %第一个隐层的输出
    v1 = W2 * img_input;
    y1 = max(0, v1);
    %输出层的输出
    v2 = W3 * y1;
    y2 = softmax(v2);
    %观察模型是否训练准确
    [value1, index1] = max(y2);
    [value2, index2] = max(D);
    if index1 == index2
        accuracy = accuracy + 1;
    end
    % 计算交叉熵函数
    error = sum(- D .* log(y2) - (1 - D) .* log(1 - y2)) / 10;
    %误差反向传播过程
    %计算输出层的delta
    e2 = D - y2;
    delta2 = e2;
    %计算第一层隐藏层的delta1
    e1 = W3' * delta2;
    delta1= (y1 > 0) .* e1;
    %计算输入层(reshape层)的e
    e = W2' * delta1;
    %将输入层的误差进行reshape,以便于误差进一步反向传播穿过池化层和卷积层
    E2 = reshape(e, size(img_pool));
    %将池化层的误差传播到卷积层
    E1 = zeros(size(img_act));
    E2_4 = E2 / 4;
    E1(1:2:end, 1:2:end, :) = E2_4;
    E1(1:2:end, 2:2:end, :) = E2_4;
    E1(2:2:end, 1:2:end, :) = E2_4;
    E1(2:2:end, 2:2:end, :) = E2_4;
    delta = (img_act > 0) .* E1;
    dW1 = zeros(9, 9, 20);
    for k = 1:20
        dW1(:, :, k) = alpha * (filter2(delta(:, :, k), imageData, 'valid'));
    end
    %更改权重
    W1 = W1 + dW1;
    W2 = W2 + alpha * delta1 * img_input';
    W3 = W3 + alpha * delta2 * y1';
end
%训练并测试
%第一个卷积层的权重
W1 = randn(9, 9, 20);
%学习率
alpha = 0.001;
%训练集文件夹路径
train_path = 'MNIST_train/';  
%第一个隐层的权重
W2 = (2 * rand(100, 2000) - 1) / 20;
%输出层的连接权重
W3 = (2 * rand(10, 100) - 1) / 10;
%设置迭代次数
n = 1;
%初始化样本标签数据(一共有60000张图片,所以需要保存60000个标签数据)
label = zeros(60000, 1);

%先对每个样本进行标记
for i = 0:9
    trainfolderpath = strcat(train_path, num2str(i)); 
    % 获取文件夹中的所有图像文件
    trainimageFiles = dir(fullfile(trainfolderpath, '*.jpg'));
    % 循环读取每个图像
    for j = 1:length(trainimageFiles)
        % 假设imageFiles(j).name包含文件名
        FileName = trainimageFiles(j).name;
        % 利用fileparts获得文件名,方便后续辨识每张图片的标签
        [~, name_number, ~] = fileparts(FileName);
        %通过解析文件名就可以获得图片的序号
        number = str2num(name_number);
        %给图片打上标签
        label(number) = i;
    end
end

%开始计时
tic;

%训练网络时用到的文件夹,在该文件夹下将所有类别的图片混合,可以提高训练效果
Path_mix = 'train_mix/';  
%每张图片的交叉熵
loss = zeros(60000, 1);
%平均交叉熵
loss_ave = zeros(60000, 1);
%训练集的准确率
acc_train = zeros(60000, 1);
accuracy = 0;
%开始训练,只训练一轮
for epochs = 1:n
    folderpath =  Path_mix;
    %获取文件夹中的所有图像文件
    imageFiles = dir(fullfile(folderpath, '*.jpg'));  % 可以更改文件扩展名以匹配你的图像格式
    % 循环读取每个图像
    for j = 1:length(imageFiles)
        % 构建完整的文件路径
        lab = label(j); 
        %设置目标输出
        D = zeros(10, 1);
        D(lab+1) = 1;
        %获取要读取的图片的地址
        imagePath = strcat(folderpath, num2str(j));
        imagePath = strcat(imagePath, '.jpg');
        %输出正在处理的图像和训练进度
        fprintf('模型训练的进度:%f%%\n', j/600);
        s = sprintf('正在训练的图片为:%s', imagePath);
        disp(s);
        % 使用 imread 读取图像
        imageData = imread(imagePath);
        %对图像进行归一化操作
        imageData = round(imageData / 255);
        [W1, W2, W3, error, accuracy] = BP(W1, W2, W3, alpha, D, imageData, accuracy);
        acc_train(j) = accuracy / j;
        loss(j) = error;
        loss_ave(j) = sum(loss(1:j)) / j;
    end
end
% 停止计时
elapsedTime = toc;
% 打印执行时间
fprintf('训练时长为:%.4f 秒\n', elapsedTime);
%训练结束的信号
disp('训练结束,正在进行测试...');
%测试集地址
testPath = 'MNIST_test/'; 
%记录测试集有多少张图片
image_numbers_test = 1;
%测试集上的准确率
acc = 0;
for i = 0:9
    %依次遍历MINIST_train(训练集)文件夹下的每一个子文件夹,每一个子文件夹中包含相同的数字
    test_path = strcat(testPath, num2str(i)); 
    % 获取文件夹中的所有图像文件
    testimageFiles = dir(fullfile(test_path, '*.jpg'));
    % 循环读取每个图像
    for j = 1:length(testimageFiles)
        %测试集中每张图片的路径
        imagePath = fullfile(test_path, testimageFiles(j).name);
        %读取图像
        imageData = imread(imagePath);
        %图片归一化操作
        imageData = round(imageData / 255);
        %卷积
        img_conv1 = zeros(20, 20, 20);
        for k = 1:20
            img_conv1(:, :, k) = filter2(W1(:, :, k), imageData, 'valid'); 
        end    
        %对卷积得到的图片进行ReLU激活
        img_act = max(0, img_conv1);    
        %平均池化(2*2)
        img_pool = (img_act(1:2:end, 1:2:end, :) + img_act(2:2:end, 2:2:end, :) + img_act(1:2:end, 2:2:end, :) +img_act(2:2:end, 1:2:end, :)) / 4;
        %将img_pool转换成列向量(2000*1)
        img_input = reshape(img_pool, [], 1);
        %第一个隐层的输出
        v1 = W2 * img_input;
        y1 = max(0, v1);
        %输出层的输出
        v2 = W3 * y1;
        y2 = softmax(v2);
        [~, index] = max(y2);
        %如果分类正确准确率就加1
        acc = acc + ((index-1) == i);
        image_numbers_test = image_numbers_test + 1;
    end
end
%画图观察模型训练效果
subplot(1, 2, 1);
plot(1:60000, loss_ave);
xlabel('训练的图片数');
ylabel('平均损失函数值');
title('平均交叉熵随训练的图片数量的变化');
subplot(1, 2, 2);
plot(1:60000, acc_train);
xlabel('训练的图片数');
ylabel('准确率');
title('准确率随训练的图片数量的变化');
fprintf('测试集的准确率为%f\n', acc/(image_numbers_test-1));

到了这里,关于(神经网络)MNIST手写体数字识别MATLAB完整代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Python机器学习】实验14 手写体卷积神经网络(PyTorch实现)

    LeNet-5是卷积神经网络模型的早期代表,它由LeCun在1998年提出。该模型采用顺序结构,主要包括7层(2个卷积层、2个池化层和3个全连接层),卷积层和池化层交替排列。以mnist手写数字分类为例构建一个LeNet-5模型。每个手写数字图片样本的宽与高均为28像素,样本标签值是0~

    2024年02月12日
    浏览(52)
  • 实战:基于卷积的MNIST手写体分类

    前面实现了基于多层感知机的MNIST手写体识别,本章将实现以卷积神经网络完成的MNIST手写体识别。 1.  数据的准备 在本例中,依旧使用MNIST数据集,对这个数据集的数据和标签介绍,前面的章节已详细说明过了,相对于前面章节直接对数据进行“折叠”处理,这里需要显式地

    2024年02月10日
    浏览(40)
  • 基于PyTorch的MNIST手写体分类实战

    第2章对MNIST数据做了介绍,描述了其构成方式及其数据的特征和标签的含义等。了解这些有助于编写合适的程序来对MNIST数据集进行分析和识别。本节将使用同样的数据集完成对其进行分类的任务。 3.1.1  数据图像的获取与标签的说明 MNIST数据集的详细介绍在第2章中已经完成

    2024年02月08日
    浏览(38)
  • 深度学习:使用卷积神经网络CNN实现MNIST手写数字识别

    本项目基于pytorch构建了一个深度学习神经网络,网络包含卷积层、池化层、全连接层,通过此网络实现对MINST数据集手写数字的识别,通过本项目代码,从原理上理解手写数字识别的全过程,包括反向传播,梯度下降等。 卷积神经网络是一种多层、前馈型神经网络。从功能上

    2024年02月13日
    浏览(46)
  • 卷积神经网络CNN原理+代码(pytorch实现MNIST集手写数字分类任务)

    前言 若将图像数据输入全连接层,可能会导致丧失一些位置信息 卷积神经网络将图像按照原有的空间结构保存,不会丧失位置信息。 卷积运算: 1.以单通道为例: 将将input中选中的部分与kernel进行数乘 : 以上图为例对应元素相乘结果为211,并将结果填入output矩阵的左上角

    2024年02月04日
    浏览(63)
  • 机器学习第一周:用卷积神经网络实现Mnist手写数字识别(付基础知识解释)

    MNIST 数据集是一个手写数字识别数据集,包含了 60000 张训练图像和 10000 张测试图像,每张图像都是 28x28 像素的灰度图像。 在这个代码中,我们首先使用了 numpy 库中的 np.random.seed() 方法来设置随机种子,以确保结果可重复。 然后,我们使用了 Keras 中的 mnist.load_data() 方法来

    2024年02月08日
    浏览(43)
  • 真的不能再详细了,2W字保姆级带你一步步用Pytorch搭建卷积神经网络实现MNIST手写数字识别

    目录 一、引言(环境)  二、正文 1. 代码基本情况介绍 2. MNIST数据集介绍         3. 代码输出结果介绍 数据集取样: 训练信息输出: 前三次训练成果以及预测: 八次训练的结果:  4. 代码拆解讲解 基本的参数设定 MNIST数据集下载、保存与加载 神经网络模型 训练前的准

    2023年04月20日
    浏览(38)
  • 在树莓派上实现numpy的LSTM长短期记忆神经网络做图像分类,加载pytorch的模型参数,推理mnist手写数字识别

    这几天又在玩树莓派,先是搞了个物联网,又在尝试在树莓派上搞一些简单的神经网络,这次搞得是LSTM识别mnist手写数字识别 训练代码在电脑上,cpu就能训练,很快的: 然后需要自己在dataset里导出一些图片:我保存在了mnist_pi文件夹下,“_”后面的是标签,主要是在pc端导出

    2024年02月07日
    浏览(43)
  • 在树莓派上实现numpy的conv2d卷积神经网络做图像分类,加载pytorch的模型参数,推理mnist手写数字识别,并使用多进程加速

    这几天又在玩树莓派,先是搞了个物联网,又在尝试在树莓派上搞一些简单的神经网络,这次搞得是卷积识别mnist手写数字识别 训练代码在电脑上,cpu就能训练,很快的: 然后需要自己在dataset里导出一些图片:我保存在了mnist_pi文件夹下,“_”后面的是标签,主要是在pc端导

    2024年02月07日
    浏览(35)
  • 深度学习(六):paddleOCR理解及识别手写体,手写公式,表格

    光学字符识别(Optical Character Recognition, OCR),ORC是指对包含文本资料的图像文件进行分析识别处理,获取文字及版面信息的技术,检测图像中的文本资料,并且识别出文本的内容。 那么有哪些应用场景呢? 其实我们日常生活中处处都有ocr的影子,比如在疫情期间身份证识别

    2024年02月05日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包