用 C 写一个卷积神经网络

用 C 写一个卷积神经网络

深度学习领域最近发展很快,前一段时间读transformer论文《Attention Is All You Need》时,被一些神经网络和深度学习的概念搞得云里雾里,其实也根本没读懂。发现深度学习和传统的软件开发工程领域的差别挺大,光读论文可能不是一条很好了解深度学习的路径。所以我换了一个思路,从开源的项目入手,当时我研究了一段时间ggml项目代码(https://github.com/ggerganov/ggml) , 但实际的难度还是太过陡峭,主要的困难来源于数学推导和神经网络本身的特殊性。为了更全面的了解深度学习领域,最后我选择从基础的系统知识和书籍入手, 在阅读《Neural Networks and Deep Learning》这本书时,正好书中是通过设计一个手写识别程序来讲解神经网络,书中的例子是用python实现的,其中用了不少机器学习库,屏蔽了很多细节。于是萌生了自己用C写一个手写识别程序想法。

要用C不依赖第三方库写一个神经网络,需要从数学推导、网络模型和工程实现三个方面着手。项目本身没有什么价值,只是个人学习神经网络一个小玩具。
代码地址:https://github.com/yuanrongxi/simple-neural-network.git

神经网络涉及到的数学主要是线性代数和微积分求导,神经网络中的计算大部分是通过矩阵来完成的,首先需要弄明白标量、向量、张量等概念,掌握基本的矩阵运算,例如:空间转置、加减乘除、点积、reshape等,线性代数推荐看《Linear Algebra an Its Applications》,了解基本的向量空间和运算即可,如果想更直观可以看https://github.com/kf-liu/The-Art-of-Linear-Algebra-zh-CN/blob/main/The-Art-of-Linear-Algebra-zh-CN.pdf。积分求导主要是针对神经网络的反向传播,因为在神经网络推导时会用各种激活函数、softmax、卷积、pooling max、norm、flatten等数据操作,反向传播的过程的梯度下降算法需要对这些操作进行反向求导,所以需要清楚各个函数求导过程和代价函数概念,求导更详细的可以看B站上的《跟着李沐学AI》。

网络模型涉及到神经元和感知机的概念,通过编排神经元和激活函数构建网络分层,这个《Neural Networks and Deep Learning》中讲的比较清楚。网络模型可以理解成一堆weight(权重)/bais(偏置)加一堆的y = w.x+b的函数,但它分为正向传播(feedforward)和反向传播(backprop),正向传播就是推理,反向传播就是求权重和偏置参数。因为反向传播过程是一个利用梯度下降求导的过程,理解起来会有些困难,https://builtin.com/machine-learning/backpropagation-neural-network 对反向传播总结的非常好,通俗易懂。最后CNN模型选择参照了YanLeCun的LeNet(图-1),保留第一个卷积层,去掉了中间的卷积层。

LeNet

工程实现方面参照了NumPy的思路,将涉及到矩阵运算、激活函数、反向求导等做成一个独立的矩阵运算模块,这样做的好处是可以对专门的运算做优化,后面也方便加入GPU和CUDA做尝试。其次设计了一个run state机制,因为神经网络在推理和训练时,会有很多的中间数据,这些数据有些是临时的,有些是反向传播依赖的。为了避免频繁内存分配,在创建NN时将所有用到的对象统一分配,中间数据的矩阵flatten也是零拷贝。关于CPU并行计算上,采用了openmp进行简单的矩阵并行处理,加快训练速度,所以在矩阵运算代码中用了大量的数组下标寻址,没有使用更快的指针,后面CPU上可以尝试SSSE3/simd128采用多线程分任务优化。最后神经网络是难于调试的,往往逻辑流程运行正确,但训练出来的结果不达预期,和传统的系统工程差别大。在实现中采用了对所有数学代码进行单元测试,并逐一对照相对应的pytorch运行结果,确保数学上正确,这样做大大减轻了神经网络的调试难度。值得一提的是程序设计后期借助了cursor AI代码工具,效率是前期的4~5倍左右。

来看一下程序的效果,采用的是MNIST的数据集,6万张训练图片和1万张测试图片,训练和测试30轮,多层感知机网络的识别准确度在95%左右,CNN网络的准确度在98%左右。执行时间CNN是多层感知机的20倍左右。
在这里插入图片描述
整个程序的开发设计断断续续用了4个周末的时间,实现难度一般,过程有些简单的认识:

  1. 之所以Python成为深度学习界的标准开发语言,是因为它有很多强大的库和平台,像NumPy、Pytorch、Keras等,写一个神经网络可能只需几十行代码,简单高效,其他语言无可匹及。业界正在研究基于Python语言的编译技术,这可能是未来重要的方向之一。

  2. 深度学习与传统软件工程差别大,传统软件工程是建立的逻辑学层面的工程体系,只要逻辑性强从事软件开发不是难事,所以行业内人员参差不齐。AI和深度学习领域有自己独立的知识体系,而且更多是要依靠数学推导和模型设计,工程实现也更偏CPU/GPU相关的编程,逻辑在其中起的作用有限,AI这个领域不太可能出现从培训机构出来就业的人员。传统软降工程也走到一个阶段了,软件工程的需求正在从传统的工程领域快速迁移到深度学习领域。

  3. 深度学习的计算分为推理和训练,随着网络模型的发展计算将越来越重。训练的计算量会因为成本越来越高会出现更高效的芯片和分布式计算网络。而推理计算由于安全和场景需要,可能会越来越终端化,而且推理的计算量未来是训练计算量的万倍甚至更多,会催生出新的工程领域,例如ggml。

  4. AI发展很快,很多面向程序员的工具,像github copilot、cursor等,生成的代码未必可直接使用,但能够加快从概念到代码的过程,合理使用AI工具可以更快的进入陌生领域。

科技正在大力向前,它已不再朝我而来,我唯一能做的是调整自己的位置来跟上它的步伐。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/225183.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

19、XSS——HTTP协议安全

文章目录 一、Weak Session IDs(弱会话IDs)二、HTTP协议存在的安全问题三、HTTPS协议3.1 HTTP和HTTPS的区别3.2 SSL协议组成 一、Weak Session IDs(弱会话IDs) 当用户登录后,在服务器就会创建一个会话(Session),叫做会话控制&…

tomcat配置管理员And配置访问静态资源

配置管理员 打开 tomcat\conf\tomcat-users.xml <tomcat-users xmlns"http://tomcat.apache.org/xml"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://tomcat.apache.org/xml tomcat-users.xsd"version&qu…

openai 1.3.x 版本 openai.APITimeoutError: Request timed out. 解决

问题描述 openai 1.3.x 版本 请求出现 Request timed out File "E:\Python\Python312\Lib\site-packages\openai\_base_client.py", line 920, in _request return self._retry_request( ^^^^^^^^^^^^^^^^^^^^ File "E:\Python\Python312\L…

python爬虫零基础学习之简单流程示例

文章目录 爬虫基础爬虫流程常用库爬虫示例关于Python爬虫技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 爬虫基础 网络爬…

微信小程序动态加载图表[echart]

1.引入Echarts &#xff08;1&#xff09;将ec-canvas文件拷贝下来放到你自己的项目中&#xff1a; &#xff08;2&#xff09;在你需要使用Echarts的页面的json文件中引入Echarts "usingComponents": {"ec-canvas": "../utils/ec-canvas/ec-canva…

STM32——PWM介绍

STM32F103C8T6 PWM资源&#xff1a; 高级定时器&#xff08;TIM1&#xff09;&#xff1a;7路 通用定时器&#xff08;TIM2~TIM4&#xff09;&#xff1a;各4路 PWM输出模式&#xff1a; PWM模式1&#xff1a;在向上计数时&#xff0c;一旦 CNT < CCRx 时输出为有效电平&…

基于Eclipse+Mysql+Servlet开发的学生信息管理系统

基于EclipseMysqlServlet开发的学生信息管理系统 项目介绍&#x1f481;&#x1f3fb; 随着信息技术的不断发展&#xff0c;学校管理学生信息的方式也在不断改进。传统的手工管理方式已经无法满足现代学校对信息管理的需求&#xff0c;因此开发一套基于EclipseMysql的学生信息管…

C#基础学习--命名空间和程序集

引用其他程序集 编译器接受源代码文件并生成一个名为程序集的输出文件。 在许多项目中&#xff0c;会想使用来自其他程序集的类或类型。这些程序集可能来自BCL或第三方供应商&#xff0c;或者自己创建的。这些程序集称为类库&#xff0c;而且它们的程序集文件的名称通常以dll…

MySQL为何偏爱B+树索引

一、MySQL、B树概念 MySQL是一种关系型数据库&#xff0c;它使用SQL语言来操作数据。SQL语言可以实现对数据的增删改查等操作&#xff0c;但是如果数据量很大&#xff0c;那么这些操作的效率就会很低。为了提高效率&#xff0c;MySQL引入了索引的概念。 索引是一种数据结构&am…

Java TCP(一对一)聊天简易版

客户端 import java.io.*; import java.net.Socket; import java.util.Date; import javax.swing.*;public class MyClient {private JFrame jf;private JButton jBsend;private JTextArea jTAcontent;private JTextField jText;private JLabel JLcontent;private Date data;p…

Redis——某马点评day02——商铺缓存

什么是缓存 添加Redis缓存 添加商铺缓存 Controller层中 /*** 根据id查询商铺信息* param id 商铺id* return 商铺详情数据*/GetMapping("/{id}")public Result queryShopById(PathVariable("id") Long id) {return shopService.queryById(id);} Service…

构建socket的客户端和服务端

网络函数 WSAStartup socket bind listen accept connect send recv closesocket WSACleanup 为什么要用WSAStartup初始化&#xff1f; 本函数必须是应用程序或DLL调用的第一个Windows Sockets函数.它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows So…

文件加密软件——支持对任意类型文档加密保护

你是不是经历过这样的场景&#xff1a; 公司的文件随意外发 员工拿U盘随意拷贝文件 公司辛辛苦苦设计的图纸莫名其妙泄露了 标书里的数据不知道什么时候就被竞品公司知道了 …… 一系列的文件泄密事件&#xff0c;让企业主不寒而栗。遂千方百计、好似无头苍蝇似的在市面上…

postgreSql服务的window启动

CMD启动服务&#xff1a; D:\PostgreSQL\bin pg_ctl register -N PostgreSQL -D "D:\PostgreSQL\data # 登录 psql -U postgres # 验证输入 select 1; 拓展&#xff1a;删除服务 sc delete 服务名称 PostgreSQLUSER: postgresPWD: rootPORT: 5432动PostgreSQL服务器 3.1 打…

R语言手册30分钟上手

文章目录 1. 环境&安装1.1. rstudio保存工作空间 2. 创建数据集2.1. 数据集概念2.2. 向量、矩阵2.3. 数据框2.3.1. 创建数据框2.3.2. 创建新变量2.3.3. 变量的重编码2.3.4. 列重命名2.3.5. 缺失值2.3.6. 日期值2.3.7. 数据框排序2.3.8. 数据框合并(合并沪深300和中证500收盘…

Java设计模式:单例模式(饿汉式、懒汉式、枚举实现类)

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

[足式机器人]Part2 Dr. CAN学习笔记-数学基础Ch0-4线性时不变系统中的冲激响应与卷积

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-数学基础Ch0-4线性时不变系统中的冲激响应与卷积 1. LIT System&#xff1a;Linear Time Invariant2. 卷积 Convolution3. 单位冲激 Unit Impulse——Dirac Delta 线性时不变系统 &#xff1a; L…

目标检测综述(待补ing)

文章目录 摘要引言目标检测发展历程目标检测路线图传统检测器基于CNN的两阶段检测器基于CNN的一阶段检测器 目标检测数据集及指标数据集评价指标标注软件 backboneAlexNet&#xff08;2012&#xff09;VGGNet&#xff08;2014&#xff09;GoogleNet&#xff08;2014&#xff09…

使用函数计算,数禾如何实现高效的数据处理?

作者&#xff5c;邱鑫鑫&#xff0c;王彬&#xff0c;牟柏旭 公司背景和业务 数禾科技以大数据和技术为驱动&#xff0c;为金融机构提供高效的智能零售金融解决方案&#xff0c;服务银行、信托、消费金融公司、保险、小贷公司等持牌金融机构&#xff0c;业务涵盖消费信贷、小…

Node.js快速搭建简单的HTTP服务器并发布公网远程访问

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…