10 行代码,实现手写数字识别

简介:

识别手写的阿拉伯数字,对于人类来说十分简单,但是对于程序来说还是有些复杂的。
1

不过随着机器学习技术的普及,使用10几行代码,实现一个能够识别手写数字的程序,并不是一件难事。这是因为有太多的机器学习模型可以拿来直接用,比如tensorflow、caffe,在python下都有现成的安装包,写一个识别数字的程序,10几行代码足够了。

然而我想做的,是不借助任何第三方的库,从零开始,完全自己实现一个这样的程序。之所以这么做,是因为自己动手实现,才能深入了解机器学习的原理。

1 模型实现
1.1 原理
熟悉神经网络回归算法的,可以略过这一节了。

学习了一些基本概念,决定使用回归算法。首先下载了著名的MNIST数据集,这个数据集有60000个训练样本,和10000个测试样本。每个数字图片都是2828的灰度图片,所以输入可以认为是一个2828的矩阵,也可以认为是一个28*28=784个像素值。

这里定义一个模型用于判断一个图片数字,每个模型包括每个输入的权重,加一个截距,最后再做个归一。模型的表达式:

Out5= sigmoid(X0W0+ X1W1+……X783*W783+bias)

X0到X783是784个输入,W0到W783是784个权重,bias是一个常量。sigmoid函数可以将较大范围的数挤压到(0,1)区间内,也就是归一。

例如我们用这一组权重和bias来判断数字5,期望当图片是5时输出是1,当不是5时输出是0。然后训练的过程就是根据每个样本的输入,计算Out5的值和正确值(0或1)的差距,然后根据这个差距,调整权重和bias。转换一下公式,就是在努力使得(Out5-正确值)接近于0,即所谓损失最小。

同理,10个数字就要有10套模型,每个判断不同的数字。训练好以后,一个图片来了,用这10套模型进行计算,哪个模型计算的结果更接近于1,就认为这个图片是哪个数字。

1.2 训练
按照上面的思路,使用集算器的SPL(结构化处理语言)来编码实现:
2
不用再找了,训练模型的所有代码都在这里了,没有用到任何第三方库,下面解析一下:

A1,用游标导入MNIST训练样本,这个是我转换过的格式,可以被集算器直接访问;

A2,定义变量:输入x,权重wei,训练速度v,等;

A3,B3,初始化10组模型(每组是784个权重+1个bias);

A4,循环取5万个样本进行训练,10模型同时训练;

B4,取出来label,即这个图片是几;

B5,计算正确的10个输出,保存到变量y;

B6,取出来这个图片的28*28个像素点作为输入,C6把每个输入除以255,这是为了归一化;

B7,计算X0W0+ X1W1+……X783*W783+bias

B8,计算sigmoid(B7)

B9,计算B8的偏导,或者叫梯度;

B10,C10,根据B9的值,循环调整10个模型的参数;

A11,训练完毕,把模型保存到文件。

1.3 测试
测试一下这个模型的成功率吧,用 SPL 写了一个测试程序:
3
运行测试,正确率达到了91.1%,我对这个结果是很满意的,毕竟这只是一个单层模型,我用TensorFlow的单层模型得到的正确率也是91%多一点。下面解析一下代码:

A1,导入模型文件;

A2,把模型提取到变量里;

A3,计数器初始化(用于计算成功率);

A4,导入MNIST测试样本,这个文件格式是我转换过的;

A5,循环取1万个样本进行测试;

   B5,取出来label;

   B6,清空输入;

B7,取出来这个图片的28*28个像素点作为输入,每个输入除以255,这是为了归一化;

B8,计算X0W0+ X1W1+……X783*W783+bias

B9,计算sigmoid(B7)

B10,得到最大值,即最可能的那个数字;

B11,判断正确测计数器加一;

A12,A13,测试结束,关闭文件,输出正确率。

1.4 优化
这里要说的优化并不是继续提高正确率,而是提升训练的速度。想提高正确率的同学可以尝试一下这几个手段:

1.       加一个卷积层;

2.       学习速度不要用固定值,而是随着训练次数递减;

3.       权重的初始值不要使用全零,使用正态分布;

 

我认为单纯追求正确率的意义不大,因为MNIST数据集有些图片本身就有问题,即使人工也不一定能知道写的是数字几。我用集算器显示了几张出错的图片,都是书写十分不规范的,下面这个图片很难看出来是2。
4

下面说重点,要提高训练速度,可以使用并行或集群。使用SPL语言实现并行很简单,只要使用fork关键字,把上面的代码稍加处理就可以了。
5
使用了并行之后,训练的时间减少差不多一半,而代码并没有做太多修改。

2 为什么是 SPL 语言?
使用SPL语言在初期可能会有点不适应,用得多了会觉得越来越方便:

1.       支持集合运算,比如例子里用到的784个输入和784个权重的乘法,直接写一个**就可以了,如果使用Java或者C,还要自己实现。

2.       数据的输入输出很方便,可以方便地对文件读写。

3.       调试太方便了,所有变量都直观可见,这一点比python要好用。

4.       可以单步计算,有了改动不用从头重来,Java和C做不到这一点,python虽然可以但也不方便,集算器只要点中相应格执行就可以了。

5.       实现并行和集群很方便,不需要太多的开发工作量。

6.       支持调用和被调用。集算器可以调用第三方java库,Java也可以调用集算器的代码,例如上面的代码就可以被Java调用,实现一个自动填验证码的功能。

这样的编程语言,用在数学计算上,实在是最合适不过了。

154037421300096d9.rar

相关文章
|
应用服务中间件 Shell Docker
Docker Hub 公有镜像在国内拉取加速配置
通过加速,国内用户能够快速访问最流行的 Docker 镜像。 仓库 registry.docker-cn.com 包含流行的公有镜像。私有镜像仍需要从 Docker Hub 镜像库中拉取。 以下命令直接从镜像加速地址进行拉取: $ docker pull registry.
35894 0
|
4月前
|
机器学习/深度学习 人工智能 程序员
Reflexion:让AI智能体学会反思的神奇技术
想象一下AI智能体能像人类一样从错误中学习,Reflexion技术让智能体不再需要重新训练就能自我改进。本文通过一个智能体助手小R的成长故事,带你轻松理解这个改变智能体学习方式的创新技术。
355 2
|
6月前
|
人工智能 JavaScript 前端开发
分享开源库:AI驱动的JavaScript反编译,针对混淆和压缩的代码
这是一个智能JavaScript反混淆与代码分析工具,通过AST转换和AI深度分析,自动还原变量名、识别依赖库、生成可视化控制流图,并支持多格式导出,提升代码理解与审计效率。访问 [jsunpack.tech](https://www.jsunpack.tech/) 即可在线体验。
1347 0
|
4月前
|
人工智能 自然语言处理 测试技术
AI测试平台的用例管理实践:写得清晰,管得高效,执行更智能
在测试过程中,用例分散、步骤模糊、回归测试效率低等问题常困扰团队。霍格沃兹测试开发学社推出的AI测试平台,打通“用例编写—集中管理—智能执行”全流程,提升测试效率与覆盖率。平台支持标准化用例编写、统一管理操作及智能执行,助力测试团队高效协作,释放更多精力优化测试策略。目前平台已开放内测,欢迎试用体验!
|
6月前
|
机器学习/深度学习 人工智能 编解码
AI-Compass LLM合集-多模态模块:30+前沿大模型技术生态,涵盖GPT-4V、Gemini Vision等国际领先与通义千问VL等国产优秀模型
AI-Compass LLM合集-多模态模块:30+前沿大模型技术生态,涵盖GPT-4V、Gemini Vision等国际领先与通义千问VL等国产优秀模型
AI-Compass LLM合集-多模态模块:30+前沿大模型技术生态,涵盖GPT-4V、Gemini Vision等国际领先与通义千问VL等国产优秀模型
|
自然语言处理 前端开发 安全
当被问到你使用过iframe吗?有哪些优点和缺点?
当被问到你使用过iframe吗?有哪些优点和缺点?
691 0
|
存储 C语言
【C语言程序设计——循环程序设计】利用数列的累加和求 sinx(头歌实践教学平台习题)【合集】
项的累加和,一般会使用循环结构,在每次循环中计算出当前项的值(可能基于通项公式或者递推关系),然后累加到一个用于存储累加和的变量中。在C语言中推导数列中的某一项,通常需要依据数列给定的通项公式或者前后项之间的递推关系来实现。例如,对于一个简单的等差数列,其通项公式为。的级数,其每一项之间存在特定的递推关系(后项的分子是其前项的分子乘上。,计算sinx的值,直到最后一项的绝对值小于。为项数),就可以通过代码来计算出指定项的值。对于更复杂的数列,像题目中涉及的用于近似计算。开始你的任务吧,祝你成功!
323 6
|
存储 机器人
01 ROS基本概念及命令
这篇文章介绍了ROS(机器人操作系统)的基本概念,如节点、ROS Master、参数、通信机制(话题和消息、服务)、功能包、命名空间和命名重映射,以及一些基本的ROS命令行工具的使用,例如rosnode、rostopic、rossrv、rosservice、rosparam和roslaunch。
592 0
|
Linux
【专栏】Linux系统中"cd"命令的使用技巧,包括基本用法
【4月更文挑战第28天】本文介绍了Linux系统中"cd"命令的使用技巧,包括基本用法(如切换到指定目录)、利用"."和".."、"~"符号,以及绝对路径和相对路径切换。还分享了高级技巧,如使用通配符、结合其他命令和在脚本中的应用。通过学习这些技巧,可提升工作效率,如快速切换到项目目录或最近使用的目录。
864 0
|
开发框架 前端开发 机器人
从模型到前端,你应该知道的LLM生态系统指南
LLM在在2023年发展的风生水起,一个围绕LLM的庞大生态系统正在形成,本文通过介绍这个生态系统的核心组成部分,来详细整理LLM的发展。
1068 2