用 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),保留第一个卷积层,去掉了中间的卷积层。

工程实现方面参照了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个周末的时间,实现难度一般,过程有些简单的认识:
-
之所以Python成为深度学习界的标准开发语言,是因为它有很多强大的库和平台,像NumPy、Pytorch、Keras等,写一个神经网络可能只需几十行代码,简单高效,其他语言无可匹及。业界正在研究基于Python语言的编译技术,这可能是未来重要的方向之一。
-
深度学习与传统软件工程差别大,传统软件工程是建立的逻辑学层面的工程体系,只要逻辑性强从事软件开发不是难事,所以行业内人员参差不齐。AI和深度学习领域有自己独立的知识体系,而且更多是要依靠数学推导和模型设计,工程实现也更偏CPU/GPU相关的编程,逻辑在其中起的作用有限,AI这个领域不太可能出现从培训机构出来就业的人员。传统软降工程也走到一个阶段了,软件工程的需求正在从传统的工程领域快速迁移到深度学习领域。
-
深度学习的计算分为推理和训练,随着网络模型的发展计算将越来越重。训练的计算量会因为成本越来越高会出现更高效的芯片和分布式计算网络。而推理计算由于安全和场景需要,可能会越来越终端化,而且推理的计算量未来是训练计算量的万倍甚至更多,会催生出新的工程领域,例如ggml。
-
AI发展很快,很多面向程序员的工具,像github copilot、cursor等,生成的代码未必可直接使用,但能够加快从概念到代码的过程,合理使用AI工具可以更快的进入陌生领域。
科技正在大力向前,它已不再朝我而来,我唯一能做的是调整自己的位置来跟上它的步伐。
相关文章:
用 C 写一个卷积神经网络
用 C 写一个卷积神经网络 深度学习领域最近发展很快,前一段时间读transformer论文《Attention Is All You Need》时,被一些神经网络和深度学习的概念搞得云里雾里,其实也根本没读懂。发现深度学习和传统的软件开发工程领域的差别挺大…...
直面双碳目标,优维科技携手奥意建筑打造绿色低碳建筑数智云平台
优维“双碳”战略合作建筑 为落实创新驱动发展战略,增强深圳工程建设领域科技创新能力,促进技术进步、科技成果转化和推广应用,根据《深圳市工程建设领域科技计划项目管理办法》《深圳市住房和建设局关于组织申报2022年深圳市工程建设领域科…...
docker 基础入门
docker 基础入门 引言 在当今快速演进的软件开发领域,Docker 已经成为一个革命性的工具,它极大地改变了我们构建、部署和管理应用程序的方式。作为一种开源容器化平台,Docker 提供了一个轻量级且一致的环境,使得软件能够在几乎任…...
HarmonyOS:NativeWindow 开发指导
场景介绍 NativeWindow 是 HarmonyOS 本地平台化窗口,表示图形队列的生产者端。开发者可以通过 NativeWindow 接口进行申请和提交 Buffer,配置 Buffer 属性信息。 针对 NativeWindow,常见的开发场景如下: ● 通过 NativeWindow…...
汉威科技传感器为农业加点“智慧”
农业是国家之根本,历来受到高度重视,在央视《传感中国》系列节目中,智慧农业独占一期,重要性不言而喻。 随着传感器、物联网、GIS、大数据、5G、人工智能、区块链等技术的快速发展,智慧农业成为种植、养殖行业的新趋势…...
springboot listener、filter登录实战
转载自: www.javaman.cn 博客系统访问: http://175.24.198.63:9090/front/index 登录功能 1、前端页面 采用的是layui-admin框架,文中的验证码内容,请参考作者之前的验证码功能 <!DOCTYPE html> <html lang"zh…...
【数据结构—栈的实现(数组栈)】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、栈 1.1栈的概念及结构 二、栈的实现 2.1头文件的实现—Stack.h 2.2源文件的实现—Stack.c 2.3源文件的测试—test.c 三、栈的实际测试数据展示 3.1正常的出…...
Linux安装Halo(个人网站)
项目简介 1.代码开源:Halo 的项目代码开源在 GitHub 上且处于积极维护状态,截止目前已经发布了 109 个版本。你也可以在上面提交你的问题或者参与代码贡献。2.易于部署:推荐使用 Docker 的方式部署 Halo,便于升级,同时避免了各种环境依赖的问…...
Java - Spring中Bean的循环依赖问题
什么是Bean的循环依赖 A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。 比如:丈夫类Husband,妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。 Spring解决循环依赖的机理 Spring为什么可以解决set s…...
使用 Python 实现简单的爬虫框架
爬虫是一种自动获取网页内容的程序,它可以帮助我们从网络上快速收集大量信息。在本文中,我们将学习如何使用 Python 编写一个简单的爬虫框架。 一、请求网页 首先,我们需要请求网页内容。我们可以使用 Python 的 requests 库来发送 HTTP 请…...
Activiti七大接口,28张表详解
Activiti七大接口,28张表详解 7大接口 RepositoryService:提供管理流程部署和流程定义API。 RuntimeService:提供运行时流程实例进行管理与控制API。 TaskService:提供流程任务管理API。 IdentityService:提供对流程…...
解决msvcr120.dll文件丢失问题
项目场景: 在VMware虚拟机中安装win7家庭版系统,安装MySQL数据库,部署项目文件。 问题描述 安装MySQL数据库过程中提示“msvcr120.dll文件丢失”。 原因分析: 提示丢失msvcr120.dll文件,我们首先要到C:\Windows\Sys…...
AI日报:人工智能与新材料的发现
文章目录 总览人工智能正在革命性地发现新的或更强的材料,这将改变制造业。更坚韧的合金问题研究解决方案 新材料人工智能存在的挑战方法探索 日本的研究人员正在使用人工智能制造更强的金属合金或发现新材料,并彻底改变制造过程 总览 日本的研究人员开…...
鱼fish数据集VOC+yolo-1400张(labelImg标注)
鱼类,是最古老的脊椎动物。易蓄积重金属。 部分不同染色体数目的杂交的后代依然有生育能力。它们几乎栖居于地球上所有的水生环境,从淡水的湖泊、河流到咸水的大海和大洋。 今天要介绍鱼的数据集。 数据集名称:鱼 fish 数据集格式…...
爬虫解析-BeautifulSoup-bs4(七)
目录 1.bs4的安装 2.bs4的语法 (1)查找节点 (2)查找结点信息 3.bs4的操作 (1)对本地文件进行操作 (2)对服务器响应文件进行操作 4.实战 beautifulsoup:和lxml一样…...
分类预测 | Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输入数据分类预测
分类预测 | Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输入数据分类预测 目录 分类预测 | Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输入数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现OOA-SVM鱼鹰算法优化支持向量机的多变量输…...
2.vue学习笔记(目录结构+模板语法+属性绑定)
文章目录 1.目录结构2.模板语法2.1.文本插值2.2.使用JavaScript表达式2.3.原始HTML 3.属性绑定3.1.简写3.2.布尔型Attribute3.3.动态绑定多个值 1.目录结构 1.vscode ——VSCode工具的配置文件夹 2.node_modules ——Vue项目的运行依赖文件夹 3.public ——资源文件夹&am…...
Python基本语法及高级特性总结
1. Python基本语法 1.1 变量和数据类型 在Python中,变量不需要预先声明,可以直接赋值。Python是一种动态类型语言,变量的类型会根据赋值的对象自动确定。例如: a 10 # a是整数类型变量 b 3.14 # b是浮点数类型变量 c …...
03-详解网关的过滤器工厂和常见的网关过滤器路由过滤器,默认过滤器,全局过滤器的执行顺序
过滤器工厂 过滤器种类 GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务响应的结果做加工处理 Spring提供了31中不同的路由过滤器工厂 AddResponseHeader表示给请求添加响应头 default-filters: # 默认过滤器 - AddResponseHeaderX-Response-Default-R…...
基于SSM的小儿肺炎知识管理系统设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...
RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...
使用VMware克隆功能快速搭建集群
自己搭建的虚拟机,后续不管是学习java还是大数据,都需要集群,java需要分布式的微服务,大数据Hadoop的计算集群,如果从头开始搭建虚拟机会比较费时费力,这里分享一下如何使用克隆功能快速搭建一个集群 先把…...
