matlab手写神经网络实现识别手写数字
实验说明
一直想自己写一个神经网络来实现手写数字的识别,而不是套用别人的框架。恰巧前几天,有幸从同学那拿到5000张已经贴好标签的手写数字图片,于是我就尝试用matlab写一个网络。
实验数据:5000张手写数字图片(.jpg),图片命名为1.jpg,2.jpg…5000.jpg。还有一个放着标签的excel文件。
数据处理:前4000张作为训练样本,后1000张作为测试样本。
图片处理:用matlab的imread()函数读取图片的灰度值矩阵(28,28),然后把每张图片的灰度值矩阵reshape为(28*28,1),然后把前4000张图片的灰度值矩阵合并为x_train,把后1000张图片的灰度值矩阵合并为x_test。
神经网络设计
网络层设计:一层隐藏层,一层输出层
输入层:一张图片的灰度值矩阵reshape后的784个数,也就是x_train中的某一列
输出层:(10,1)的列向量,其中列向量中最大的数所在的索引就是预测的数字
激励函数:sigmoid函数(公式)
更新法则:后向传播算法(参考)
一点说明:这里的训练我分别用了普通梯度下降法和mini_batch(batch size 为10)梯度下降法来实现
测试:用了两种方式表示正确率,一是统计预测正确的个数,而是利用matlab的plotconfusion函数
网络实现
全部实现包括5个函数(gedata.m / layerout.m / mytrain.m / mytrain_mini.m / test.m)和一个main.m文件。
读取数据(getdata.m)
function[x_train,y_train,x_test,y_test]=getdata()
%把图片变成像素矩阵
%path :图片路径
% x_train:训练样本像素矩阵(784,4000)
%y_train:训练样本标签(10,4000)
%x_test:测试样本像素矩阵(784,1000)
%y_test:测试样本标签(10,1000)
% photopath = './photo/';
% snames=dir([photopath '*' '.jpg'])%get all filenames in photopath
% l = length(snames)
%
% %get x_ data
% x_train = [];
% x_test = [];
%
% for i=1:4000
% iname=[photopath snames(i).name] %the path of jpg
% x = imread(iname); % the shape of x is (28,28)
% x = reshape(x,784,1); %reshape x to (784,1)
% x_train = [x_train,x];
% end
%
% for k=4001:5000
% kname=[photopath snames(k).name]; %the path of jpg
% x = imread(kname); %the shape of x is (28,28)
% x = reshape(x,784,1); %reshape x to (784,1)
% x_test = [x_test,x];
% end
x_train=[];
for i=1:4000
x=im2double(imread(strcat(num2str(i),'.jpg')));
x=reshape(x,784,1);
x_train=[x_train,x];
end
x_test =[];
for k=4001:5000
x=im2double(imread(strcat(num2str(k),'.jpg')));
x=reshape(x,784,1);
x_test=[x_test,x];
end
data=xlsread('label.xlsx');
y_train=data(:,1:4000);
y_test = data(:,4001:5000);
x_train;
y_train;
x_test;
y_test;
end
这里踩了一个坑。我本来读取图片,是按目录来读取的,然后训练出来的效果一直不好。一度怀疑自己的更新函数写错了,改了很久,才发现按目录读取的图片顺序是错误的!按目录读取的图片并不是按1,2,3…这样读的,而是按下面的顺序读取的,这样就和label对不上了!!!
layerout函数
function [y] = layerout(w,b,x)
%output function
y = w*x + b;
n = length(y);
for i =1:n
y(i)=1.0/(1+exp(-y(i)));
end
y;
end
训练一(mytrain.m)
function[w,b,w_h,b_h]=mytrain(x_train,y_train)
%train function:设置一个隐藏层,784-->隐藏层神经元个数-->10
%x_train:训练样本的像素数据
%y_train:训练样本的标签
%w:输出层权重
%b:输出层偏置
%w_h:隐藏层权重
%b_h:隐藏层偏置
%step:循环步数
step=input('迭代步数:');
a=input('学习因子:');
in = 784; %输入神经元个数
hid = input('隐藏层神经元个数:');%隐藏层神经元个数
out = 10; %输出层神经元个数
o =1;
w = randn(out,hid);
b = randn(out,1);
w_h =randn(hid,in);
b_h = randn(hid,1);
for i=0:step
%打乱训练样本
r=randperm(4000);
x_train = x_train(:,r);
y_train = y_train(:,r);
for j=1:4000
x = x_train(:,j);
y = y_train(:,j);
hid_put = layerout(w_h,b_h,x);
out_put = layerout(w,b,hid_put);
%更新公式的实现
o_update = (y-out_put).*out_put.*(1-out_put);
h_update = ((w')*o_update).*hid_put.*(1-hid_put);
outw_update = a*(o_update*(hid_put'));
outb_update = a*o_update;
hidw_update = a*(h_update*(x'));
hidb_update = a*h_update;
w = w + outw_update;
b = b+ outb_update;
w_h = w_h +hidw_update;
b_h =b_h +hidb_update;
end
end
end
训练二(mytrain_mini.m)
function[w,b,w_h,b_h]=mytrain_mini(x_train,y_train)
%train function:设置一个隐藏层,784-->隐藏层神经元个数-->10
%x_train:训练样本的像素数据
%y_train:训练样本的标签
%w:输出层权重
%b:输出层偏置
%w_h:隐藏层权重
%b_h:隐藏层偏置
%step:循环步数
step=ipout('迭代步数:');
a=input('学习因子:');
in = 784; %输入神经元个数
hid = input('隐藏层神经元个数:');%隐藏层神经元个数
out = 10; %输出层神经元个数
o =1;
w = randn(out,hid);
b = randn(out,1);
w_h =randn(hid,in);
b_h = randn(hid,1);
for i=0:step
%打乱训练样本
r=randperm(4000);
x_train = x_train(:,r);
y_train = y_train(:,r);
%mini_batch
for jj=0:399
%取batch为10 更新取10次的平均值
for j=jj*10+1:(jj+1)*10
x = x_train(:,j);
y = y_train(:,j);
hid_put = layerout(w_h,b_h,x);
out_put = layerout(w,b,hid_put);
%更新公式的实现
o_update = (y-out_put).*out_put.*(1-out_put);
h_update = ((w')*o_update).*hid_put.*(1-hid_put);
if j==1
outw_update = (double(a)/10)*(o_update*(hid_put'));
outb_update = (double(a)/10)*o_update;
hidw_update = (double(a)/10)*(h_update*(x'));
hidb_update = (double(a)/10)*h_update;
end
if j~=1
outw_update = outw_update + (double(a)/10)*(o_update*(hid_put'));
outb_update = outb_update -(double(a)/10)*o_update;
hidw_update = hidw_update + (double(a)/10)*(h_update*(x'));
hidb_update = hidb_update -(double(a)/10)*h_update;
end
end
w = w + outw_update;
b = b+ outb_update;
w_h = w_h +hidw_update;
b_h =b_h +hidb_update;
end
end
end
测试(mytest.m)
function[]= mytest(x_test,y_test,w,b,w_h,b_h)
%x_test:测试样本的像素数据
%y_test:测试样本的标签
%w:输出层权重
%b:输出层偏置
%w_h:隐藏层权重
%b_h:隐藏层偏置
test = zeros(10,1000);
for k=1:1000
x = x_test(:,k);
hid = layerout(w_h,b_h,x);
test(:,k)=layerout(w,b,hid);
%正确率表示方式一:输出正确个数
[t,t_index]=max(test);
[y,y_index]=max(y_test);
sum = 0;
for p=1:length(t_index)
if t_index(p)==y_index(p)
sum =sum+1;
end
end
end
fprintf('正确率: %d/1000\n',sum);
%正确率表示方式二:用plotconfusion函数
plotconfusion(y_test,test);
end
main.m
[x_train,y_train,x_test,y_test]=getdata();
%归一化
x_train = mapminmax(x_train,0,1);
x_test =mapminmax(x_test,0,1);
[w1,b1,w_h1,b_h1]=mytrain(x_train,y_train);
fprintf('mytrain正确率:\n');
mytest(x_test,y_test,w1,b1,w_h1,b_h1);
[w2,b2,w_h2,b_h2]=mytrain(x_train,y_train);
fprintf('mytrain_mini正确率:\n');
mytest(x_test,y_test,w2,b2,w_h2,b_h2);
实验结果
直接运行main.m,且两个训练方式都输入相同参数,得到结果如下:
下面是mini_batch的plotconfusion结果,mytrain的也差不多。其中绿色的为正确率:
直观感觉min_batch方式的训练会快一丢丢。由于这里数据不多,所以两者的差别看不大出来!
matlab手写神经网络实现识别手写数字的更多相关文章
- python手写神经网络实现识别手写数字
写在开头:这个实验和matlab手写神经网络实现识别手写数字一样. 实验说明 一直想自己写一个神经网络来实现手写数字的识别,而不是套用别人的框架.恰巧前几天,有幸从同学那拿到5000张已经贴好标签的手 ...
- 如何用卷积神经网络CNN识别手写数字集?
前几天用CNN识别手写数字集,后来看到kaggle上有一个比赛是识别手写数字集的,已经进行了一年多了,目前有1179个有效提交,最高的是100%,我做了一下,用keras做的,一开始用最简单的MLP, ...
- 使用神经网络来识别手写数字【译】(三)- 用Python代码实现
实现我们分类数字的网络 好,让我们使用随机梯度下降和 MNIST训练数据来写一个程序来学习怎样识别手写数字. 我们用Python (2.7) 来实现.只有 74 行代码!我们需要的第一个东西是 MNI ...
- Python实现神经网络算法识别手写数字集
最近忙里偷闲学习了一点机器学习的知识,看到神经网络算法时我和阿Kun便想到要将它用Python代码实现.我们用了两种不同的方法来编写它.这里只放出我的代码. MNIST数据集基于美国国家标准与技术研究 ...
- NN:神经网络实现识别手写的1~9的10个数字—Jason niu
import numpy as np from sklearn.datasets import load_digits from sklearn.metrics import confusion_ma ...
- C#中调用Matlab人工神经网络算法实现手写数字识别
手写数字识别实现 设计技术参数:通过由数字构成的图像,自动实现几个不同数字的识别,设计识别方法,有较高的识别率 关键字:二值化 投影 矩阵 目标定位 Matlab 手写数字图像识别简介: 手写 ...
- stanford coursera 机器学习编程作业 exercise 3(使用神经网络 识别手写的阿拉伯数字(0-9))
本作业使用神经网络(neural networks)识别手写的阿拉伯数字(0-9) 关于使用逻辑回归实现多分类问题:识别手写的阿拉伯数字(0-9),请参考:http://www.cnblogs.com ...
- Tensorflow搭建卷积神经网络识别手写英语字母
更新记录: 2018年2月5日 初始文章版本 近几天需要进行英语手写体识别,查阅了很多资料,但是大多数资料都是针对MNIST数据集的,并且主要识别手写数字.为了满足实际的英文手写识别需求,需要从训练集 ...
- Pytorch1.0入门实战一:LeNet神经网络实现 MNIST手写数字识别
记得第一次接触手写数字识别数据集还在学习TensorFlow,各种sess.run(),头都绕晕了.自从接触pytorch以来,一直想写点什么.曾经在2017年5月,Andrej Karpathy发表 ...
随机推荐
- 在MFC中改变控件的TAB顺序
在MFC界面中,控件的TAB顺序如果乱了,不合理,可能会使界面出现意料之外的显示. 例如,在用Spin Control来对Edit Control内的值进行增减时,如果Edit Control.Spi ...
- 编程之美 set 4 找到符合条件的数
题目 任意给定一个正整数 N, 求一个最小的正整数 M (M > 1), 使得 N*M 的十进制表达式中只有 0 和 1. 解法 1. 枚举0,1能够组成的数字, 可以组成一颗二叉树 然后由 B ...
- __file__
__file__ 是 python 的内置变量它的值等于文件名本身 [root@localhost ~]$ cat test.py #!/usr/bin/env python print(__file ...
- vue2.0非父子间进行通讯
在vue中,父组件向之组件通讯使用的是props,子组件向父组件通讯使用的是$emit+事件,那非父子间的通讯呢,在官方文档上只有寥寥数笔, 概念很模糊,这个空的vue实例应该放在哪里呢,光放文档并没 ...
- IOS7 新特性(针对同样讨厌更新后IOS7的开发者)
本文转载至 http://blog.csdn.net/hanbing861210/article/details/13614211 您还未登录!|登录|注册|帮助 首页 业界 移动 云计算 研发 论坛 ...
- 通过Servlet获取初始化参数
获取初始化参数在web.xml中配置Servlet时,可以配置一些初始化参数.而在Servlet中可以通过ServletConfig接口提供的方法来获取这些参数.(其实还可以通过ServletCont ...
- Eclipse之相关快捷键
Eclipse的编辑功能非常强大,掌握了Eclipse快捷键功能,能够大大提高开发效率.Eclipse中有如下一些和编辑相关的快捷键. 1.[ALT+/] 此快捷键为用户编辑的好帮手,能为用 ...
- Windows 下Hadoop的环境变量配置
一.安装JDK 1.下载路径:http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.安装到C:\Java\jdk1. ...
- centos7 edit hostname
1.临时修改主机名 hostname 主机名 重新连接shell,就可以,这种方式,只能修改临时的主机名,当重启机器后,主机名称又变回来了. 2.永久修改主机名 hostnamectl set-hos ...
- PMP十大知识领域整理
2018-7-28至2018-12-8历时4个多月,学写了PMP(拍马屁),感觉自己经历了,哇-唉-哦-嗯这四个阶段 刚开始觉得如遇圣经,被PMP的知识体系和老师的精彩课程深深震撼! 后来觉得很多东西 ...