机器学习笔记(5)--基于Matlab的底层全解析数据网络识别minist手写数字

神经网络

数据来源

采用手写数字识别作为例子进行讲解

THE MNIST DATABASE of handwritten digits 数据集下载地址为MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

在该数据集下有4个文件可获取(采用二进制格式存储,若需要单独的图片需要解码代码,后面会叙述)分别为训练图片、训练标签、测试图片和测试标签(也可直接使用下方链接下载),图片为28X28像素

http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz training set images (9912422 bytes)

http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz training set labels (28881 bytes)

http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz test set images (1648877 bytes)

http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz test set labels (4542 bytes)

训练集共60000份图片,测试集有10000份图片,测试集中的前5000份来自于原始的NIST训练数据集,后5000份来自于原始的NIST测试集。

数据解析

下面为各个数据集的数据存储模式,若要解析出单独的图片和标签便需要了解他的数据格式。

数据格式

TRAINING SET LABEL FILE (train-labels-idx1-ubyte):
[offset] [type]     [value]     [description]`
`0000   32 bit integer 0x00000801(2049) magic number (MSB first)`
`0004   32 bit integer 60000      number of items`
`0008   unsigned byte  ??        label`
`0009   unsigned byte  ??        label`
`........`
`xxxx   unsigned byte  ??        label
标签值为 0 到 9.
TRAINING SET IMAGE FILE (train-images-idx3-ubyte):
[offset] [type]     [value]     [description]`
`0000   32 bit integer 0x00000803(2051) magic number`
`0004   32 bit integer 60000      number of images`
`0008   32 bit integer 28        number of rows`
`0012   32 bit integer 28        number of columns`
`0016   unsigned byte  ??        pixel`
`0017   unsigned byte  ??        pixel`
`........`
`xxxx   unsigned byte  ??        pixel

训练集有60000张图片 ,28X28像素,像素按行组织,像素数据从第16个字节开始。像素值为 0 到 255。0 表示背景(白色),255 表示前景(黑色)。

TEST SET LABEL FILE (t10k-labels-idx1-ubyte):
[offset] [type]     [value]     [description]`
`0000   32 bit integer 0x00000801(2049) magic number (MSB first)`
`0004   32 bit integer 10000      number of items`
`0008   unsigned byte  ??        label`
`0009   unsigned byte  ??        label`
`........`
`xxxx   unsigned byte  ??        label

标签值为 0 to 9.

TEST SET IMAGE FILE (t10k-images-idx3-ubyte):
[offset] [type]     [value]     [description]`
`0000   32 bit integer 0x00000803(2051) magic number`
`0004   32 bit integer 10000      number of images`
`0008   32 bit integer 28        number of rows`
`0012   32 bit integer 28        number of columns`
`0016   unsigned byte  ??        pixel`
`0017   unsigned byte  ??        pixel`
`........`
`xxxx   unsigned byte  ??        pixel

测试集有10000张图片 ,28X28像素,像素按行组织,像素数据从第16个字节开始。像素值为 0 到 255。0 表示背景(白色),255 表示前景(黑色)。

数据解析代码

训练图片解析
%数据读入
clear all;
clc;
%读取训练图片数据文件
[FileName,PathName] = uigetfile('*.*','选择测试图片数据文件train-images.idx3-ubyte');
TrainFile = fullfile(PathName,FileName);
fid = fopen(TrainFile,'r'); %fopen()是最核心的函数,导入文件,‘r’代表读入
a = fread(fid,16,'uint8'); %这里需要说明的是,包的前十六位是说明信息,从上面提到的那个网页可以看到具体那一位代表什么意义。所以a变量提取出这些信息,并记录下来,方便后面的建立矩阵等动作。
MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
ImageRow = ((a(9)*256+a(10))*256+a(11))*256+a(12);
ImageCol = ((a(13)*256+a(14))*256+a(15))*256+a(16);
%从上面提到的网页可以理解这四句
if ((MagicNum~=2051)||(ImageNum~=60000))
    error('不是 MNIST train-images.idx3-ubyte 文件!');
    fclose(fid);   
    return;   
end %排除选择错误的文件。
savedirectory = uigetdir('','选择测试图片路径:');
h_w = waitbar(0,'请稍候,处理中>>');
for i=1:ImageNum
    b = fread(fid,ImageRow*ImageCol,'uint8');   %fread()也是核心的函数之一,b记录下了一副图的数据串。注意这里还是个串,是看不出任何端倪的。
    c = reshape(b,[ImageRow ImageCol]); %亮点来了,reshape重新构成矩阵,终于把串转化过来了。众所周知图片就是矩阵,这里reshape出来的灰度矩阵就是该手写数字的矩阵了。
    d = c'; %转置一下,因为c的数字是横着的。。。
    e = 255-d; %根据灰度理论,0是黑色,255是白色,为了弄成白底黑字就加入了e
    e = uint8(e);
    savepath = fullfile(savedirectory,['TrainImage_' num2str(i) '.bmp']);
    imwrite(e,savepath,'bmp'); %最后用imwrite写出图片
    waitbar(i/ImageNum);
end
fclose(fid);
close(h_w);
训练标签解析
%数据读入
clear all;
clc;
%读取训练图片数据文件
[FileName,PathName] = uigetfile('*.*','选择训练图片标签数据文件train-labels.idx1-ubyte');
TrainFile = fullfile(PathName,FileName);
fid = fopen(TrainFile,'r'); %fopen()是最核心的函数,导入文件,‘r’代表读入
a = fread(fid,8,'uint8'); %这里需要说明的是,包的前十六位是说明信息,从上面提到的那个网页可以看到具体那一位代表什么意义。所以a变量提取出这些信息,并记录下来,方便后面的建立矩阵等动作。
MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ItemNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
%从上面提到的网页可以理解这四句
if ((MagicNum~=2049)||(ItemNum~=60000))
    error('不是 MNIST train-labels.idx1-ubyte 文件!');
    fclose(fid);   
    return;   
end %排除选择错误的文件。
h_w = waitbar(0,'请稍候,处理中>>');
for i=1:ItemNum
    TrainLabels(i) = fread(fid,1,'uint8');   %fread()也是核心的函数之一,b记录下了一副图的数据串。注意这里还是个串,是看不出任何端倪的。
    waitbar(i/ItemNum);
end
save TrainLabels
fclose(fid);
close(h_w);
测试图片解析
%数据读入
clear all;
clc;
%读取训练图片数据文件
[FileName,PathName] = uigetfile('*.*','选择测试图片数据文件t10k-images.idx3-ubyte');
TrainFile = fullfile(PathName,FileName);
fid = fopen(TrainFile,'r'); %fopen()是最核心的函数,导入文件,‘r’代表读入
a = fread(fid,16,'uint8'); %这里需要说明的是,包的前十六位是说明信息,从上面提到的那个网页可以看到具体那一位代表什么意义。所以a变量提取出这些信息,并记录下来,方便后面的建立矩阵等动作。
MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
ImageRow = ((a(9)*256+a(10))*256+a(11))*256+a(12);
ImageCol = ((a(13)*256+a(14))*256+a(15))*256+a(16);
%从上面提到的网页可以理解这四句
if ((MagicNum~=2051)||(ImageNum~=10000))
    error('不是 MNIST t10k-images.idx3-ubyte 文件!');
    fclose(fid);   
    return;   
end %排除选择错误的文件。
savedirectory = uigetdir('','选择测试图片路径:');
h_w = waitbar(0,'请稍候,处理中>>');
for i=1:ImageNum
    b = fread(fid,ImageRow*ImageCol,'uint8');   %fread()也是核心的函数之一,b记录下了一副图的数据串。注意这里还是个串,是看不出任何端倪的。
    c = reshape(b,[ImageRow ImageCol]); %亮点来了,reshape重新构成矩阵,终于把串转化过来了。众所周知图片就是矩阵,这里reshape出来的灰度矩阵就是该手写数字的矩阵了。
    d = c'; %转置一下,因为c的数字是横着的。。。
    e = 255-d; %根据灰度理论,0是黑色,255是白色,为了弄成白底黑字就加入了e
    e = uint8(e);
    savepath = fullfile(savedirectory,['TestImage_' num2str(i) '.bmp']);
    imwrite(e,savepath,'bmp'); %最后用imwrite写出图片
    waitbar(i/ImageNum);
end
fclose(fid);
close(h_w);
测试标签解析
%数据读入
clear all;
clc;
%读取训练图片数据文件
[FileName,PathName] = uigetfile('*.*','选择测试图片标签数据文件t10k-labels.idx1-ubyte');
TrainFile = fullfile(PathName,FileName);
fid = fopen(TrainFile,'r'); %fopen()是最核心的函数,导入文件,‘r’代表读入
a = fread(fid,8,'uint8'); %这里需要说明的是,包的前十六位是说明信息,从上面提到的那个网页可以看到具体那一位代表什么意义。所以a变量提取出这些信息,并记录下来,方便后面的建立矩阵等动作。
MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ItemNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
%从上面提到的网页可以理解这四句
if ((MagicNum~=2049)||(ItemNum~=10000))
    error('不是 MNIST t10k-labels.idx1-ubyte 文件!');
    fclose(fid);   
    return;   
end %排除选择错误的文件。
h_w = waitbar(0,'请稍候,处理中>>');
for i=1:ItemNum
    TestLabels(i) = fread(fid,1,'uint8');
    waitbar(i/ItemNum);
end
save TestLabels
fclose(fid);
close(h_w);

以上完成了数据解析

神经网络解析

前向传播

先以一个简单的神经网络开始

在这里插入图片描述

X = [ x 1 x 2 x 3 x 4 ] X=\begin{bmatrix} x_1 & x_2 & x_3 & x_4 \end{bmatrix} X=[x1x2x3x4]

A 1 = [ a 1 1 a 2 1 a 3 1 a 4 1 ] = X T = [ x 1 x 2 x 3 x 4 ] A1=\left[\begin{matrix} a_1^1 \\ a_2^1 \\a_3^1 \\a_4^1 \end{matrix}\right]=X^T=\left[\begin{matrix} x_1 \\ x_2 \\x_3 \\x_4 \end{matrix}\right] A1= a11a21a31a41 =XT= x1x2x3x4

Θ 1 = [ θ 11 1 θ 12 1 θ 13 1 θ 14 1 θ 21 1 θ 22 1 θ 23 1 θ 24 1 θ 31 1 θ 32 1 θ 33 1 θ 34 1 θ 41 1 θ 42 1 θ 43 1 θ 44 1 ] \Theta_1 = \left[ \begin{matrix} \theta_{11}^1 & \theta_{12}^1 & \theta_{13}^1 & \theta_{14}^1 \\ \theta_{21}^1 & \theta_{22}^1 & \theta_{23}^1 & \theta_{24}^1 \\ \theta_{31}^1 & \theta_{32}^1 & \theta_{33}^1 & \theta_{34}^1 \\ \theta_{41}^1 & \theta_{42}^1 & \theta_{43}^1 & \theta_{44}^1 \\ \end{matrix} \right] Θ1= θ111θ211θ311θ411θ121θ221θ321θ421θ131θ231θ331θ431θ141θ241θ341θ441

Z 2 = Θ 1 × A 1 = [ z 1 2 z 2 2 z 3 2 z 4 2 ] Z_2=\Theta_1 \times A_1 =\left[\begin{matrix} z_1^2 \\ z_2^2 \\z_3^2 \\z_4^2 \end{matrix}\right] Z2=Θ1×A1= z12z22z32z42

激活函数
s i g m o i d ( z ) = 1 1 + e − z sigmoid(z) = \frac{1}{1+e^{-z}} sigmoid(z)=1+ez1

A 2 = s i g m o i d ( Z 2 ) = [ s i g m o i d ( z 1 2 ) s i g m o i d ( z 2 2 ) s i g m o i d ( z 3 2 ) s i g m o i d ( z 4 2 ) ] = [ a 1 2 a 2 2 a 3 2 a 4 2 ] A_2 = sigmoid(Z_2)=\left[\begin{matrix} sigmoid(z_1^2) \\sigmoid(z_2^2)\\sigmoid(z_3^2) \\sigmoid(z_4^2) \end{matrix}\right] =\left[\begin{matrix} a_1^2 \\a_2^2\\a_3^2 \\a_4^2 \end{matrix}\right] A2=sigmoid(Z2)= sigmoid(z12)sigmoid(z22)sigmoid(z32)sigmoid(z42) = a12a22a32a42

Θ 2 = [ θ 11 2 θ 12 2 θ 13 2 θ 14 2 θ 21 2 θ 22 2 θ 23 2 θ 24 2 ] \Theta_2 = \left[ \begin{matrix} \theta_{11}^2 & \theta_{12}^2 & \theta_{13}^2 & \theta_{14}^2 \\ \theta_{21}^2 & \theta_{22}^2 & \theta_{23}^2 & \theta_{24}^2 \end{matrix} \right] Θ2=[θ112θ212θ122θ222θ132θ232θ142θ242]

Z 3 = Θ 2 × A 2 = [ z 1 3 z 2 3 ] Z_3=\Theta_2 \times A_2 =\left[\begin{matrix} z_1^3 \\ z_2^3 \end{matrix}\right] Z3=Θ2×A2=[z13z23]

A 3 = s i g m o i d ( Z 3 ) = [ s i g m o i d ( z 1 3 ) s i g m o i d ( z 2 3 ) ] = [ a 1 3 a 2 3 ] A_3 = sigmoid(Z_3)=\left[\begin{matrix} sigmoid(z_1^3) \\sigmoid(z_2^3) \end{matrix}\right] =\left[\begin{matrix} a_1^3 \\a_2^3 \end{matrix}\right] A3=sigmoid(Z3)=[sigmoid(z13)sigmoid(z23)]=[a13a23]

反向传播

在这里插入图片描述

标签值 Y Y Y
Y = [ y 1 y 2 ] Y=\left[ \begin{matrix} y_{1}\\y_{2} \end{matrix} \right ]\\ Y=[y1y2]
激活函数求导
S i g m o i d D e r i v a t i v e ( a ) = a ⋅ ( 1 − a ) SigmoidDerivative(a) = a \cdot (1-a) SigmoidDerivative(a)=a(1a)

Δ 3 = [ δ 11 3 δ 12 3 ] = ( A 3 − Y ) ⋅ S i g m o i d D e r i v a t i v e ( A 3 ) = [ a 1 3 − y 1 a 2 3 − y 2 ] ⋅ S i g m o i d D e r i v a t i v e ( [ a 1 3 a 2 3 ] ) \Delta_3=\left[ \begin{matrix} \delta^3_{11}\\\delta^3_{12} \end{matrix} \right ]=(A_3 - Y) \cdot SigmoidDerivative(A_3)= \left[ \begin{matrix} a_1^3-y_1\\a_2^3-y_2 \end{matrix} \right ] \cdot SigmoidDerivative(\left[\begin{matrix} a_1^3 \\a_2^3 \end{matrix}\right]) Δ3=[δ113δ123]=(A3Y)SigmoidDerivative(A3)=[a13y1a23y2]SigmoidDerivative([a13a23])

Δ 2 = Θ 2 T × Δ 2 ⋅ S i g m o i d D e r i v a t i v e ( A 2 ) \Delta_2 = \Theta_2^T \times \Delta_2 \cdot SigmoidDerivative(A_2) Δ2=Θ2T×Δ2SigmoidDerivative(A2)

D 1 = 1 l e n g t h ( A 1 ) ⋅ ( Δ 2 ⋅ A 1 T ) D 2 = 1 l e n g t h ( A 2 ) ⋅ ( Δ 3 ⋅ A 2 T ) D_1 = \frac {1}{length(A1)} \cdot (\Delta_2 \cdot A_1^T)\\ D_2 = \frac {1}{length(A2)} \cdot (\Delta_3 \cdot A_2^T) D1=length(A1)1(Δ2A1T)D2=length(A2)1(Δ3A2T)
更新权重
Θ 1 = Θ 1 − α D 2 Θ 2 = Θ 2 − α D 2 \Theta_1 = \Theta_1 -\alpha D_2\\ \Theta_2 = \Theta_2 -\alpha D_2 Θ1=Θ1αD2Θ2=Θ2αD2

训练代码

%加载训练数据标签
clear;
close all;
load('TrainLabels.mat');
%激发函数
sigmoid = @(z) 1./(1.+exp(-z));
sigmoidDerivative = @(a) a.*(1.-a);
imgLoad = @(i)imread(strcat(['TrainImage(',num2str(i),').bmp']));
% costFunction = @(delta)
%构建神经网络
%随机产生权重矩阵
Theta1=rand(200,784)*2-1;
Theta2=rand(200,200)*2-1;
Theta3=rand(200,200)*2-1;
Theta4=rand(10,200)*2-1;
b1=rand(200,1)*2-1;
b2=rand(200,1)*2-1;
b3=rand(200,1)*2-1;
b4=rand(10,1)*2-1;

m=784;
ImageNum=60000;
h0 = waitbar(0,'Please wait,Iterating...');
h1 = waitbar(1,'Please wait,Processing...');
alpha=1;
lambda=0.01;
for i=1:ImageNum
%图片数据加载
X = imgLoad(i);
subplot(1,4,1);
imshow(X);
A1=double(reshape(X./255,784,1));
%获取标签
y=zeros(10,1);
y(TrainLabels(i)+1)=1;

%循环迭代
j=1;
J=zeros(1,1);
for n=1:1000
%计算A2
A2=sigmoid(Theta1*A1+b1);

%计算A3
A3=sigmoid(Theta2*A2+b2);
%计算A4
A4=sigmoid(Theta3*A3+b3);
%计算A5
A5=sigmoid(Theta4*A4+b4);
%计算delta5
delta5=(A5-y).*sigmoidDerivative(A5);
%计算delta4
delta4=Theta4'*delta5.*sigmoidDerivative(A4);
%计算delta3
delta3=Theta3'*delta4.*sigmoidDerivative(A3);
%计算delta2
delta2=Theta2'*delta3.*sigmoidDerivative(A2);

%计算代价函数偏导数
D1=1./784.*(delta2.*A1');%+lambda*Theta1;
D2=1./200.*(delta3.*A2');%+lambda*Theta2;
D3=1./200.*(delta4.*A3');%+lambda*Theta3;
D4=1./200.*(delta5.*A4');%+lambda*Theta4;
%更新权重
Theta1 = Theta1 - alpha*D1;
Theta2 = Theta2 - alpha*D2;
Theta3 = Theta3 - alpha*D3;
Theta4 = Theta4 - alpha*D4;
%更新偏差
b1=b1-alpha/784*delta2;
b2=b2-alpha/200*delta3;
b3=b3-alpha/200*delta4;
b4=b4-alpha/200*delta5;
%计算方差
j=1/2/10*sum((y-A5).^2);
J(n)=j;
waitbar(n/200,h0);
end
numResult = find(A5==max(A5))-1;
J_Last(i)=J(n);
subplot(1,4,2);
plot(1:n,J);
subplot(1,4,3);
plot(J_Last);
subplot(1,4,4);
%plot3(i2,j2,Theta2,'*');
waitbar(i/ImageNum,h1);
end
 save Theta Theta1 Theta2 Theta3 Theta4 b1 b2 b3 b4;%训练完成后将权重和偏差保存到Theta.mat %中用于测试使用

训练过程中,迭代次数1000次,第一个坐标区为单张图片迭代过程中预测前向过程中误差的方差变化,第二个坐标区为整个训练过程中总体代价函数的变化

在这里插入图片描述

测试代码

clear;
close all;
load('.\matlab_code\Theta.mat');
load('TestLabels.mat');
imgLoad = @(i)imread(strcat(['TestImage_',num2str(i),'.bmp']));
sigmoid = @(z) 1./(1.+exp(-z));
ImageNum=600;
for n=1:ImageNum
X = imgLoad(n);
imshow(X);
A1=double(reshape(X./255,784,1));
A2=sigmoid(Theta1*A1+b1);
A3=sigmoid(Theta2*A2+b2);
A4=sigmoid(Theta3*A3+b3);
A5=sigmoid(Theta4*A4+b4);
numResult(n) = find(A5==max(A5))-1;
end
y=TestLabels(1:n);
h=numResult-y;
num=0;
for i=1:n
    if(h(i)==0)
        h(i)=1;
        num=num+1;
    else
        h(i)=0;
    end
end
h=reshape(h,24,25);
imshow(h);
rate=num/ImageNum

测试中

在这里插入图片描述

测试600张测试集图片,正确率83.17%

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值