基于BP神经网络的简单字符识别算法自小结(C语言版)

C语言bp神经网络,四分类任务 该程序是gpt生成的,我稍加改动,可以直接运行。后续会上传到github上。 阅读详情

1.BP神经网络的基本概念和原理
BP神经网络的概念:
BP(Back Propagation)网络是1986年由Rumelhart和McCelland为首的科学家小组提出,是一种按误差逆传播算法训练的多层前馈网络。是目前应用最广泛的神经网络模型之一。BP网络能学习和存贮大量的输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。BP神经网络的基本模型图如下所示:
这里写图片描述
BP网络的三个层次:输入层、隐藏层以及输出层。我们所要做的就是根据自身的需求建立一个属于我们自己的BP神经网络。

2.BP神经网络的原理以及相关公式的推导
2.1、BP网络的基本思想:
BP神经网络学习过程由信息的正向传递与误差的反向传播两个过程组成:
(1) 正向传递:输入样本从输入经隐含层逐层计算传向输出层,若输出层的实际输出和期望输出不符,则计算输出层的误差值,然后转向反向传播过程。
(2) 误差的反向传播:是将输出误差以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层所有单元,从而获得各层单元的误差信号,此误差做为修正该单元的依据。信号正向传递和误差反向传播反复进行,权值不断得到调整的过程,就是网络的学习/训练过程。当训练达到规定误差或一定训练次数,则结束训练。

BP网络训练学习过程可理解成:样本输入时的理想目标Tk与实际输出Ok之间的误差平方Ep不断趋向于0的一个过程:
这里写图片描述
根据误差梯度下降法依次修正输出层权值的修正量 Δ wki ,输出层阈值的修正量 Δa k,隐含层权值的修正量 Δ wij ,隐含层阈值的修正量这里写图片描述:
这里写图片描述
上述公式表明网络输入误差是各层权值wjk、vij的函数,因此调整权值可改变误差E。显然,调整权值的原则是使误差不断地减小,因此应使权值的调整量与误差的梯度下降成正比,故而对BP网络算法的直观解释如下所示:
这里写图片描述
通过上图表明,BP网络算法的核心是在不断调整权值的情况下,使得误差不断的减小。显然无论是在正向梯度还是负向梯度,在离散情况下都需要不断的将权值往误差极小值的地方调整。而调整的速率值eta(也称权值的步进值)关乎着整个神经网络的训练速度。

BP神经网络的公式推导可以参考:http://en.wikipedia.org/wiki/Backpropagation,相关推导公式核心内容如下:

BP网络的算法核心是使用一个刺激函数不断的forward,而这个刺激函数往往使用S型激活函数(logsig)为:
这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
3.BP神经网络算法用C语言的实现
3.1.初始的准备工作,建立三个层的数据结构体:分别表示样本信息、输入层的信息、隐藏层的信息以及输出层的信息,最终归于到一个BP核心算法的结构体bp_alg_core_params;

    typedef struct {  

        unsigned int img_sample_num; //待训练的图像字符、数字样本个数  
        unsigned int img_width;  
        unsigned int img_height;  
        unsigned char *img_buffer;  

    }img_smaple_params;  

    typedef img_smaple_params* hd_sample_params;  


    typedef struct {  

        unsigned int in_num;  //输入层节点数目  
        double *in_buf; //输入层输出数据缓存  
        double **weight; //权重,当前输入层一个节点对应到多个隐层  
        unsigned int weight_size;  
        double **pri_deltas; //记录先前权重的变化值,用于附加动量  
        double *deltas; //当前计算的隐层反馈回来的权重矫正  

    }bp_input_layer_params;  

    typedef bp_input_layer_params* hd_input_layer_params;  

    typedef struct {  

        unsigned int hid_num; //隐层节点数目  
        double *hid_buf; //隐层输出数据缓存  
        double **weight; //权重,当前隐层一个节点对应到多个输出层  
        unsigned int weight_size;  
        double **pri_deltas; //记录先前权重的变化值,用于附加动量  
        double *deltas; //当前计算的输出反馈回来的权重矫正值  

    }bp_hidden_layer_params;  

    typedef bp_hidden_layer_params* hd_hidden_layer_params;  


    typedef struct {  

        unsigned int out_num;//输出层节点数目  
        double *out_buf; //输出层输出数据缓存  
        double *out_target;  

    }bp_out_layer_params;  

    typedef bp_out_layer_params* hd_out_layer_params;  


    typedef struct {  

        unsigned int size; //结构体大小  
        unsigned int train_ite_num; //训练迭代次数  
        unsigned int sample_num;  //待训练的样本个数  
        double momentum;   //BP阈值调整动量  
        double eta;                //训练步进值,学习效率  
        double err2_thresh;  //最小均方误差  

        hd_sample_params p_sample; //样本集合参数  
        hd_input_layer_params p_inlayer; //输入层参数  
        hd_hidden_layer_params p_hidlayer;//隐藏层参数  
        hd_out_layer_params p_outlayer;//输出层参数  

    }bp_alg_core_params;  

3.2.参数的初始化,主要包括对计算缓存区的分配。

假设这里分别有M,N,K表示输入、隐藏、输出的节点数目;

那么一个输入缓存区大小:分配大小M+1个;同理隐藏层和输出分别分配:N+1,P+1个;数据量大小默认双精度的double类型。

权值的缓冲区大小:一个根据BP网络的算法,一个节点到下一层的节点分别需要具备一一对应,故这是一个二维数组的形式存在,我们分配输入层权值空间大小为(M+1)(N+1)的大小,隐藏权值空间大小为(N+1)(P+1);

当然对于权值的矫正量,其是一个依据节点的输出值向后反馈的一个变量,实际就是多对1的反馈,而通过公式可以看到我们可以只采用一维数组来表示每一个节点的反馈矫正值(不基于输入节点的数据,即如下的变量:
这里写图片描述
同理最终隐藏层到输出层的反馈矫正、输出层和隐藏层的反馈矫正都以一个一位变量的形式存在,只是在计算权值时要结合节点的输入数据来进行2维矫正。

完成二维数组的动态分配过程函数如下所示:

    double** alloc_2d_double_buf(unsigned int m, unsigned int n)  
    {  

        unsigned int i;  
        double **buf = NULL;  
        double *head;  

        /*分配一个数组指针空间+ 2维数据缓存空间*/  
        buf = (double **)malloc(sizeof(double *)*m + m*n*sizeof(double));  
        if(buf == NULL)  
        {  
            ERR("malloc error!");  
            exit(1);  
        }  

        head = (double *)(buf + m);  

        memset((void *)head, 0x00, sizeof(double)*m*n);//clear 2d buf  
        for(i = 0; i < m; i++)  
        {  

            buf[i] = head + i*n;  
            DEG("alloc_2d_double_buf,  addr = 0x%x", buf[i] );  
        }  

        return buf;  

    }  

3.3 BP神经网络训练过程和不断的权值矫正

依次经过forward向前刺激,权值矫正值计算,权值调整,样本均分误差计算。以一次样本数所有样本节点计算完后做均方误差,误差满足一定的阈值就说明BP神经网络训练可以基本结束(一般定义可接受的误差在0.001左右):

    int bp_train(bp_alg_core_params *core_params)  
    {  
        unsigned int i, j, k;  
        unsigned int train_num, sample_num;  
        double err2;//均分误差  

        DEG("Enter bp_train Function");  

        if(core_params == NULL)  
        {  
            ERR("Null point Entry");  
            return -1;  
        }  

        train_num = core_params->train_ite_num;//迭代训练次数  
        sample_num = core_params->sample_num;//样本数  

        hd_sample_params p_sample = core_params->p_sample;  //样本集合参数  
        hd_input_layer_params p_inlayer = core_params->p_inlayer;  //输入层参数  
        hd_hidden_layer_params p_hidlayer = core_params->p_hidlayer; //隐藏层参数  
        hd_out_layer_params p_outlayer = core_params->p_outlayer; //输出层参数  

        DEG("The max train_num = %d", train_num);  

        /*依次按照训练样本数目进行迭代训练*/  
        for(i = 0; i < train_num; i++)  
        {  
            err2 = 0.0;  


            DEG("current train_num = %d", i);  

            for(j = 0 ; j < sample_num; j++)  
            {  

                DEG("current sample id = %d", j);  

                memcpy((unsigned char*)(p_inlayer->in_buf+1), (unsigned char*)sample[j], p_inlayer->in_num*sizeof(double));  
                memcpy((unsigned char*)(p_outlayer->out_target+1), (unsigned char*)out_target[j%10], p_outlayer->out_num*sizeof(double));  

                /*输入层到隐藏层的向前传递输出*/  
                bp_layerforward(p_inlayer->in_buf, p_hidlayer->hid_buf, p_inlayer->in_num, p_hidlayer->hid_num, p_inlayer->weight);  

                /*隐藏层到输出层的向前传递输出*/  
                bp_layerforward(p_hidlayer->hid_buf, p_outlayer->out_buf, p_hidlayer->hid_num, p_outlayer->out_num, p_hidlayer->weight);  

                /*输出层向前反馈错误到隐藏层,即权值矫正值*/  
                bp_outlayer_deltas(p_outlayer->out_buf, p_outlayer->out_target, p_outlayer->out_num, p_hidlayer->deltas);  

                /*隐藏层向前反馈错误到输入层,权值矫正值依赖于上一层的调整值*/  
                bp_hidlayer_deltas(p_hidlayer->hid_buf, p_hidlayer->hid_num, p_outlayer->out_num, p_hidlayer->weight, p_hidlayer->deltas, p_inlayer->deltas);  

                /*调整隐藏层到输出层的权值*/  
                adjust_layer_weight(p_hidlayer->hid_buf, p_hidlayer->weight, p_hidlayer->pri_deltas, p_hidlayer->deltas, p_hidlayer->hid_num,   
                                                        p_outlayer->out_num, core_params->eta, core_params->momentum);  

                /*调整隐藏层到输出层的权值*/  
                adjust_layer_weight(p_inlayer->in_buf, p_inlayer->weight, p_inlayer->pri_deltas, p_inlayer->deltas, p_inlayer->in_num,   
                                                        p_hidlayer->hid_num, core_params->eta, core_params->momentum);        

                err2 +=  calculate_err2(p_outlayer->out_buf, p_outlayer->out_target, p_outlayer->out_num);//统计所有样本遍历一次后的均分误差  

            }  

            /*一次样本处理后的均分误差统计*/  
            err2 = err2/(double)(p_outlayer->out_num*sample_num);  
            INFO("err2 =%08f\n",err2 );  

            if(err2 < core_params->err2_thresh)  
            {  
                INFO("BP Train Success by costs vaild iter nums: %d\n", i);  
                return 1;  
            }  
        }  

        INFO("BP Train %d Num Failured! need to modfiy core params\n", i);  
        return 0;  

    }  
C语言实现BP神经网络详细解析 矩阵是BP神经网络中不可或缺的数据结构,矩阵运算的效率直接关系到网络的训练速度和性能。在本章节中,我们将深入了解矩阵运算库的使用与自定义过程。从标准库函数的应用开始,逐步过渡到自定义矩阵运算库的设计与优化,帮助读者建立起高效的矩阵处理能力。在许多情况下,标准库提供的函数可能无法完全满足我们的性能要求,或者无法与特定的应用场景紧密集成。因此,自定义矩阵运算库显得尤为重要。以下是一个简单的自定义矩阵加法函数的示例:i < m;j++) { 阅读详情

相关推荐

基于C++实现 bp 神经网络的手写数字识别

提供 sigmoid,Leaky_Relu,Relu 三种激活函数可供选择。通过本次课设,我们初步了解到计算机语言中神经网络的魅力,这是用代码对人脑的识别系统的简单模拟,是人类创造的计算机世界与自然创造的人脑智慧相衔接的初步桥梁。课设任务中,我们成功完成了利用汇编语言实现对人脑识别数字的初步模拟,同时也面临问题,显然,人脑神经结构旁支交错,现阶段的模拟程度还远远不够。课设中,我们将任务分工,难点一步步攻克,最终的成功结果也让我们明白了团队合作、个人学习精神的重要性。

神仙别闹的自留地 1025

C语言实现BP神经网络并检测手写数字

本文简要记录了作者在实现BP神经网络过程,学到的各种知识。注意只是简单记录一下用到的知识点,内容以公式和结论为主。

m0_50566107的博客 2298

BP神经网络源代码(c语言版本)

BP神经网络代码,vc下实现 BP神经网络代码,vc下实现 BP神经网络代码,vc下实现

BP神经网络C语言实现

BP神经网络C语言实现 山人 BP神经网络应用广泛,大概是今年的五月份左右,我需要做一个多元函数的拟合,所以写了这个BP神经网络。为什么要使用C语言来写呢?因为我的程序需要在单片机上跑,所以不得不使用C语言。 这一篇博客不会讲解BP神经网络的基本原理,反向传播公式,因为关于这些的资料网上已经很多了(虽然大多数都有着不小的BUG,但足以入门学习)。我会着重讲解我写的BP神经网络的每个函数的具体...

qq_39545674的博客 2万+

BP神经网络C语言工程(当前最终版)

这是修改了bug的版本,目前已经在stm32f407zgt6上、msp430F5529上仿真过。

【可不卸载重装】VS2019新建项目里没有CUDA选项

问题:VS2019 新建项目里没有CUDA选项,vs也属性没有cuda。这是因为你在Visual Studio 2019安装之前,先安装了CUDA Toolkit。

qq_62844901的博客 1318

BP神经网络-- C语言实现

在上一篇文章中,介绍了BP神经网络的基本模型、模型中的一些术语并对模型进行了数学上的分析,对它的原理有了初步的认识。那么如何用程序语言来具体的实现它,将是我们下一步需要讨论的问题。本文选取的是C语言来实现一个简单的单隐藏层的BP神经网络(默认大家了解了BP神经网络的基本概念,本文中涉及到些术语参见上一篇  基本模型 ),因此对于其他C类语言(C#、JAVA等)只需对本文中的代码稍作修改即可移植。

xyjikl 5428

EtherCAT丢包问题深度解析:从原理到实战排查指南

在工业自动化与运动控制领域,实时通讯网络的稳定性是系统可靠运行的基石。EtherCAT(以太网控制自动化技术)作为一种高性能工业以太网协议,其核心在于独特的“飞读飞写”机制和纳秒级的分布时钟同步,以实现多设备间的精准协同。然而,物理链路干扰、配置不当或硬件性能瓶颈都可能导致数据帧丢失,破坏时钟同步,进而引发伺服抖动、定位精度下降乃至生产线停机。本文聚焦于EtherCAT丢包这一典型故障,结合SSC(Slave Stack Code Tool)从站协议栈开发与实时系统调优等工程实践,系统阐述其成因、影响及一套

weixin_32050773的博客 341

详解 BP 神经网络基本原理及 C 语言实现

BP(back propagation)即反向传播,是一种按照误差反向传播来训练神经网络的一种方法,BP神经网络应用极为广泛。BP 神经网络主要可以解决以下两种问题:1.分类问题:用给定的输入向量和标签训练网络,实现网络对输入向量的合理分类。2.函数逼近问题:用给定的输入向量和输出向量训练网络,实现对函数的逼近。本文主要介绍 BP 神经网络的基本结构,而后简单介绍用 C 语言实现神经网络必需要用到...

RToax 4389

自制JS某课脚本

根据实际需求自制网页讯网刷题脚本,绕过人脸,弹窗,答题,实现自动化运行

2301_81243054的博客 3458

YOLOv11的代数不变量解释:Syzygy模分析特征重要性,用交换代数揭示卷积核的语义相关性

本文提出了一种基于代数几何与交换代数的创新方法,特别是运用Syzygy模理论,对YOLOv11目标检测算法的卷积核语义相关性进行数学解释。研究揭示了YOLO系列算法演进背后的代数结构特征,建立了网络组件与多项式环、理想簇等代数概念的对应关系。通过构建分层的准同构代数系统,分析了YOLOv11在不同尺度下保持语义不变性的数学本质。文章系统阐述了Syzygy模在CNN特征冗余分析、跨层依赖关系建模和语义聚类中的应用,并提出了适用于动态稀疏训练的改进算法。该理论框架为深度神经网络的解释性研究提供了新的数学工具,同

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1270

机器视觉常用算法C语言实现

小狼@http://blog.youkuaiyun.com/xiaolangyangyang

Hello Mr.Z的博客 1万+

JEDEC JESD51-14 瞬态双界面测试方法详解

(瞬态双界面测试方法,用于测量具有单路径热流的半导体器件的结到壳热阻 RθJC,包括结到壳顶部 RθJCT 和结到壳底部 RθJCB)。该标准于 2010 年发布(版本 JESD51-14.1),旨在提供一种准确、可重复的瞬态方法来测量功率半导体器件(如 MOSFET、IGBT)的结到壳热阻(RthJC),取代传统的稳态测量方法(如 MIL-STD-883E METHOD 1012.1)。方法,通过比较两种不同热界面材料(TIM)下的瞬态温度响应曲线,提取 RthJC,而无需直接测量壳温(Tc)。

专注于前沿技术的探索与实践,热衷于从代码逻辑、架构设计到行业应用等多维度深挖技术本质。期待在技术之路上与你共同成长~ 605

深度学习学习教程,从入门到精通,深度学习概论 — 知识点详解(1)

框架开发方主要语言特点适用场景CaffeC++/Python速度快,CNN支持好计算机视觉TheanoMontreal大学Python首个主流DL框架,已停止维护学术研究(历史)百度Python/C++国产框架,中文文档完善国内产业应用MindSpore华为Python/C++支持昇腾芯片,端-边-云协同华为生态TensorFlowGooglePython/C++生态完善,工业部署成熟工业级部署PyTorchPython/C++

qq_45746668的博客 516

芯片原厂linux驱动开发的分享

大家好,我是XX,来自湖南XX学院,电子信息18级,也曾在创新基地控制组学习过两三年,毕业后就职于一家芯片原厂的解决方案部,担任驱动工程师的职位,算上实习期,我的工作时长已有两年。在此我想将这两年期间学习与积累到的一些经验输出出来,与大家一同分享。知识面有限,只能简单介绍一些驱动开发方向的一些经验,且由于经验尚浅,文中难免会有一些疏漏和错误之处,还请大家积极地批评指正。

嵌入式技术开发 847

apple游客下单逆向分析

Apple游客下单Cookies注册激活流程逆向分析与算法实现

吴秋霖的博客 1999

Introduction to neural network —— C语言实现BP神经网络识别数字

Introduction to nerual network                  基本上玩过数模或者模式识别的研究生就会知道神经网络这个新兴的技术,当然多数人也就只会在matlab里面调用API而已,真正神经网络是什么,怎么实现的...就呵呵了. 仅有基础数据类型元素,没有过多的抽象的C语言实现的时候,才是真正把逻辑思维转化为可用,同时也是对自身逻辑思

Jason Leaster | Rebuilding the tower of babel 6334

如何用 Claude Code 做大型项目重构与架构优化

本文介绍了如何利用Claude Code参与大型项目重构。文章指出,大型项目重构的最大难点在于理解系统结构和控制风险,而非单纯修改代码。作者提出了五步重构法:首先分析项目结构,其次梳理模块依赖关系,然后发现架构问题,接着设计分阶段重构方案,最后逐步实施。重点强调了Claude Code的核心价值在于帮助开发者理解复杂系统、分析模块依赖、发现结构问题、评估改动风险,而非仅作为代码生成工具。文章建议将Claude Code作为架构助手,通过分阶段小范围重构来降低风险,而非一次性全面重构。

sg_knight的专栏 1571

bp神经网络c语言实现

#include "stdio.h" #include "stdlib.h" #include "time.h" #include "math.h" /********************************************* inpoints 为输入神经元个数,可改变 outpoints为输出神经元个数 defaultpoints为隐层神经元个数 datagrou

south_mountain_kl的专栏 4120

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

c 语言实现神经网络算法,神经网络BP算法(C程序实现)[转载]

文件输入输出目录为:F:\BP\训练样本文件名:训练样本.txt值为:11-11-110101输出文件名为:阈值.txt权值.txt=========================#include "stdlib.h"#include "math.h"#include "conio.h"#include "stdio.h"#define N 2 /*/学习样本个数*/#define IN 3 ...

weixin_30357183的博客 1726

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

深度学习神经网络纯C语言基础版

本文转载自:http://blog.youkuaiyun.com/calcular/article/details/47031417当今Deep-Learning已经是火到一定境界了,深度学习神经网络(DNN)在计算机视觉领域的表现可谓见效非凡。当然,工程上运用了卷积神经网络来减少计算量而不是全连结的神经网络-这样计算量实在太大了。但是,对于神经网络来说计算量真的不是问题,因为它的结构能够确保它能够并行计算,

Trent1985的专栏 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

基于C语言BP神经网络的实现

本文介绍了BP神经网络的实现及其在螨虫分类问题中的应用。实验采用C++语言在Visual Studio 2017环境下开发,构建了三层BP神经网络模型(输入层、隐藏层和输出层)。文章详细阐述了BP神经网络的结构原理、算法流程和数学推导过程,包括前向传播计算、误差反向传播及权值调整机制。通过实验分析了隐藏层节点数量对模型性能的影响,比较了不同训练方式的收敛效果。结果显示,BP神经网络能有效解决非线性映射问题,但也存在学习速度慢、初始参数设定缺乏理论指导等局限性。实验截图展示了神经网络训练过程和分类效果。该研究

毕业作品网站 1974

C语言实现神经网络

这个例子中,我们实现了一个简单的单层神经网络,它只有一个输入节点和一个输出节点,权重向量有3个元素(对应于输入节点和输出节点之间的3个连接),偏置为0。我们使用sigmoid作为激活函数,使用梯度下降法进行训练。在训练过程中,我们根据期望的输出和实际的输出计算误差,然后根据误差和梯度更新权重和偏置。最后,我们使用训练好的神经网络来计算输入为[1, 1]时的输出,输出结果为0.99。神经网络是一种深度学习的结构,它可以模拟人脑的神经元来进行复杂的学习和预测。下面是一个简单的使用C语言实现神经网络的例子。

weixin_62562497的博客 2485
上一篇: 银行家算法
下一篇: 4gl 的内建函数和操作符简介
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值