BP神经网络原理推导和实现

BP神经网络原理(详细推导) 系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录前言第一步:正向传播激活神经网络A.变量说明B.正向传播C.偏置单元二、误差逆向传播1.理解误差逆向传播2.梯度检测3.初始化的重要性总结 前言 BP神经网络(Back propagation neural network)全称为多层前馈神经网络,其用于解决非线性问题。整个神经 阅读详情


Introduction

传统工科er,大一上数学建模课就听说了BP神经网络这玩意儿,后来参加数模竞赛也经常用它。但一直是通过调用第三方包的方式来使用,神经网络对我而言简直就是黑盒中的黑盒。这回趁着毕业论文又要用它,索性学下原理,或许是考研的缘故,把数学基础给补了补,居然花了一两天时间就大概清楚BP神经网络咋运作的了… ok,拉回正题。BP神经网络(Backpropagation Neural Network,误差反向传播神经网络)是一种经典的监督学习算法,广泛应用于分类、回归等任务。它的核心是通过反向传播算法动态调整网络参数(权重和偏置),使网络输出逐渐逼近真实值。本文首先从一个三层结构的BP神经网络出发,推导出三层结构BP神经网络的相关计算公式,然后再推广到任意结构的BP神经网络,最后以经典的手写数字识别为例利用Numpy从头搭建一个神经网络。


Formula derivation

前向传播过程的相关公式是很显然的,反向传播算法相关公式推导中只会用到最基础的矩阵和向量求导的知识,这部分可以参考reference中的第一篇文章,讲的很清楚。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


Code implementation

load_mnist文件和MNIST数据集合下载:https://pan.baidu.com/s/1cfM92iI5BBz7xbBdR3HOFQ?pwd=mqwe

# -*- coding: utf-8 -*-
"""
Created on Fri Mar 14 19:56:49 2025
@author: syaunsheng
"""
import numpy as np
from MNIST.load_mnist import load_mnist
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif']=['Times New Roman']

class Bpnn():
    def __init__(self,structure,activation=None):
        self.fdict = {'sigmoid':self.sigmoid}
        self.dfdict = {'sigmoid':self.dsigmoid}
        if activation is None:
            activation = {'acfun_'+str(i+1):"sigmoid" for i in range(1,len(structure))} # 默认使用sigmoid函数作为各层的激活函数
        assert len(structure)-1 == len(activation),'check the length of strucure and activation.'
        self.structure = structure
        self.activation = activation
        self.wdict = {'w_'+str(i+1):np.random.randn(self.structure[i],self.structure[i-1]) 
                      for i in range(1,len(self.structure))} # 初始化网络权重矩阵
        self.bdict = {'b_'+str(i+1):np.random.randn(self.structure[i],1)
                      for i in range(1,len(self.structure))} # 初始化网络偏置向量
        self.zdict = {'z_'+str(i+1):None for i in range(1,len(self.structure))} # 初始化网络状态值向量
        self.adict = {'a_'+str(i+1):None for i in range(1,len(self.structure))} # 初始化网络激活值向量
        self.deltadict = {'delta_'+str(i+1):None for i in range(1,len(self.structure))} # 初始化网络delta值向量
        self.pdwdict = {'pdw_'+str(i+1):None for i in range(1,len(self.structure))} # 初始化网络对权重的偏导数矩阵
        self.pdbdict = {'pdb_'+str(i+1):None for i in range(1,len(self.structure))} # 初始化网络对偏置的偏导数矩阵
        self.loss = [] # 记录每个批次的平均损失
        
    def forward(self,x):
        assert x.ndim == 2,"x's dimmension must be 2."
        assert x.shape[1] == 1,"x's must be a colomn vector."
        # 前向传播算输出
        for i in range(1,len(self.structure)):
            # 计算第i+1层的状态值向量
            if i == 1:
                self.zdict['z_'+str(i+1)] = (np.dot(self.wdict['w_'+str(i+1)],
                                                    x)+self.bdict['b_'+str(i+1)]) # a_1就是x
            else:
                self.zdict['z_'+str(i+1)] = (np.dot(self.wdict['w_'+str(i+1)],
                                                    self.adict['a_'+str(i)])+self.bdict['b_'+str(i+1)])
            # 计算第i+1层的激活值向量
            self.adict['a_'+str(i+1)] = self.fdict[self.activation['acfun_'+str(i+1)]](self.zdict['z_'+str(i+1)])
    
    def backward(self,x,y):
        assert x.ndim == 2,"x's dimmension must be 2."
        assert x.shape[1] == 1,"x's must be a colomn vector."
        assert y.ndim == 2,"y's dimmension must be 2."
        assert y.shape[1] == 1,"y's must be a colomn vector."
        # 反向传播算偏导数
        for i in range(len(self.structure),1,-1):
            if i == len(self.structure):
                self.deltadict['delta_'+str(i)] = (-(y-self.fdict[self.activation['acfun_'+str(i)]](self.zdict['z_'+str(i)]))
                                                   *self.dfdict[self.activation['acfun_'+str(i)]](self.zdict['z_'+str(i)]))
            else:
                self.deltadict['delta_'+str(i)] = (np.dot(self.wdict['w_'+str(i+1)].T,self.deltadict['delta_'+str(i+1)])
                                                   *self.dfdict[self.activation['acfun_'+str(i)]](self.zdict['z_'+str(i)]))
            if i >= 3: 
                self.pdwdict['pdw_'+str(i)] = np.dot(self.deltadict['delta_'+str(i)],self.adict['a_'+str(i-1)].T)
            else:
                self.pdwdict['pdw_'+str(i)] = np.dot(self.deltadict['delta_'+str(i)],x.T)
            self.pdbdict['pdb_'+str(i)] = self.deltadict['delta_'+str(i)]
    
    def train(self,x_train,y_train,max_iter=1000,batch_size=32,learning_rate=1e-2):
        counter = 0
        for iter_time in range(max_iter):
            pos = np.random.randint(x_train.shape[0],size=batch_size)
            batch_x,batch_y = x_train[pos,:],y_train[pos,:] # 生成用于本次迭代的batch
            memory = [] # 记录每个样本对于的(zdict,adict,pdwdict,pdbdict)
            memory_loss = [] # 记录每个样本的损失
            for x,y in zip(batch_x,batch_y):
                self.forward(x.reshape(-1,1))
                self.backward(x.reshape(-1,1), y.reshape(-1,1))
                memory.append((self.zdict,self.adict,self.pdwdict,self.pdbdict))
                memory_loss.append(self.mse(self.adict['a_'+str(len(self.structure))], y.reshape(-1,1)))
            self.loss.append(np.mean(memory_loss))
            # 梯度下降参数更新
            for i in range(1,len(self.structure)):
                sum_pdw = np.zeros_like(self.pdwdict['pdw_'+str(i+1)])
                sum_pdb = np.zeros_like(self.pdbdict['pdb_'+str(i+1)])
                for _,_,pdw,pdb in memory:
                    sum_pdw += pdw['pdw_'+str(i+1)]
                    sum_pdb += pdb['pdb_'+str(i+1)]
                self.wdict['w_'+str(i+1)] -= learning_rate*sum_pdw
                self.bdict['b_'+str(i+1)] -= learning_rate*sum_pdb  
            # 打印求解状态
            if iter_time % (max_iter//100) == 0:
                counter += 1
                print('[{}/{}]:loss={}'.format(iter_time,max_iter,np.mean(memory_loss)))
                
        
    def predict(self,x):
        assert x.ndim == 2,"x's dimmension must be 2."
        assert x.shape[1] == 1,"x's must be a colomn vector."
        self.forward(x)
        res = self.adict['a_'+str(len(self.structure))] # 获取预测结果,再转化
        return np.where(res == res[np.argmax(res),0],1,0) 
        
    def accuracy(self,x_test,y_test):
        # 测试接口
        acc = 0
        for x,y in zip(x_test,y_test):
           if np.all(self.predict(x.reshape(-1,1)) == y.reshape(-1,1)):
               acc += 1
        return acc/len(y_test)
                
                
    def sigmoid(self,z):
        # 解决了溢出问题
        z_ravel = z.ravel()  # 将numpy数组展平
        y = []
        for item in z_ravel:
            if item >= 0:
                y.append(1.0 / (1 + np.exp(-item)))
            else:
                y.append(np.exp(item) / (np.exp(item) + 1))
        return np.array(y).reshape(z.shape)
    
    def dsigmoid(self,z):
        # sigmoid函数的导数
        return self.sigmoid(z)*(1-self.sigmoid(z))
    
    def mse(self,pred,y):
        """均方损失函数"""
        return np.sum(1/2*(y-pred)**2)

if __name__ == '__main__':
    dataset = load_mnist() 
    # 查看一下图像信息,看读取是否出错,再x_train中每一行应该都对应一张28x28像素的图像
    plt.close('all')
    fig,ax = plt.subplots(3,4)
    x_train,y_train,x_test,y_test = (dataset['x_train'],dataset['y_train'],
                                     dataset['x_test'],dataset['y_test'])
    for i in range(3):
        for j in range(4):
            ax[i,j].imshow(x_train[i*j,:].reshape(28,28),cmap='grey') 
    # 模型训练
    model = Bpnn([784,50,20,10])
    model.train(x_train, y_train,max_iter=10000)
    fig,ax = plt.subplots(figsize=(7,4))
    ax.plot(model.loss,color='blue')
    ax.set_xlabel('iteration')
    ax.set_ylabel('loss')
    # 精度测试
    print('模型准确率:{}'.format(model.accuracy(x_test, y_test)))

模型精度约为0.82,损失函数变化情况见下图。
123
ok,再用tkinter写一个界面封装一下,咱们可以随时使用自己写的神经网络做预测了:完整代码下载地址。
在这里插入图片描述
在这里插入图片描述


Reference

科技猛兽:机器学习中的数学理论1:三步搞定矩阵求导
BP(Back Propagation)神经网络–原理篇

BP神经网络推导过程 BP神经网络推导 阅读详情

相关推荐

BP神经网络的数学原理及其算法实现

BP神经网络,BP即Back Propagation的缩写,也就是反向传播的意思,顾名思义,将什么反向传播?文中将会解答。不仅如此,关于隐层的含义文中也会给出个人的理解。最后会用Java实现的BP分类器作为其应用以加深印象。   很多初学者刚接触神经网络的时候都会到网上找相关的介绍,看了很多数学原理之后还是云里雾里,然后会琢磨到底这个有什么用?怎么用?于是又到网上找别人写的代码,下下来之后看一眼发现代码写的很糟糕

学无常师,负笈不远险阻 12万+

BP神经网络(算法整体思路及原理+手写公式推导)

1. 简介2. 计算过程3. 权重偏置更新公式推导4. BP神经网络优劣势 1. 简介 BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,是应用最广泛的神经网络。 BP网络是在输入层与输出层之间增加若干层(一层或多层)神经元,这些神经元称为隐单元,它们与外界没有直接的联系,但其状态的改变,则能影响输入与输出之间的关系,每一层可以有若干个节点。 2. 计算过程 首先,我们先来了解.

秃头小苏的博客 8万+

bp神经网络推导及python实例

bp神经网络 BP(back propagation,反向传播)神经网络(neural network),通常指具有三层网络结构的浅层神经网络。神经网络由一个个神经元(Neuron)组成,神经元由输入、计算、输出单元组成。 对应上图输入为x1,x2,⋯ ,xnx_1,x_2,\cdots,x_nx1​,x2​,⋯,xn​和截距+1+1+1,输出为: y^=hw,b(X...

猫哥 3989

BP神经网络推导

1

biiiiiide的博客 1581

深度神经网络DNN的反向传播原理及推导

DNN反向传播推理 CNN反向传播推理 对于对于任意(Borel measurable function)波莱尔可测函数(包括⼀切阶梯函数、⼀切连续函数和分段连续函数)和任意给定精度,都可以使⽤多层感知机(MLP)来近似。 【1989】Multilayer feedforward networks are universal approximators,该⽂章中证明了任意宽 的单隐层MLP的万能近似性质。 【2017】Universal Function Approximation by Deep Neur

catscanner的博客 907

FPGA—ZYNQ_BD Block Design学习(一)

1.第一步:打开Vivado软件,创建或打开一个工程。2.第二步:在Block Design中添加arm核心,并将其配置为IP核。3.第三步:配置arm核心的外设信息,如DDR接口、时钟频率、UART接口等。4.第四步:完成Block Design中的模块互联,生成PL端的比特流。 5.第五步:导出PS端的硬件信息,包括arm IP核的外设、速度、引脚和地址等信息。1创建bd 需要有ddr以及uart和时钟配置外设io口,这里就是zynq的管脚规定好的,根据原理图用哪个个勾选哪一个。 对外设uart的配

m0_58129662的博客 1028

神经网络的BP算法推导详解

神经网络的BP算法推导详解一.BP算法的提出及其算法思想二.BP算法三.前馈计算的过程四.反向传播的计算 一.BP算法的提出及其算法思想 神经网络主要是由三个部分组成的,分别是:1) 网络架构 2) 激活函数 3) 找出最优权重值的参数学习算法. BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络。 既然我们无法直接得到隐层的权值,能否先通过输出层得到输出结果和期望输出的误差来间接调

qq_43232556的博客 5174

手把手教你自制Type-C OTG转换器(附电路图及避坑指南)

本文详细指导如何自制Type-C OTG转换器,包括核心电路设计、元器件选型及焊接技巧,特别强调硬件检测电路的关键作用。通过实测数据和避坑指南,帮助开发者解决兼容性问题,实现高效数据传输。

weixin_27038245的博客 712

BP神经网络算法推导/激活函数文章推荐(开头)

本篇文章为转载,真的觉得这篇文章写的详细易懂,推导也写的很清晰,怕之后删除掉,所以复制过来 原文地址:https://zhuanlan.zhihu.com/p/38006693 另外还有一篇专门写激活函数的文章:https://blog.youkuaiyun.com/tyhj_sf/article/details/79932893 首发于腾讯技术 已关注写文章 AI从入门到放弃...

Lollipop66的博客 2719

win10任务栏文件夹设置成竖形列表样式

win10任务栏文件夹设置成竖形列表样式

ftzchina的博客 7079

别再踩坑了!QT5.15.2配置Android开发环境保姆级避坑指南(含Java8、SDK Tools版本选择)

本文提供QT5.15.2配置Android开发环境的详细避坑指南,重点解决版本锁定、SDK工具选择和QtCreator配置等常见问题。通过实测推荐的Java8、Android SDK Tools版本及NDK配置,帮助开发者高效完成环境搭建,避免隐性冲突和配置失败。

weixin_42537919的博客 237

机器学习——神经网络(四):BP神经网络

BP神经网络(Back Propagation)   误差逆传播算法(error Back Propagation 简称BP),实际上是多层感知器的一种,在1986由Rumelhart和Hinton为首的科学小组提出。BP神经网络具有任意复杂的模式分类能力和优良的多维函数映射能力,解决了简单感知器不能解决的异或问题和其他问题。从结构而言具有输入层、隐含层和输出层;从本质上来讲是以网络误差平方为目标函数、采用梯度下降法来计算目标函数的最小值。 主要过程: (1)工作信号向前正向传播的子过程 (

Liu Feng's Blog 1万+

Android息屏后台任务保活实战:从定时器失效到厂商白名单破解

本文深入探讨了Android应用在息屏后定时任务失效的根源,即系统为省电而触发的休眠机制。文章提供了从传统方案失效分析到实战破解的完整路径,核心在于引导用户将应用加入电池优化白名单并开启自启动权限,从而合法绕过限制。同时,结合WorkManager、AlarmManager等可靠定时方案,实现稳定的后台任务执行。

weixin_28475533的博客 422

bp神经网络推导以及物理意义

bp神经网络的背景我们不在做过多的介绍,就是模拟神经元,进行分类训练。他的物理意义是什么呢,就是每个神经元对应我们计算中的滤波器,当他"看到"某个图片或者某组数据,反应就特别强烈,相乘所得的值就特别大,这大概就是所说的激活吧。首先,我们来看看bp神经的数学样例图: 大家肯定有疑问了,为什么是三层,为什么不是两层或者更多层,其实都是可以的,只是是三层效果比较基...

lcsfdp的专栏 1976

001-基础入门-Web演示源码&资源&工具箱等

小迪安全2023笔记

wushangyu32335的博客 4260

【智能车Code review】—曲率计算、最小二乘法拟合

【1】曲率计算函数 选三个点计算曲率 float process_curvity(byte x1, byte y1, byte x2, byte y2, byte x3, byte y3) { float K; int S_of_ABC = ((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)) / 2; //面积的符号表示方向 byte q1 = (byte)((x2 - x1) * (x2 - x1) + (y2 - y1) *

hanhan的博客 1万+

深入浅出|深度学习算法之BP神经网络 详细公式推导

BP(back propagation)神经网络一种按照误差逆向传播算法训练的多层前馈神经网络,是目前应用最广泛的神经网络。

FENG_LIN的博客 2万+

QGIS安装与使用教程

QGIS安装与使用教程

weixin_46713695的博客 2万+

BP神经网络及python实现(详细)

本篇文章关于BP神经网络的算法实现相对来说通俗易懂,讲解下至关于函数变量的解释,上至关于BP算法中涉及的前向传播及反向传播的原理、再至其过程中涉及的公式详细推导都有笔者的一些思考笔记。本文也对标准的BP神经网络进行几处改进,目的都是为了提高训练速度。另外,若文章存在一些理论错误请各位不吝赐教,当然,在阅读过程中若有些地方不明白可以在评论区留言!

weixin_66845445的博客 5万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

深度学习笔记——手稿推导BP算法(附代码实现)

相信很多小伙伴在学习深度学习的过程中,都无法逃避BP(Back Propagation)反向传播算法,确实是ML、DL的经典算法之一。此处假设你对BP已经有了神经网络的基本概念,并且最好已经看过BP算法。 接下来将是简洁而详细的手推过程。看完这篇文章后,能够帮助你弄懂BP算法的具体流程,以及BP算法的数学推导过程。 神经网络BP算法例子 神经网络FP、BP的推算过程:(原理不难,对上号代公式即可) ...

weixin_40730615的博客 832

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深入解析BP神经网络:从理论到实战的全面指南

生物神经元模型与人工神经元的对比示意图:*!

2401_85106625的博客 1143

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

BP神经网络的介绍

  本文着重讲述经典BP神经网络的数学推导过程,并辅助一个小例子。本文不会介绍机器学习库(比如sklearn, TensorFlow等)的使用。 欲了解卷积神经网络的内容,请参见我的另一篇博客一文搞定卷积神经网络——从原理到应用。   本文难免会有叙述不合理的地方,希望读者可以在评论区反馈。我会及时吸纳大家的意见,并在之后的chat里进行说明。 本文参考了一些资料,在此一并列出。 http://neuralnetworksanddeeplearning.com/chap2.html https://ww

LTC_1234的博客 7884

BP神经网络-从推导到实现

1.BP神经网络结构与原理 由于BP神经网络参数超级多,如果不先定义好变量,后面非常难理解,故针对上述图形,定义如下: 通过上面的定义可知: 2.BP神经网络公式推导 第一次项是均方差项(经验风险),第二项是正则项。可以看出,代价函数是关于所有权重和偏置的方程,要通过求代价函数最小来得到最佳的权重和偏置,可以采用梯度下降法逐步下降迭代得到,具体为: 现在就是要求各权重和偏置的偏导,直接求上述式子会发现非常困难,而BP反向传播算法就是一种方便的求解...

river_19的博客 436

模式识别:BP神经网络算法

1、BP神经网络分类器 1.1 BP算法基本原理 神经网络结构大概如下图1-1: 图1-1 包括输入层,隐层和输出层。包含一层隐层的神经网络称为浅层神经网络,即SNN。包含多层隐层的神经网络称...

u011591807的博客 1万+

BP神经网络原理与异或实例分析

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录BP神经网络原理介绍一、BP神经网络算法原理是什么?二、激活函数1.激活函数作用三、BP神经网络异或实例分析1.问题:2.分析:3.代码总结 BP神经网络原理介绍 BP神经网络算法(Back-Propagation Neural Network) 一、BP神经网络算法原理是什

阿宾的地盘儿 2216

BP神经网络(Back Propagation Neural Network)算法原理推导与Python实现详解

该神经网络被设置为三层:一层输入层、一层隐藏层、一层输出层 样本集: 特征一 特征二 标签 0 0 0 0 1 1 1 0 1 1 1 0 可以看出,这就是一个异或样本集,使用这个样本集可以展现出神经网络与感知机在处理非线性可分问题上的差别。 import math import random # ...

白水的博客 4333
上一篇: 爬取使用了Ajax技术的网页中的数据
下一篇: 基础python爬虫
SACUKI
博客等级 码龄5年 139粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值