Python手写神经网络实现3层感知机

一、BP神经网络结构模型       

        BP算法的基本思想是,学习过程由信号的正向传播和误差的反向传播俩个过程组成,输入从输入层输入,经隐层处理以后,传向输出层。如果输出层的实际输出和期望输出不符合,就进入误差的反向传播阶段。误差反向传播是将输出误差以某种形式通过隐层向输入层反向传播,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,这个误差信号就作为修正个单元权值的依据。知道输出的误差满足一定条件或者迭代次数达到一定次数。

层与层之间为全连接,同一层之间没有连接。结构模型如下图所示。

        使用的传递函数sigmoid可微的特性使他可以使用梯度下降法。所以,在隐层函数中使用sigmoid函数作为传递函数,在输出层采用线性函数作为传递函数。

输入向量、隐层输出向量、最终输出向量、期望输出向量:

X=(x1,x2,x3……xn),其中图中x0是为隐层神经元引入阈值设置的;

Y=(y1,y2,y3……ym),其中图中y0是为输出神经元引入阈值设置的;

O=(o1,o2,o3……ol)

D=(d1,d2,d3……dl)

输出层的输入是隐层的输出,隐层的输入是输入层的输出,计算方法和单层感知器的计算方法一样。

单极性Sigmoid函数:

双极性sigmoid函数:

二、BP神经网络的学习算法

        标准BP神经网络沿着误差性能函数梯度的反方向修改权值,原理与LMS算法比较类似,属于最速下降法。此外还有以下改进算法,如动量最速下降法,拟牛顿法等。

    最速下降法又称为梯度下降法。LMS算法就是最小均方误差算法。LMS算法体现了纠错原则,与梯度下降法本质上没有区别,梯度下降法可以求目标函数的极小值,如果将目标函数取为均方误差,就得到了LMS算法。

       梯度下降法原理:对于实值函数F(x),如果函数在某点x0处有定义且可微,则函数在该点处沿着梯度相反的方向下降最快,因此,使用梯度下降法时,应首先计算函数在某点处的梯度,再沿着梯度的反方向以一定的步长调整自变量的值。其中实值函数指的是传递函数,自变量x指的是上一层权值和输入值的点积作为的输出值。

        网络误差定义:

   

   

三层BP网络算法推导:

1、变量定义

网络的实际输出:

  1. 信号正向传播

  1. 误差信号反向传播

首先误差反向传播首先经过输出层,所以首先调整隐含层和输出层之间的权值。

然后对输入神经元和隐层神经元的误差进行调整。

权值矩阵的调整可以总结为:

    权值调整量det(w)=学习率*局部梯度*上一层输出信号。

BP神经网络的复杂之处在于隐层输入层、隐层和隐层之间的权值调整时,局部梯度的计算需要用到上一步计算的结果,前一层的局部梯度是后一层局部梯度的加权和。

训练方式:

  1. 串行方式:网络每获得一个新样本,就计算一次误差并更新权值,直到样本输入完毕。

  2. 批量方式:网络获得所有的训练样本,计算所有样本均方误差的和作为总误差;

在串行运行方式中,每个样本依次输入,需要的存储空间更少,训练样本的选择是随机的,可以降低网络陷入局部最优的可能性。

批量学习方式比串行方式更容易实现并行化。由于所有样本同时参加运算,因此批量方式的学习速度往往远优于串行方式。

BP神经网络的优点:

  1. 非线性映射能力
  2. 泛化能力  
  3. 容错能力  允许输入样本中带有较大误差甚至个别错误。反应正确规律的知识来自全体样本,个别样本中的误差不能左右对权矩阵的调整。

BP神经网络的局限性:

    梯度下降法的缺陷:

  1. 目标函数必须可微;
  2. 如果一片区域比较平坦会花费较多时间进行训练;
  3. 可能会陷入局部极小值,而没有到达全局最小值;(求全局极小值的目的是为了实现误差的最小值)

BP神经网络的缺陷:

  1. 需要的参数过多,而且参数的选择没有有效的方法。确定一个BP神经网络需要知道:网络的层数、每一层神经元的个数和权值。权值可以通过学习得到,如果,隐层神经元数量太多会引起过学习,如果隐层神经元个数太少会引起欠学习。此外学习率的选择也是需要考虑。目前来说,对于参数的确定缺少一个简单有效的方法,所以导致算法很不稳定;
  2. 属于监督学习,对于样本有较大依赖性,网络学习的逼近和推广能力与样本有很大关系,如果样本集合代表性差,样本矛盾多,存在冗余样本,网络就很难达到预期的性能;
  3. 由于权值是随机给定的,所以BP神经网络具有不可重现性;

梯度下降法(最速下降法的改进):

    针对算法的不足出现了几种BP算法的改进。

  1. 动量法

动量法是在标准BP算法的权值更新阶段引入动量因子α(0<α<1),使权值修正具有一定惯性,可以看出,在原有的权值调整公式中,加入了动量因子以及上一次的权值改变量。加入的动量项表示本次权值的更新方向和幅度,不但与本次计算所得的梯度有关,还与上一次更新的方向和幅度有关。动量项反映了以前积累的调整经验,对于t时刻的调整起到了阻尼作用。当误差曲面出现骤然起伏时,可减小震荡趋势,提高训练速度。

  1. 调节学习率法

在平缓区域希望学习率大一点减小迭代次数,在坑凹处希望学习率小一点,较小震荡。所以,为了加速收敛过程,希望自适应改变学习率,在该大的时候大,在该小的时候小。

学习率可变的BP算法是通过观察误差的增减来判断的,当误差以减小的方式区域目标时,说明修正方向是正确的,可以增加学习率;当误差增加超过一定范围时,说明前一步修正进行的不正确,应减小步长,并撤销前一步修正过程。学习率的增减通过乘以一个增量/减量因子实现:

  1. 引入陡度因子。

BP神经网络的设计:

   BP神经网络采用有监督学习。解决具体问题时,首先需要一个训练集。然后神经网络的设计主要包括网络层数、输入层节点数、隐层节点数、输出层节点数、以及传输函数、训练方法、训练参数。

(一)输入输出数据的预处理:尺度变换。尺度变化也称为归一化或者标准化,是指变换处理将网络的输入、输出数据限制在[0,1]或者[-1,1]区间内。进行变换的原因是,(1)网络的各个输入数据常常具有不同的物理意义和不同的量纲。尺度变换使所有分量都在一个区间内变化,从而使网络训练一开始就给各输入分量以同等重要的地位;(2)BP神经网络神经元均采用sigmoid函数,变换后可防止因净输入的绝对值过大而使神经元输出饱和,继而使权值调整进入误差曲面的平坦区;(3)sigmoid函数输出在区间[0,1]或者[-1,1]内,如果不对期望输出数据进行变换处理,势必使数值大的分量绝对误差大,数值小的分量绝对误差小。

(二)神经网络结构设计

1)网络层数  BP神经网络最多只需要俩个隐层,在设计的时候一般先只考虑设一个隐层,当一个隐层的节点数很多但是依然不能改善网络情况时,才考虑增加一个隐层。经验表明,如果在第一个隐层较多的节点数,第二个隐层较少的节点数,可以改善网络性能。

2)输入层节点数  输入层节点数取决于输入向量的维数。应用神经网络解决实际问题时,首先应从问题中提炼出一个抽象模型。如果输入的是64*64的图像,则输入向量应为图像中左右的像素形成的4096维向量。如果待解决的问题是二院函数拟合,则输入向量应为二维向量。

3)隐层节点数设计  隐含节点数对BP神经网络的性能有很大影响,一般较多的隐含层节点数可以带来更好的性能,但是导致训练时间过长。通常是采用经验公式给出估计值:

4)输出层神经元个数  

5)传递函数的选择  一般隐层选择sigmoid函数,输出层选择线性函数。如果也使用sigmoid函数,则输出值将会被限制在(0,1)或者(-1,1)之间。

6)训练方法的选择  一般来说,对于包含数百个权值的函数逼近网络,使用LM算法收敛速度最快,均方误差也小,但是LM算法对于模式识别相关问题的处理能力较弱,且需要较大的存储空间。对于模式识别问题,使用RPROP算法能收到较好的效果。SCG算法对于模式识别和函数逼近都有较好的性能表现。串行方式需要更小的存储空间,且输入样本具有一定随机性,可以避免陷入局部最优。批量方式的误差收敛条件非常简单,训练速度快。

三、python实现加动量法改进

# -*- coding: utf-8 -*-
"""
Created on Mon Oct  1 22:15:54 2018@author: Heisenberg
"""
import numpy as np
import math
import random
import string
import matplotlib as mpl
import matplotlib.pyplot as plt#random.seed(0)  #当我们设置相同的seed,每次生成的随机数相同。如果不设置seed,则每次会生成不同的随机数#参考https://blog.csdn.net/jiangjiang_jian/article/details/79031788#生成区间[a,b]内的随机数
def random_number(a,b):return (b-a)*random.random()+a#生成一个矩阵,大小为m*n,并且设置默认零矩阵
def makematrix(m, n, fill=0.0):a = []for i in range(m):a.append([fill]*n)return a#函数sigmoid(),这里采用tanh,因为看起来要比标准的sigmoid函数好看
def sigmoid(x):return math.tanh(x)#函数sigmoid的派生函数
def derived_sigmoid(x):return 1.0 - x**2#构造三层BP网络架构
class BPNN:def __init__(self, num_in, num_hidden, num_out):#输入层,隐藏层,输出层的节点数self.num_in = num_in + 1  #增加一个偏置结点self.num_hidden = num_hidden + 1   #增加一个偏置结点self.num_out = num_out#激活神经网络的所有节点(向量)self.active_in = [1.0]*self.num_inself.active_hidden = [1.0]*self.num_hiddenself.active_out = [1.0]*self.num_out#创建权重矩阵self.wight_in = makematrix(self.num_in, self.num_hidden)self.wight_out = makematrix(self.num_hidden, self.num_out)#对权值矩阵赋初值for i in range(self.num_in):for j in range(self.num_hidden):self.wight_in[i][j] = random_number(-0.2, 0.2)for i in range(self.num_hidden):for j in range(self.num_out):self.wight_out[i][j] = random_number(-0.2, 0.2)#最后建立动量因子(矩阵)self.ci = makematrix(self.num_in, self.num_hidden)self.co = makematrix(self.num_hidden, self.num_out)        #信号正向传播def update(self, inputs):if len(inputs) != self.num_in-1:raise ValueError('与输入层节点数不符')#数据输入输入层for i in range(self.num_in - 1):#self.active_in[i] = sigmoid(inputs[i])  #或者先在输入层进行数据处理self.active_in[i] = inputs[i]  #active_in[]是输入数据的矩阵#数据在隐藏层的处理for i in range(self.num_hidden - 1):sum = 0.0for j in range(self.num_in):sum = sum + self.active_in[i] * self.wight_in[j][i]self.active_hidden[i] = sigmoid(sum)   #active_hidden[]是处理完输入数据之后存储,作为输出层的输入数据#数据在输出层的处理for i in range(self.num_out):sum = 0.0for j in range(self.num_hidden):sum = sum + self.active_hidden[j]*self.wight_out[j][i]self.active_out[i] = sigmoid(sum)   #与上同理return self.active_out[:]#误差反向传播def errorbackpropagate(self, targets, lr, m):   #lr是学习率, m是动量因子if len(targets) != self.num_out:raise ValueError('与输出层节点数不符!')#首先计算输出层的误差out_deltas = [0.0]*self.num_outfor i in range(self.num_out):error = targets[i] - self.active_out[i]out_deltas[i] = derived_sigmoid(self.active_out[i])*error#然后计算隐藏层误差hidden_deltas = [0.0]*self.num_hiddenfor i in range(self.num_hidden):error = 0.0for j in range(self.num_out):error = error + out_deltas[j]* self.wight_out[i][j]hidden_deltas[i] = derived_sigmoid(self.active_hidden[i])*error#首先更新输出层权值for i in range(self.num_hidden):for j in range(self.num_out):change = out_deltas[j]*self.active_hidden[i]self.wight_out[i][j] = self.wight_out[i][j] + lr*change + m*self.co[i][j]self.co[i][j] = change#然后更新输入层权值for i in range(self.num_in):for i in range(self.num_hidden):change = hidden_deltas[j]*self.active_in[i]self.wight_in[i][j] = self.wight_in[i][j] + lr*change + m* self.ci[i][j]self.ci[i][j] = change#计算总误差error = 0.0for i in range(len(targets)):error = error + 0.5*(targets[i] - self.active_out[i])**2return error#测试def test(self, patterns):for i in patterns:print(i[0], '->', self.update(i[0]))#权重def weights(self):print("输入层权重")for i in range(self.num_in):print(self.wight_in[i])print("输出层权重")for i in range(self.num_hidden):print(self.wight_out[i])def train(self, pattern, itera=100000, lr = 0.1, m=0.1):for i in range(itera):error = 0.0for j in pattern:inputs = j[0]targets = j[1]self.update(inputs)error = error + self.errorbackpropagate(targets, lr, m)if i % 100 == 0:print('误差 %-.5f' % error)#实例
def demo():patt = [[[1,2,5],[0]],[[1,3,4],[1]],[[1,6,2],[1]],[[1,5,1],[0]],[[1,8,4],[1]]]#创建神经网络,3个输入节点,3个隐藏层节点,1个输出层节点n = BPNN(3, 3, 1)#训练神经网络n.train(patt)#测试神经网络n.test(patt)#查阅权重值n.weights()if __name__ == '__main__':demo()

计算结果:

任何程序错误,以及技术疑问或需要解答的,请添加

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM(四)垃圾回收的实现算法和执行细节

全文共 1890 个字&#xff0c;读完大约需要 6 分钟。 上一篇我们讲了垃圾标记的一些实现细节和经典算法&#xff0c;而本文将系统的讲解一下垃圾回收的经典算法&#xff0c;和Hotspot虚拟机执行垃圾回收的一些实现细节&#xff0c;比如安全点和安全区域等。 因为各个平台的虚拟…

python-cx_oracle报错“DatabaseError: DPI-1047: 64-bit Oracle Client library cannot be loaded: “

问题的主要原因是python-cx_oracle加载的是32位的instantclient-basic&#xff0c;我们需要让他读到64位的。 弄清版本&#xff0c;最重要&#xff01;&#xff01;&#xff01; 首先安装配置时&#xff0c;必须把握一个点&#xff0c;就是版本一致&#xff01;包括&#xff1…

JVM(五)垃圾回收器的前世今生

全文共 2195 个字&#xff0c;读完大约需要 8 分钟。 如果垃圾回收的算法属于内存回收的方法论的话&#xff0c;那本文讨论的垃圾回收器就属于内存回收的具体实现。 因为不同的厂商&#xff08;IBM、Oracle&#xff09;&#xff0c;实现的垃圾回收器各不相同&#xff0c;而本文…

【SlowFast复现】SlowFast Networks for Video Recognition复现代码 使用自己的视频进行demo检测

目录 一&#xff0c;准备 1.1代码1.2 环境准备1.3 搭建镜像1.4 配置slowfast环境1.5 ava.json1.6 SLOWFAST_32x2_R101_50_50.yaml1.7 SLOWFAST_32x2_R101_50_50 .pkl二&#xff0c;代码运行三 错误解决复现过程视频&#xff1a;B站复现视频复现结果 一&#xff0c;准备 1.1代…

MySQL学生向笔记以及使用过程问题记录(内含8.0.34安装教程

MySQL 只会写代码 基本码农 要学好数据库&#xff0c;操作系统&#xff0c;数据结构与算法 不错的程序员 离散数学、数字电路、体系结构、编译原理。实战经验&#xff0c; 高级程序员 去IOE&#xff1a;去掉IBM的小型机、Oracle数据库、EMC存储设备&#xff0c;代之以自己在开源…

程序员专属精品简历合集—面试必备

听说你最近打算换工作&#xff1f;听说你和好工作之间&#xff0c;只差一个漂亮的简历模板&#xff1f;人们常说“金三银四”&#xff0c;一年之际在于春。不管你是主动离职&#xff0c;还是被动“被离职”&#xff08;稳住&#xff0c;我们能赢&#xff01;&#xff09;&#…

ubuntu20.10下wine安装微信

1.unbuntu20.04下安装wine sudo apt-get install wine2.微信官网http://short.weixin.qq.com/下载window系统微信软件 3.在wine中安装微信 在WeChatSetup.exe文件中打开终端输入&#xff1a; wine WeChatSetup.exe

【faster rcnn 实现via的自动框人】使用detectron2中faster rcnn 算法生成人的坐标,将坐标导入via(VGG Image Annotator)中,实现自动框选出人的区域

前言 B站讲解视频 我的研究生毕业论文方向就是时空行为检测&#xff0c;所以&#xff0c;slowfast和ava是我重点搞的&#xff0c;我的博客主页也有很多这些相关内容。 终于&#xff0c;到了标注数据这一块了&#xff0c;为了更简单的标注数据&#xff0c;我要做的这部分的数据…

程序员精美简历Top榜—面试必备

听说你最近打算换工作&#xff1f;听说你和好工作之间&#xff0c;只差一个漂亮的简历模板&#xff1f; 不管是主动离职&#xff0c;还是“被离职”&#xff08;稳住&#xff0c;我们能赢&#xff01;&#xff09;&#xff0c;趁着大好时光和对新年的憧憬&#xff0c;再找一个…

失败创业者的告白:初创团队应有一位绝对领导者

做了两年的项目失败了&#xff0c;我们的项目做的是数码3C的优惠信息&#xff0c;我是一个80后&#xff0c;小硕一枚;我们的1号创始人是90后&#xff0c;有激情、有梦想;在十八岁那年带上他的梦想千里北上&#xff0c;找我们的开复老师指点一二;但那时&#xff0c;开复老师正为…

【ffmpeg裁剪视频faster rcnn自动检测 via】全自动实现ffmpeg将视频切割为图片帧,再使用faster rcnn将图片中的人检测出来,最后将检测结果转化为via可识别的csv格式

目录 前言一&#xff0c;ffmpeg 自动裁剪 1.1 目录结构1.2 cutVideoToImage.sh1.2 myVideo1.3 myVideo15mins1.5 myFrames1.6 运行1.7 查看结果二&#xff0c;detectron2中的faster rcnn检测 2.1 img2.2 myvia.py2.3 运行2.4 结果展示三&#xff0c;via标注 3.1 csv文件修改&am…

ubuntu20.10(Linux)在wine下用pyinstaller打包python程序在window系统运行 交叉编译

1.安装wine 在终端中输入&#xff1a; sudo apt-get install wine2.安装pip 在https://pypi.org/project/pip/#files下载pip-21.0.tar.gz&#xff0c;在压缩包上右键提取到此处&#xff0c;打开解压的文件夹pip-21.0 在该文件夹中打开终端安装pip-21.0.tar.gz&#xff1a; wi…

JVM(六)为什么新生代有两个Survivor分区?

本文会使用排除法的手段&#xff0c;来讲解新生代的区域划分&#xff0c;从而让读者能够更清晰的理解分代回收器的原理&#xff0c;在开始之前我们先来整体认识一下分代收集器。 分代收集器会把内存空间分为&#xff1a;老生代和新生代两个区域&#xff0c;而新生代又会分为&a…

【slowfast复现 训练】训练过程 制作ava数据集 复现 SlowFast Networks for Video Recognition 训练 train

目录 前言一&#xff0c;ava相关文件准备 1.1 空间准备&#xff08;500G&#xff09;1.2 整体ava文件结构1.3 frames文件1.4 frame_lists 文件1.5 annotations 文件二&#xff0c;预训练模型三&#xff0c;配置文件 3.1 创建新的yaml文件3.2 yaml文件解释四&#xff0c;训练前言…

Qt6 在线安装图文步骤

说明&#xff1a; Qt 自从5.15版本开始&#xff0c;对非商业版本&#xff0c;也就是开源版本&#xff0c;不提供已经制作好的离线exe安装包&#xff0c;自这个版本开始你只有两种选择&#xff1a; 1、编译源码 例如qt-everywhere-src-5.15.2.zip 编译步骤繁琐&#xff0c;需严…

【slowfast 减少ava数据集】将ava数据集缩小到2个,对数据集做训练,然后进行检测,为训练自己的数据集做准备

目录 前言一&#xff0c;数据文件结构 1.1 myava1.2 annotations1.3 annotations文件处理1.4 frame_lists1.5 frames二&#xff0c;预训练模型四&#xff0c;配置文件 4.1 创建新的yaml文件4.2 yaml文件解释五&#xff0c;训练六&#xff0c;结果查看前言 b站讲解 ava的数据集…

JAVA反射系列之Field,java.lang.reflect.Field使用获取方法。

2019独角兽企业重金招聘Python工程师标准>>> 首先必须明一点 Field类主要是用来辅助获取和操作类的属性的&#xff01; 1.怎么通过反射获取类的属性 先来看JDK提供的方法有如下几种&#xff1a; a)Class.getDeclaredField(String name); 返回一个 Field 对象&#x…

Python3自带HTTP文件传输服务(局域网文件共享)

一行命令搭建一个基于python3的http文件传输服务 WIN10系统下&#xff0c;打开打算要分享传输的文件夹&#xff08;文件夹内存放分享的文件&#xff0c;建议以压缩包形式存放&#xff09;&#xff0c;shift鼠标右键&#xff0c;出现如下图&#xff0c;选择“在此处打开Powershe…

90% 的人都会答错的面试题 == 和 equals 的区别

和 equals 的区别是什么&#xff1f; 解读对于基本类型和引用类型&#xff0c; 的作用效果是不同的&#xff0c;如下所示&#xff1a;基本类型&#xff1a;比较的是值是否相同&#xff1b;引用类型&#xff1a;比较的是引用是否相同&#xff1b;代码示例&#xff1a;String x …

【slowfast 训练自己的数据集】自定义动作,制作自己的数据集,使用预训练模型进行训练,并检测其结果

目录 前言一&#xff0c;视频的处理 1.1 视频准备1.2 切割视频为图片1.3 使用faster rcnn自动框人1.4 via标注图片二&#xff0c;数据集文件 2.1 数据集文件总览2.2 annotations 2.2.1 ava_train_v2.2.csv2.2.2 ava_val_v2.2.csv2.2.3 ava_val_excluded_timestamps_v2.2.csv2.…