BP算法程序实现
- 格式:doc
- 大小:6.15 MB
- 文档页数:20
BP算法python实现0-9数字识别,NMIST数据的识别。
具体代码包括NMIST见中。
参考资料是TOM的机器学习BP那⼀章。
# coding:utf-8# 没考虑⼤⼩端import structimport numpydef loadImages(filename):try:f = open(filename,'rb')except Exception as instance:print type(instance)exit()allImage = []bins = f.read()index = 0magicNum,imageNum,rowNum,colNum = struct.unpack_from('>IIII',bins,index)index = index + struct.calcsize('>IIII')assert 2051 == magicNum,'dataset damaged | little endian'for ct in xrange(imageNum):allImage.append(struct.unpack_from('>784B',bins,index))index = index + struct.calcsize('>784B')return numpy.array(allImage,dtype='float32')def loadLabels(filename):try:f = open(filename,'rb')except Exception as instance:print type(instance)exit()allLabels = []bins = f.read()index = 0magicNum,labelNum = struct.unpack_from('>II',bins,index)index = index + struct.calcsize('>II')assert 2049 == magicNum,'dataset damaged | little endian'for ct in xrange(labelNum):allLabels.append(struct.unpack_from('B',bins,index))index = index + struct.calcsize('B')return numpy.array(allLabels,dtype='float32')if'__main__' == __name__:images = loadImages('t10k-images.idx3-ubyte')labels = loadLabels('t10k-labels.idx1-ubyte')import matplotlib.pyplot as pltfor x in range(3):plt.figure()shown = images[x].reshape(28,28)# shown 28*28 numpy matrixplt.imshow(shown,cmap='gray')plt.title(str(labels[x]))plt.show()读取NMIST# -*- coding: utf-8 -*-import dataLoadimport numpy as npimport sysimport warningsdef bp(trainSet,eta=0.01,nin=None,nhid=None,nout=None,iterNum = 10): '''[(instance,label),((784,1)array,(10,1)array)……]'''Wkh = (np.random.rand(nout,nhid)-0.5) / 10.0Whi = (np.random.rand(nhid,nin )-0.5) / 10.0iteration = 0er = 1'''iteration'''while iteration < iterNum and er > 0.04:print'iteration=',iterationer = testAnn((Whi,Wkh))iteration += 1for (x,label) in trainSet:# 最⼤最⼩归⼀化x = (x - x.min())/x.max()-x.min()#前向neth = np.dot(Whi,x) # nhid*nin nin*1 -> nhid*1oh = sigmoid(neth) # nhid*1netk = np.dot(Wkh,oh) #nout*nhid nhid*1 -> nout*1ok = sigmoid(netk) # nout*1#求误差dk = ok*(1-ok)*(label-ok)dh = oh*(1-oh)*np.dot(Wkh.T,dk) #(nhid,1) = (nout,nhid).T * (nout,1) #更新权值矩阵Wkh = Wkh + eta * np.dot(dk,oh.T) #nout*nhid + nout*1*1*hidWhi = Whi + eta * np.dot(dh,x.T) #nhid*nin + nhid*1*1*ninprint'iteration over'return Wkh,Whidef testAnn(model):err = 0for i in range(len(testLabels)):res = fit(model,testImages[i].reshape(784,1))if i > 9990:print'\t ',int(testLabels[i][0]),'was recognized as',res[1]if testLabels[i][0] != res[1]:err += 1errorRate = float(err)/float(len(testLabels))print'error rate',errorRate,'\n'return errorRatedef fit(model,Image):Whi,Wkh = modelok = list(sigmoid(sigmoid(Image.T.dot(Whi.T)).dot(Wkh.T))[0])return ok,ok.index(max(ok))def sigmoid(y):# 讨厌的溢出警告warnings.filterwarnings("ignore")return 1/(1+np.exp(-y))if'__main__' == __name__:np.random.seed(207)trainImages = dataLoad.loadImages('train-images.idx3-ubyte')trainLabels = dataLoad.loadLabels('train-labels.idx1-ubyte')testImages = dataLoad.loadImages('t10k-images.idx3-ubyte')testLabels = dataLoad.loadLabels('t10k-labels.idx1-ubyte')dataSet = []for i in range(len(trainLabels)):tmp = np.zeros((10,1),dtype='float32')tmp[int(trainLabels[i]),0] = 1dataSet.append((trainImages[i].reshape(784,1),tmp))bp(trainSet=dataSet,eta=0.05,nin=784,nhid=20,nout=10,iterNum=20)。
神经⽹络(BP)算法Python实现及应⽤本⽂实例为⼤家分享了Python实现神经⽹络算法及应⽤的具体代码,供⼤家参考,具体内容如下⾸先⽤Python实现简单地神经⽹络算法:import numpy as np# 定义tanh函数def tanh(x):return np.tanh(x)# tanh函数的导数def tan_deriv(x):return 1.0 - np.tanh(x) * np.tan(x)# sigmoid函数def logistic(x):return 1 / (1 + np.exp(-x))# sigmoid函数的导数def logistic_derivative(x):return logistic(x) * (1 - logistic(x))class NeuralNetwork:def __init__(self, layers, activation='tanh'):"""神经⽹络算法构造函数:param layers: 神经元层数:param activation: 使⽤的函数(默认tanh函数):return:none"""if activation == 'logistic':self.activation = logisticself.activation_deriv = logistic_derivativeelif activation == 'tanh':self.activation = tanhself.activation_deriv = tan_deriv# 权重列表self.weights = []# 初始化权重(随机)for i in range(1, len(layers) - 1):self.weights.append((2 * np.random.random((layers[i - 1] + 1, layers[i] + 1)) - 1) * 0.25)self.weights.append((2 * np.random.random((layers[i] + 1, layers[i + 1])) - 1) * 0.25)def fit(self, X, y, learning_rate=0.2, epochs=10000):"""训练神经⽹络:param X: 数据集(通常是⼆维):param y: 分类标记:param learning_rate: 学习率(默认0.2):param epochs: 训练次数(最⼤循环次数,默认10000):return: none"""# 确保数据集是⼆维的X = np.atleast_2d(X)temp = np.ones([X.shape[0], X.shape[1] + 1])temp[:, 0: -1] = XX = tempy = np.array(y)for k in range(epochs):# 随机抽取X的⼀⾏i = np.random.randint(X.shape[0])# ⽤随机抽取的这⼀组数据对神经⽹络更新a = [X[i]]# 正向更新for l in range(len(self.weights)):a.append(self.activation(np.dot(a[l], self.weights[l])))error = y[i] - a[-1]deltas = [error * self.activation_deriv(a[-1])]# 反向更新for l in range(len(a) - 2, 0, -1):deltas.append(deltas[-1].dot(self.weights[l].T) * self.activation_deriv(a[l])) deltas.reverse()for i in range(len(self.weights)):layer = np.atleast_2d(a[i])delta = np.atleast_2d(deltas[i])self.weights[i] += learning_rate * layer.T.dot(delta)def predict(self, x):x = np.array(x)temp = np.ones(x.shape[0] + 1)temp[0:-1] = xa = tempfor l in range(0, len(self.weights)):a = self.activation(np.dot(a, self.weights[l]))return a使⽤⾃⼰定义的神经⽹络算法实现⼀些简单的功能:⼩案例:X: Y0 0 00 1 11 0 11 1 0from NN.NeuralNetwork import NeuralNetworkimport numpy as npnn = NeuralNetwork([2, 2, 1], 'tanh')temp = [[0, 0], [0, 1], [1, 0], [1, 1]]X = np.array(temp)y = np.array([0, 1, 1, 0])nn.fit(X, y)for i in temp:print(i, nn.predict(i))发现结果基本机制,⽆限接近0或者⽆限接近1第⼆个例⼦:识别图⽚中的数字导⼊数据:from sklearn.datasets import load_digitsimport pylab as pldigits = load_digits()print(digits.data.shape)pl.gray()pl.matshow(digits.images[0])pl.show()观察下:⼤⼩:(1797, 64)数字0接下来的代码是识别它们:import numpy as npfrom sklearn.datasets import load_digitsfrom sklearn.metrics import confusion_matrix, classification_report from sklearn.preprocessing import LabelBinarizerfrom NN.NeuralNetwork import NeuralNetworkfrom sklearn.cross_validation import train_test_split# 加载数据集digits = load_digits()X = digits.datay = digits.target# 处理数据,使得数据处于0,1之间,满⾜神经⽹络算法的要求X -= X.min()X /= X.max()# 层数:# 输出层10个数字# 输⼊层64因为图⽚是8*8的,64像素# 隐藏层假设100nn = NeuralNetwork([64, 100, 10], 'logistic')# 分隔训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y)# 转化成sklearn需要的⼆维数据类型labels_train = LabelBinarizer().fit_transform(y_train)labels_test = LabelBinarizer().fit_transform(y_test)print("start fitting")# 训练3000次nn.fit(X_train, labels_train, epochs=3000)predictions = []for i in range(X_test.shape[0]):o = nn.predict(X_test[i])# np.argmax:第⼏个数对应最⼤概率值predictions.append(np.argmax(o))# 打印预测相关信息print(confusion_matrix(y_test, predictions))print(classification_report(y_test, predictions))结果:矩阵对⾓线代表预测正确的数量,发现正确率很多这张表更直观地显⽰出预测正确率:共450个案例,成功率94%以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
人工神经网络是一种模仿人脑结构及其功能的信息处理系统,能提高人们对信息处理的智能化水平。
它是一门新兴的边缘和交叉学科,它在理论、模型、算法等方面比起以前有了较大的发展,但至今无根本性的突破,还有很多空白点需要努力探索和研究。
1人工神经网络研究背景神经网络的研究包括神经网络基本理论、网络学习算法、网络模型以及网络应用等方面。
其中比较热门的一个课题就是神经网络学习算法的研究。
近年来己研究出许多与神经网络模型相对应的神经网络学习算法,这些算法大致可以分为三类:有监督学习、无监督学习和增强学习。
在理论上和实际应用中都比较成熟的算法有以下三种:(1) 误差反向传播算法(Back Propagation,简称BP 算法);(2) 模拟退火算法;(3) 竞争学习算法。
目前为止,在训练多层前向神经网络的算法中,BP 算法是最有影响的算法之一。
但这种算法存在不少缺点,诸如收敛速度比较慢,或者只求得了局部极小点等等。
因此,近年来,国外许多专家对网络算法进行深入研究,提出了许多改进的方法。
主要有:(1) 增加动量法:在网络权值的调整公式中增加一动量项,该动量项对某一时刻的调整起阻尼作用。
它可以在误差曲面出现骤然起伏时,减小振荡的趋势,提高网络训练速度;(2) 自适应调节学习率:在训练中自适应地改变学习率,使其该大时增大,该小时减小。
使用动态学习率,从而加快算法的收敛速度;(3) 引入陡度因子:为了提高BP 算法的收敛速度,在权值调整进入误差曲面的平坦区时,引入陡度因子,设法压缩神经元的净输入,使权值调整脱离平坦区。
此外,很多国内的学者也做了不少有关网络算法改进方面的研究,并把改进的算法运用到实际中,取得了一定的成果:(1) 王晓敏等提出了一种基于改进的差分进化算法,利用差分进化算法的全局寻优能力,能够快速地得到BP 神经网络的权值,提高算法的速度;(2) 董国君等提出了一种基于随机退火机制的竞争层神经网络学习算法,该算法将竞争层神经网络的串行迭代模式改为随机优化模式,通过采用退火技术避免网络收敛到能量函数的局部极小点,从而得到全局最优值;(3) 赵青提出一种分层遗传算法与BP 算法相结合的前馈神经网络学习算法。
BP算法程序实现BP(Back Propagation)神经网络是一种常见的人工神经网络模型,是一种监督学习算法。
在BP算法中,神经网络的参数通过反向传播的方式得到更新,以最小化损失函数。
BP神经网络的实现主要分为前向传播和反向传播两个步骤。
首先,我们需要定义BP神经网络的结构。
一个典型的BP神经网络包括输入层、隐藏层和输出层。
输入层接收原始数据,隐藏层进行特征提取和转换,输出层进行最终的预测。
在实现BP神经网络时,我们首先需要进行初始化。
初始化可以为神经网络的权重和偏置添加一些随机的初始值。
这里我们使用numpy库来处理矩阵运算。
前向传播的过程实际上就是将输入数据通过神经网络的每一层,直到输出层。
在每一层中,我们将对应权重和输入数据进行点乘运算,并加上偏置项,然后通过一个激活函数进行非线性转换。
这里我们可以选择sigmoid函数作为激活函数。
在反向传播中,我们根据损失函数对权重和偏置进行调整。
首先,我们计算输出误差,即预测值与真实值之间的差异。
然后,我们根据链式法则来计算每一层的误差,并将误差传递回前一层。
根据误差和激活函数的导数,我们可以计算每个权重和偏置的更新量,然后使用梯度下降法对权重和偏置进行更新。
实现BP算法的程序如下:```pythonimport numpy as npclass NeuralNetwork:def __init__(self, layers):yers = layersself.weights = [np.random.randn(y, x) for x, y inzip(layers[:-1], layers[1:])]self.biases = [np.random.randn(y, 1) for y in layers[1:]] def forward(self, x):a = np.array(x).reshape(-1, 1)for w, b in zip(self.weights, self.biases):z = np.dot(w, a) + ba = self.sigmoid(z)return adef backward(self, x, y, lr=0.01):a = np.array(x).reshape(-1, 1)targets = np.array(y).reshape(-1, 1)# forward passactivations = [a]zs = []for w, b in zip(self.weights, self.biases):z = np.dot(w, a) + bzs.append(z)a = self.sigmoid(z)activations.append(a)# backward passdeltas = [self.loss_derivative(activations[-1], targets) * self.sigmoid_derivative(zs[-1])]for l in range(2, len(yers)):z = zs[-l]sp = self.sigmoid_derivative(z)deltas.append(np.dot(self.weights[-l + 1].T, deltas[-1]) * sp)deltas.reverse# update weights and biasesfor l in range(len(yers) - 1):self.weights[l] += -lr * np.dot(deltas[l], activations[l].T) self.biases[l] += -lr * deltas[l]def sigmoid(x):return 1 / (1 + np.exp(-x))def sigmoid_derivative(x):return NeuralNetwork.sigmoid(x) * (1 -NeuralNetwork.sigmoid(x))def loss_derivative(y_pred, y_true):return y_pred - y_true```上述代码中,首先我们定义一个NeuralNetwork类,包含两个主要方法:forward(和backward(。
package backp;import java.*;import java.awt.*;import java.io.*;import java.util.Scanner;//by realmagicianimport org.omg.CORBA.portable.InputStream;public class backpro {public static void main(String args[]){String filename=new String("delta.in");try {FileInputStream fileInputStream=new FileInputStream(filename);Scanner sinScanner=new Scanner(fileInputStream);int attN,hidN,outN,samN;attN=sinScanner.nextInt();outN=sinScanner.nextInt();hidN=sinScanner.nextInt();samN=sinScanner.nextInt();//System.out.println(attN+" "+outN+" "+hidN+" "+samN);double samin[][]=new double[samN][attN];double samout[][]=new double[samN][outN];for(int i=0;i<samN;++i){for(int j=0;j<attN;++j){samin[i][j]=sinScanner.nextDouble();}for(int j=0;j<outN;++j){samout[i][j]=sinScanner.nextDouble();}}int times=10000;double rate=0.5;BP2 bp2=new BP2(attN,outN,hidN,samN,times,rate);bp2.train(samin, samout);for(int i=0;i<hidN;++i){for(int j=0;j<attN;++j)System.out.print(bp2.dw1[i][j]+" ");System.out.println();}for(int i=0;i<outN;++i){for(int j=0;j<hidN;++j)System.out.print(bp2.dw2[i][j]+" ");System.out.println();}while(true){double testout[]=new double[outN];double testin[]=new double[attN];Scanner testinScanner=new Scanner(System.in);for(int i=0;i<attN;++i){testin[i]=testinScanner.nextDouble();}testout=bp2.getResault(testin);for(int i=0;i<outN;++i)System.out.print(testout[i]+" ");System.out.println(outN);}} catch (IOException e) {// TODO: handle exception}System.out.println("End");}}class BP2//包含一个隐含层的神经网络{double dw1[][],dw2[][];int hidN;//隐含层单元个数int samN;//学习样例个数int attN;//输入单元个数int outN;//输出单元个数int times;//迭代次数double rate;//学习速率boolean trained=false;//保证在得结果前,先训练BP2(int attN,int outN,int hidN,int samN,int times,double rate){this.attN=attN;this.outN=outN;this.hidN=hidN;this.samN=samN;dw1=new double[hidN][attN+1];//每行最后一个是阈值w0for(int i=0;i<hidN;++i)//每行代表所有输入到i隐藏单元的权值{for(int j=0;j<=attN;++j)dw1[i][j]=Math.random()/2;}dw2=new double[outN][hidN+1];//输出层权值,每行最后一个是阈值w0 for(int i=0;i<outN;++i)//每行代表所有隐藏单元到i输出单元的权值{for(int j=0;j<=hidN;++j)dw2[i][j]=Math.random()/2;}this.times=times;this.rate=rate;}public void train(double samin[][],double samout[][]){double dis=0;//总体误差int count=times;double temphid[]=new double[hidN];double tempout[]=new double[outN];double wcout[]=new double[outN];double wchid[]=new double[hidN];while((count--)>0)//迭代训练{dis=0;for(int i=0;i<samN;++i)//遍历每个样例samin[i]{for(int j=0;j<hidN;++j)//计算每个隐含层单元的结果{temphid[j]=0;for(int k=0;k<attN;++k)temphid[j]+=dw1[j][k]*samin[i][k];temphid[j]+=dw1[j][attN];//计算阈值产生的隐含层结果temphid[j]=1.0/(1+Math.exp(-temphid[j] ));}for(int j=0;j<outN;++j)//计算每个输出层单元的结果{tempout[j]=0;for(int k=0;k<hidN;++k)tempout[j]+=dw2[j][k]*temphid[k];tempout[j]+=dw2[j][hidN];//计算阈值产生的输出结果tempout[j]=1.0/(1+Math.exp( -tempout[j] ));}//计算每个输出单元的误差项for(int j=0;j<outN;++j){wcout[j]=tempout[j]*(1-tempout[j])*(samout[i][j]-tempout[j]);dis+=Math.pow((samout[i][j]-tempout[j]),2);}//计算每个隐藏单元的误差项for(int j=0;j<hidN;++j){double wche=0;for(int k=0;k<outN;++k)//计算输出项误差和{wche+=wcout[k]*dw2[k][j];}wchid[j]=temphid[j]*(1-temphid[j])*wche;}//改变输出层的权值for(int j=0;j<outN;++j){for(int k=0;k<hidN;++k){dw2[j][k]+=rate*wcout[j]*temphid[k];}dw2[j][hidN]=rate*wcout[j];}//改变隐含层的权值for(int j=0;j<hidN;++j){for(int k=0;k<attN;++k){dw1[j][k]+=rate*wchid[j]*samin[i][k];}dw1[j][attN]=rate*wchid[j];}}if(dis<0.003)break;}trained=true;}public double[] getResault(double samin[]){double temphid[]=new double[hidN];double tempout[]=new double[outN];if(trained==false)return null;for(int j=0;j<hidN;++j)//计算每个隐含层单元的结果{temphid[j]=0;for(int k=0;k<attN;++k)temphid[j]+=dw1[j][k]*samin[k];temphid[j]+=dw1[j][attN];//计算阈值产生的隐含层结果temphid[j]=1.0/(1+Math.exp(-temphid[j] ));}for(int j=0;j<outN;++j)//计算每个输出层单元的结果{tempout[j]=0;for(int k=0;k<hidN;++k)tempout[j]+=dw2[j][k]*temphid[k];tempout[j]+=dw2[j][hidN];//计算阈值产生的输出结果tempout[j]=1.0/(1+Math.exp( -tempout[j]));//System.out.print(tempout[j]+" ");}return tempout;}}。
/************************************************ Back Propagation Algorithm************************************************/ #include "stdio.h"#include "stdlib.h"#include "math.h"/************************************************ The Definition of User Data************************************************/ #define MAXINPUT 1#define MAXHIDE 3#define MAXOUTPUT 1#define MAX 1#define MIN -1#define T 100#define CA 4double a=0.8;double b=0.05;double k=0;double error=0;int t=0;double sout[MAXOUTPUT];double shide[MAXHIDE];double m=2;double howchange[MAXHIDE][MAXOUTPUT];double ihwchange[MAXINPUT][MAXHIDE];double CatalogueOut[CA][MAXOUTPUT];double CatalogueIn[CA][MAXINPUT];/************************************************ The Definition of Data Structure************************************************/ struct theBP{double input[MAXINPUT];double hide[MAXHIDE];double output[MAXOUTPUT];double ihw[MAXINPUT][MAXHIDE];double how[MAXHIDE][MAXOUTPUT];};struct theBP bpa;/************************************************ Definition of Prototype************************************************/ void WeightInitial();void InitialError();void InPutCatalogue();void CalculateOut(int k);void CalculateError(int k);void ReverseHideError();void CalculateChange();void CalculateNewWeight();void Test();void TestCalculateOut();void camain();void main(){WeightInitial();// InitialError();InPutCatalogue();//doint m=0;while(1){printf("请选择要进行的操作\n");printf("0----------------学习\n");printf("1----------------测试\n");printf("2----------------退出\n");scanf("%d",&m);switch(m){case 0:camain();break;case 1:Test();break;case 2:exit(0);}//while((error)>k);;}}void camain(){for(t=0;t<T;t++){for(int k=0;k<CA;k++){CalculateOut(k);CalculateError(k);ReverseHideError();CalculateChange();CalculateNewWeight();}for(k=0;k<CA;k++){CalculateOut(k);}}}/************************************************Function:initial the weight************************************************/void WeightInitial(){//产生输入层到隐藏层的权值for(int i=0;i<MAXINPUT;i++){for(int j=0;j<MAXHIDE;j++){bpa.ihw[i][j]=0.3;//((double)rand()/(double)(RAND_MAX))*(MAX-MIN)+MIN;}}//产生从隐藏层到输出层的权值for(i=0;i<MAXHIDE;i++){for(int j=0;j<MAXOUTPUT;j++){bpa.how[i][j]=0.2;//((double)rand()/(double)(RAND_MAX))*(MAX-MIN)+MIN;}}}/************************************************Function:input the Catalogue************************************************/void InPutCatalogue(){for(int k=0;k<CA;k++){printf("请输入第%d个样本的输入值:\n",k);for(int i=0;i<MAXINPUT;i++){scanf("%lf",&bpa.input[i]);CatalogueIn[k][i]=bpa.input[i];}printf("请输入第%d个样本的输出值:\n",k);for(i=0;i<MAXOUTPUT;i++){scanf("%lf",&CatalogueOut[k][i]);}}}/************************************************Function:calculate the out************************************************/void CalculateOut(int k){//计算隐藏层的输出for(int j=0;j<MAXHIDE;j++){double sum2=0;for(int i=0;i<MAXINPUT;i++){bpa.input[i]=CatalogueIn[k][i];sum2+=bpa.ihw[i][j]*bpa.input[i];//计算输入}bpa.hide[j]=1/(1+exp(-sum2));//计算输出}//计算每输出层个单元的输入和输出for(j=0;j<MAXOUTPUT;j++){double sum3=0;for(int i=0;i<MAXHIDE;i++){sum3+=bpa.how[i][j]*bpa.hide[i];//计算输入}bpa.output[j]=m*sum3;//计算输出bpa.output[j]=1/(1+exp(-sum3))printf("第%d个样本的最后输出%lf\n",k,bpa.output[j]);}}void TestCalculateOut(){//计算隐藏层的输出for(int j=0;j<MAXHIDE;j++){double sum1=0;for(int i=0;i<MAXINPUT;i++){sum1=sum1+bpa.ihw[i][j]*bpa.input[i];//计算输入}bpa.hide[j]=1/(1+exp(-sum1));//计算输出}//计算每输出层个单元的输入和输出for(j=0;j<MAXOUTPUT;j++){double sum2=0;for(int i=0;i<MAXHIDE;i++){sum2=sum2+bpa.how[i][j]*bpa.hide[i];//计算输入}bpa.output[j]=m*sum2;//计算输出bpa.output[j]=1/(1+exp(sum2))printf("最后输出%lf\n",bpa.output[j]);}}/************************************************Function:对输出层Calculate************************************************/void CalculateError(int k){double temp=0;error=0;for(int i=0;i<MAXOUTPUT;i++){temp=(CatalogueOut[k][i]-bpa.output[i])*(CatalogueOut[k][i]-bpa.output[i]);error=(0.5)*temp+error;}for(i=0;i<MAXOUTPUT;i++){sout[i]=(CatalogueOut[k][i]-bpa.output[i])*bpa.output[i]*(1-bpa.output[i]);}}/************************************************Function: 从后向前对隐藏层************************************************/void ReverseHideError(){for(int i=0;i<MAXHIDE;i++){double sum=0;for(int j=0;j<MAXOUTPUT;j++){sum+=sout[j]*bpa.how[i][j];}shide[i]=(bpa.hide[i])*(1-bpa.hide[i])*sum;}}/************************************************Function:Calculate the 权值的变化量************************************************/void CalculateChange(){int j=0;//隐藏层到输出层for(int i=0;i<MAXHIDE;i++){for(j=0;j<MAXOUTPUT;j++){howchange[i][j]=a*(howchange[i][j])+b*(sout[i])*(bpa.hide[i]);// }}//对输入层到隐藏层for(i=0;i<MAXINPUT;i++){for(j=0;j<MAXHIDE;j++){ihwchange[i][j]=a*(ihwchange[i][j])+b*(shide[i])*(bpa.input[i]);// }}}/************************************************Function:Calculate the 新的权值************************************************/void CalculateNewWeight(){int j=0;//隐藏层到输出层for(int i=0;i<MAXHIDE;i++){for(j=0;j<MAXOUTPUT;j++){bpa.how[i][j]=bpa.how[i][j]+howchange[i][j];}}//对输入层到隐藏层for(i=0;i<MAXINPUT;i++){for(j=0;j<MAXHIDE;j++){bpa.ihw[i][j]=bpa.ihw[i][j]+ihwchange[i][j];}}}void Test(){printf("请输入测试数据的输入值:\n");for(int i=0;i<MAXINPUT;i++){scanf("%lf",&bpa.input[i]);}TestCalculateOut();}。
//"pd" 偏导#include <stdio.h>#include <iostream>#include <vector>#include <math.h>using namespace std;#define sigmoid(x) (1/(1+exp(-(x))))#define sqr(x) ((x)*(x))#define sigmoidDerivationx(x) (x*(1-x))// double alpha = 0.5;// double w1[10][10] = {{0.15 0.20} {0.25 0.30}}; int main(){double bias[2] = {0.350.60};double weight[8] = {0.15 0.2 0.25 0.3 0.4 0.45 0.5 0.55};double output_laxxxxyer_weights[4] = {0.4 0.45 0.5 0.55};double i1 = 0.05;double i2 = 0.10;double target1 = 0.01;double target2 = 0.99;double alpha= 0.5;//学习率double numIter = 50000;//迭代次数for (int i = 0; i < numIter; i++){double neth1 = i1*weight[1] + i2*weight[2] + bias[1];double neth2 = i1*weight[3-1] + i2*weight[4-1] + bias[0];double outh1 = sigmoid(neth1);double outh2 = sigmoid(neth2);double neto1 = outh1*weight[5-1] + outh2*weight[6-1] + bias[1];double neto2 = outh2*weight[7-1] + outh2*weight[8-1] + bias[1];double outo1 = sigmoid(neto1);double outo2 = sigmoid(neto2);printf("%dtarget1:%ftarget2:%f\n"itarget1-outo1target2-outo2);if (i==numIter-1){printf("lastst result : %.4f %.4f\n\n" outo1 outo2);}//计算w5到w8(输出层权重)的误差double pdEOuto1 = - (target1 - outo1);double pdOuto1Neto1 = sigmoidDerivationx(outo1);double pdNeto1W5 = outh1;double pdEW5 = pdEOuto1 * pdOuto1Neto1 * pdNeto1W5;double pdNeto1W6 = outh2;double pdEW6 = pdEOuto1 * pdOuto1Neto1 * pdNeto1W6;double pdEOuto2 = - (target2 - outo2);double pdOuto2Neto2 = sigmoidDerivationx(outo2);double pdNeto1W7 = outh1;double pdEW7 = pdEOuto2 * pdOuto2Neto2 * pdNeto1W7;double pdNeto1W8 = outh2;double pdEW8 = pdEOuto2 * pdOuto2Neto2 * pdNeto1W8;//计算w1-w4(输出层权重)的误差pdEOuto1 = - (target1 - outo1);// #之前算过pdEOuto2 = - (target2 - outo2);// #之前算过pdOuto1Neto1 = sigmoidDerivationx(outo1) ; // #之前算过pdOuto2Neto2 = sigmoidDerivationx(outo2) ; // #之前算过double pdNeto1Outh1 = weight[5];double pdNeto1Outh2 = weight[7];double pdENeth1 = pdEOuto1 * pdOuto1Neto1 * pdNeto1Outh1 + pdEOuto2 * pdOuto2Neto2 * pdNeto1Outh2;double pdOuth1Neth1 = sigmoidDerivationx(outh1);double pdNeth1W1 = i1;double pdNeth1W2 = i2;double pdEW1 = pdENeth1 * pdOuth1Neth1 * pdNeth1W1;double pdEW2 = pdENeth1 * pdOuth1Neth1 * pdNeth1W2;pdNeto1Outh2 = weight[6];double pdNeto2Outh2 = weight[8];double pdOuth2Neth2 = sigmoidDerivationx(outh2);double pdNeth1W3 = i1;double pdNeth1W4 = i2;double pdENeth2 = pdEOuto1 *pdOuto1Neto1 * pdNeto1Outh2 + pdEOuto2 * pdOuto2Neto2 * pdNeto2Outh2;double pdEW3 = pdENeth2 * pdOuth2Neth2 * pdNeth1W3;double pdEW4 = pdENeth2 * pdOuth2Neth2 * pdNeth1W4;//权重更新weight[1] = weight[1] - alpha * pdEW1;weight[2] = weight[2] - alpha * pdEW2;weight[3] = weight[3] - alpha * pdEW3;weight[4] = weight[4] - alpha * pdEW4;weight[5] = weight[5] - alpha * pdEW5;weight[6] = weight[6] - alpha * pdEW6;weight[7] = weight[7] - alpha * pdEW7;weight[8] = weight[8] - alpha * pdEW8;}}。
bp算法流程BP算法流程。
BP算法是一种常用的神经网络训练算法,它通过不断地调整网络中的权重和偏置来实现对样本数据的拟合和预测。
在本文中,将详细介绍BP算法的流程,包括前向传播和反向传播两个重要步骤。
首先,我们来看看BP算法的前向传播过程。
在前向传播过程中,输入样本数据通过输入层进入神经网络,经过隐藏层的计算,最终得到输出层的预测结果。
具体而言,前向传播的计算过程如下:1. 初始化输入层的神经元,将样本数据输入网络中;2. 根据输入层的权重和偏置,计算隐藏层神经元的输出;3. 将隐藏层的输出作为输入,再次根据输出层的权重和偏置,计算最终的预测结果。
在前向传播过程中,神经网络通过不断的权重和偏置计算,逐步得到样本数据的预测结果。
接下来,我们将介绍BP算法的反向传播过程。
在反向传播过程中,我们需要根据预测结果和样本标签之间的误差,来调整网络中的权重和偏置,以达到减小误差的目的。
具体而言,反向传播的计算过程如下:1. 计算输出层神经元的误差,即预测结果与样本标签之间的差值;2. 根据输出层的误差,反向传播到隐藏层,计算隐藏层神经元的误差;3. 根据误差值,调整网络中的权重和偏置,以减小误差。
通过不断地前向传播和反向传播过程,神经网络不断地调整权重和偏置,最终实现对样本数据的拟合和预测。
需要注意的是,BP 算法的训练过程可能会出现过拟合或欠拟合的情况,因此需要根据实际情况进行调整和优化。
总结来说,BP算法的流程包括前向传播和反向传播两个重要步骤,通过这两个步骤的不断迭代,神经网络最终实现对样本数据的拟合和预测。
希望本文对BP算法的流程有所帮助,谢谢阅读!。
BP神经网络算法的C语言实现代码以下是一个BP神经网络的C语言实现代码,代码的详细说明可以帮助理解代码逻辑:```c#include <stdio.h>#include <stdlib.h>#include <math.h>#define INPUT_SIZE 2#define HIDDEN_SIZE 2#define OUTPUT_SIZE 1#define LEARNING_RATE 0.1//定义神经网络结构体typedef structdouble input[INPUT_SIZE];double hidden[HIDDEN_SIZE];double output[OUTPUT_SIZE];double weights_ih[INPUT_SIZE][HIDDEN_SIZE];double weights_ho[HIDDEN_SIZE][OUTPUT_SIZE];} NeuralNetwork;//激活函数double sigmoid(double x)return 1 / (1 + exp(-x));//创建神经网络NeuralNetwork* create_neural_networNeuralNetwork* nn =(NeuralNetwork*)malloc(sizeof(NeuralNetwork));//初始化权重for (int i = 0; i < INPUT_SIZE; i++)for (int j = 0; j < HIDDEN_SIZE; j++)nn->weights_ih[i][j] = (double)rand( / RAND_MAX * 2 - 1;}}for (int i = 0; i < HIDDEN_SIZE; i++)for (int j = 0; j < OUTPUT_SIZE; j++)nn->weights_ho[i][j] = (double)rand( / RAND_MAX * 2 - 1;}}return nn;//前向传播void forward(NeuralNetwork* nn)//计算隐藏层输出for (int i = 0; i < HIDDEN_SIZE; i++)double sum = 0;for (int j = 0; j < INPUT_SIZE; j++)sum += nn->input[j] * nn->weights_ih[j][i];}nn->hidden[i] = sigmoid(sum);}//计算输出层输出for (int i = 0; i < OUTPUT_SIZE; i++)double sum = 0;for (int j = 0; j < HIDDEN_SIZE; j++)sum += nn->hidden[j] * nn->weights_ho[j][i];}nn->output[i] = sigmoid(sum);}void backpropagation(NeuralNetwork* nn, double target)//计算输出层误差double output_error[OUTPUT_SIZE];for (int i = 0; i < OUTPUT_SIZE; i++)double delta = target - nn->output[i];output_error[i] = nn->output[i] * (1 - nn->output[i]) * delta;}//更新隐藏层到输出层权重for (int i = 0; i < HIDDEN_SIZE; i++)for (int j = 0; j < OUTPUT_SIZE; j++)nn->weights_ho[i][j] += LEARNING_RATE * nn->hidden[i] * output_error[j];}}//计算隐藏层误差double hidden_error[HIDDEN_SIZE];for (int i = 0; i < HIDDEN_SIZE; i++)double delta = 0;for (int j = 0; j < OUTPUT_SIZE; j++)delta += output_error[j] * nn->weights_ho[i][j];}hidden_error[i] = nn->hidden[i] * (1 - nn->hidden[i]) * delta;}//更新输入层到隐藏层权重for (int i = 0; i < INPUT_SIZE; i++)for (int j = 0; j < HIDDEN_SIZE; j++)nn->weights_ih[i][j] += LEARNING_RATE * nn->input[i] * hidden_error[j];}}void train(NeuralNetwork* nn, double input[][2], double target[], int num_examples)int iteration = 0;while (iteration < MAX_ITERATIONS)double error = 0;for (int i = 0; i < num_examples; i++)for (int j = 0; j < INPUT_SIZE; j++)nn->input[j] = input[i][j];}forward(nn);backpropagation(nn, target[i]);error += fabs(target[i] - nn->output[0]);}//判断误差是否已达到允许范围if (error < 0.01)break;}iteration++;}if (iteration == MAX_ITERATIONS)printf("Training failed! Error: %.8lf\n", error); }void predict(NeuralNetwork* nn, double input[]) for (int i = 0; i < INPUT_SIZE; i++)nn->input[i] = input[i];}forward(nn);printf("Prediction: %.8lf\n", nn->output[0]); int maiNeuralNetwork* nn = create_neural_network(; double input[4][2] ={0,0},{0,1},{1,0},{1,1}};double target[4] =0,1,1,};train(nn, input, target, 4);predict(nn, input[0]);predict(nn, input[1]);predict(nn, input[2]);predict(nn, input[3]);free(nn);return 0;```以上代码实现了一个简单的BP神经网络,该神经网络包含一个输入层、一个隐藏层和一个输出层。
文件输入输出目录为:F:\BP\训练样本文件名:训练样本.txt值为:1 1 -1 1 -1 1 0 1 0 1 输出文件名为:阈值.txt 权值.txt=========================#include "stdlib.h"#include "math.h"#include "conio.h"#include "stdio.h"#define N 2 /*/学习样本个数*/#define IN 3 /*/输入层神经元数目*/#define HN 3 /*/隐层神经元数目*/#define ON 2 /*/输出层神经元数目*/#define Z 20 /*旧权值保存,每次study的权值都保存下来*/ double P[IN]; /*单个样本输入数据*/double T[ON]; /*单个样本输出数据*/double W[HN][IN]; /*/输入层至隐层权值*/double V[ON][HN]; /*/隐层至输出层权值*/double X[HN]; /*/隐层的输入*/double Y[ON]; /*/输出层的输入*/double H[HN]; /*/隐层的输出*/double O[ON]; /*/输出层的输出*/double YU_HN[HN]; /*/隐层的阈值*/double YU_ON[ON]; /*/输出层的阈值*/double err m[N]; /*/第m个样本的总误差*/double a; /*/输出层至隐层的学习效率*/double b; /*/隐层至输入层学习效率*/double alpha; /*/动量因子,改进型bp算法使用*/ double d err[ON];FILE *fp;/*定义一个放学习样本的结构*/struct {double input[IN];double teach[ON];}Study_Data[N];/*改进型bp算法用来保存每次计算的权值*/struct {double old_W[HN][IN];}Old_WV[Z];显示开始界面int Start_Show(){clrscr();printf("\n ***********************\n");printf(" * Welcome to use *\n");printf(" * this program of *\n");printf(" * calculating the BP *\n");printf(" * model! *\n");printf(" * Happy every day! *\n");printf(" ***********************\n");printf("\n\n Before starting, please read the follows carefully:\n\n");printf(" 1.Please ensure the Path of the '训练样本.txt'(xunlianyangben.txt) is \n correct, like 'F:\BP\训练样本.txt'!\n");printf(" 2.The calculating results will be saved in the Path of 'F:\\BP\\'!\n");printf(" 3.The program will load 10 datas when running from 'F:\\BP\\训练样本.txt'!\n");printf(" 4.The program of BP can study itself for no more than 30000 times.\n And surpassing the number, the program will be ended by itself in\n preventing running infinitely because of error!\n");printf("\n\n\n");printf("Now press any key to start...\n");getch();getch();clrscr();}显示结束界面int End_Show(){printf("\n\n---------------------------------------------------\n");printf("The program has reached the end successfully!\n\n Press any key to exit!\n\n");printf("\n ***********************\n");printf(" * This is the end *\n");printf(" * of the program which*\n");printf(" * can calculate the BP*\n");printf(" * model! *\n");printf(" ***********************\n");printf(" * Thanks for using! *\n");printf(" * Happy every day! *\n");printf(" ***********************\n");getch();exit(0);}获取训练样本GetTrainingData() /*OK*/{ int m,i,j;int datr;if((fp=fopen("f:\\bp\\训练样本.txt","r"))==NULL) /*读取训练样本*/{printf("Cannot open file and strike any key exit!");getch();exit(1);}m=0;i=0;j=0;while(fscanf(fp,"%d",&datr)!=EOF){ j++;if(j<=(N*IN)) /*N为学习样本个数;IN为输入层神经元数目*/{if(i<IN){Study_Data[m].input[i]=datr;/*printf("\nthe Study_Datat[%d].input[%d]=%f\n",m,i,Study_Data[m].input[i]);getch();*/ /*use to check the loaded training datas*/}if(m==(N-1)&&i==(IN-1)){m=0;i=-1;}if(i==(IN-1)){m++;i=-1;}}else if((N*IN)<J&&J<=(N*(IN+ON))){if(i<ON){Study_Data[m].teach[i]=datr;/*printf("\nThe Study_Data[%d].teach[%d]=%f",m,i,Study_Data[m].teach[i]);getch();*/ /*use to check the loaded training datas*/}if(m==(N-1)&&i==(ON-1))printf("\n");if(i==(ON-1)){m++;}}i++;}fclose(fp);printf("\nThere are [%d] datats that have been loaded successfully!\n",j);/*show the data which has been loaded!*/printf("\nShow the data which has been loaded as follows:\n");for(m=0;m<N;M++){for(i=0;i<IN;I++){printf("\nStudy_Data[%d].input[%d]=%f",m,i,Study_Data[m].input[i]);}for(j=0;j<ON;J++){printf("\nStudy_Data[%d].teach[%d]=%f",m,j,Study_Data[m].teach[j]);}}printf("\n\nPress any key to start calculating...");getch();return 1;}/*///////////////////////////////////*//*初始化权、阈值子程序*//*///////////////////////////////////*/initial(){int i;int ii;int j;int jj;int k;int kk;/*隐层权、阈值初始化*/for(i=0;i<HN;i++){for(j=1;j<IN;j++){W[i][j]=(double)((rand()/32767.0)*2-1); /*初始化输入层到隐层的权值,随机模拟0 和1 -1 */ printf("w[%d][%d]=%f\n",i,j,W[i][j]);}}for(ii=0;ii<ON;II++){{V[ii][jj]= (double)((rand()/32767.0)*2-1); /*初始化隐层到输出层的权值,随机模拟0 和1 -1*/ printf("V[%d][%d]=%f\n",ii,jj,V[ii][jj]);}}for(k=0;k<HN;K++){YU_HN[k] = (double)((rand()/32767.0)*2-1); /*隐层阈值初始化,-0.01 ~ 0.01 之间*/printf("YU_HN[%d]=%f\n",k,YU_HN[k]);}for(kk=0;kk<ON;KK++){YU_ON[kk] = (double)((rand()/32767.0)*2-1); /*输出层阈值初始化,-0.01 ~ 0.01 之间*/}return 1;}/*子程序initial()结束*//*//////////////////////////////////////////*//*第m个学习样本输入子程序*//*/////////////////////////////////////////*/input_P(int m){ int i,j;for(i=0;i<IN;I++){P[i]=Study_Data[m].input[i];printf("P[%d]=%f\n",i,P[i]);}/*获得第m个样本的数据*/return 1;}/*子程序input_P(m)结束*//*/////////////////////////////////////////*//*第m个样本教师信号子程序*//*/////////////////////////////////////////*/input_T(int m){int k;for(k=0;k<ON;k++)T[k]=Study_Data[m].teach[k];return 1;}/*子程序input_T(m)结束*/H_I_O(){double sigma;int i,j;for(j=0;j<HN;j++){sigma=0;{sigma+=W[j][i]*P[i];/*求隐层内积*/}X[j]=sigma-YU_HN[i];/*求隐层净输入,为什么减隐层的阀值*/ H[j]=1.0/(1.0+exp(-X[j]));/*求隐层输出siglon算法*/}return 1;}/*子程序H_I_O()结束*/O_I_O(){int k;int j;double sigma;for(k=0;k<ON;k++){sigma=0.0;for(j=0;j<HN;j++){sigma+=V[k][j]*H[k];}Y[k]=sigma-YU_ON[k];O[k]=1.0/(1.0+exp(-Y[k]));}return 1;}int Err_O_H(int m){int k;double abs_err[ON];double sqr_err=0;for (k=0;k<ON;k++){abs_err[k]=T[k]-O[k];sqr_err+=(abs_err[k])*(abs_err[k]);d_err[k]=abs_err[k]*O[k]*(1.0-O[k]);err_m[m]=sqr_err/2;}return 1;}double e_err[HN];int Err_H_I(){int j,k;double sigma;for(j=0;j<HN;j++){sigma=0.0;sigma+=d_err[k]*V[k][j];}e_err[j]=sigma*H[j]*(1-H[j]);}return 1;}saveWV(int m){int i;int ii;int j;int jj;for(i=0;i<HN;i++){for(j=0;j<IN;j++){Old_WV[m].old_W[i][j] = W[i][j];}}for(ii=0;ii<ON;ii++){for(jj=0;jj<HN;jj++){Old_WV[m].old_V[ii][jj] = V[ii][jj];}}return 1;}int Delta_O_H(int n) /*(int m,int n)*/ {int k,j;if(n<1) /*n<=1*/{for (k=0;k<ON;k++){for (j=0;j<HN;j++){V[k][j]=V[k][j]+a*d_err[k]*H[j];}YU_ON[k]+=a*d_err[k];}}else if(n>1){for (j=0;j<HN;j++){V[k][j]=V[k][j]+a*d_err[k]*H[j]+alpha*(V[k][j]-Old_WV[(n-1)].old_V[k][j]);}YU_ON[k]+=a*d_err[k];}}return 1;}Delta_H_I(int n) /*(int m,int n)*/{ int i,j;if(n<=1) /*n<=1*/{for (j=0;j<HN;j++){for (i=0;i<IN;i++){W[j][i]=W[j][i]+b*e_err[j]*P[i];}YU_HN[j]+=b*e_err[j];}}else if(n>1){for(j=0;j<HN;j++){for(i=0;i<IN;i++){W[j][i]=W[j][i]+b*e_err[j]*P[i]+alpha*(W[j][i]-Old_WV[(n-1)].old_W[j][i]);}YU_HN[j]+=b*e_err[j];}}return 1;}double Err_Sum(){int m;double total_err=0;for(m=0;m<N;m++){total_err+=err_m[m];}return total_err;}int ii,jj,kk;if((fp=fopen("f:\\bp\\权值.txt","a"))==NULL) /*save the result at f:\hsz\bpc\*.txt*/{printf("Cannot open file strike any key exit!");getch();exit(1);}fprintf(fp,"Save the result of “权值”(quanzhi) as follows:\n");for(i=0;i<HN;i++){for(j=0;j<IN;j++)fprintf(fp,"W[%d][%d]=%f\n",i,j,W[i][j]);}fprintf(fp,"\n");for(ii=0;ii<ON;ii++){for(jj=0;jj<HN;jj++)fprintf(fp,"V[%d][%d]=%f\n",ii,jj,V[ii][jj]);}fclose(fp);printf("\nThe result of “权值.txt”(quanzhi) has been saved successfully!\nPress any key to continue..."); getch();if((fp=fopen("f:\\bp\\阈值.txt","a"))==NULL) /*save the result at f:\hsz\bpc\*/{printf("Cannot open file strike any key exit!");getch();exit(1);}fprintf(fp,"Save the result of “输出层的阈值”(huozhi) as follows:\n");for(k=0;k<ON;K++)fprintf(fp,"YU_ON[%d]=%f\n",k,YU_ON[k]);fprintf(fp,"\nSave the resul t of “隐层的阈值为”(huozhi) as follows:\n");for(kk=0;kk<HN;KK++)fprintf(fp,"YU_HN[%d]=%f\n",kk,YU_HN[kk]);fclose(fp);printf("\nThe result of “阈值.txt”(huozhi) has been saved successfully!\nPress any key to continue..."); getch ();}/**********************//**程序入口,即主程序**//**********************/void main(){double Pre_error;int flag;flag=30000;a=0.7;b=0.7;alpha=0.9;study=0;Pre_error=0.0001;/*实际值为Pre_error=0.0001;*/Start_Show(); /*调用函数,显示开始界面*/GetTrainingData();initial ();do{int m;++study;for(m=0;m<N;m++){input_P(m);input_T(m);H_I_O();O_I_O();Err_O_H(m);Err_H_I();saveWV(m); /****************/Delta_O_H(m); /*(m,study)*/Delta_H_I(m); /*(m,study)*/}sum_err=Err_Sum();printf("sum_err=%f\n",sum_err);printf("Pre_error=%f\n\n",Pre_error);if(study>flag){printf("\n*******************************\n");printf("The program is ended by itself because of error!\n The learning times is surpassed!\n");printf("*****************************\n");getch();break;}} while (sum_err>Pre_error);printf("\n****************\n");printf("\nThe program have studyed for [%d] times!\n",study);printf("\n****************\n");savequan(); /*save the results,保存计算权值*/End_Show();}=========================={Save the result of “权值”(quanzhi) as follows:W[0][0]=0.350578W[0][1]=-1.008697W[0][2]=-0.962250W[1][0]=0.055661W[1][1]=-0.372367W[1][2]=-0.890795W[2][0]=0.129752W[2][1]=-0.332591W[2][2]=-0.521561V[0][0]=-2.932654V[0][1]=-3.720583V[0][2]=-2.648183V[1][0]=2.938970V[1][1]=1.633281V[1][2]=1.944077}阈值.txt{Save the result of “输出层的阈值”(huozhi) as follows: YU_ON[0]=-4.226843YU_ON[1]=1.501791Save the result of “隐层的阈值为”(huozhi) as follows: YU_HN[0]=-0.431459YU_HN[1]=0.452127YU_HN[2]=0.258449}==================================。
BP 网络隐层可以有多个,多隐层的BP 网络模型
对一般多层前馈网模型如图所示。
图3.3 多层BP 网络结构
设有h 个隐层,按前馈顺序各隐层节点数为m 1,m 2,…,m h ;各隐层输出为y 1,y 2,…,y h ;各层权值矩阵分别为W 1,W 2,…,W h ,W h+1,则,各层权值调整计算公式为: 输出层
h j k k k k h j h k h jk y o o o d y w )1()(11--==∆++ηηδ
l k m j h ,,2,1;,,2,1,0 ==
第h 隐层
1
111)1()(-+=--==∆∑h i
h j h j h jk o k l
k h i
h j
h ij
y y y w y
w δηηδ
按上述规律逐层类推,可得到第一隐层权值调整计算公式为
p q q qr r m r p q
pq
x y y w x w
)1()(1
12211
12
-==∆∑=δηηδ
1,,2,1;,,2,1,0m q n p ==
三层前馈网的BP 学习算法也可写成向量形式: 对输出层
T T o ][y δW η=∆
式中 T m j y y y y y ][210 =y , T o l o k o o o ][21δδδδ =δ
对于隐层
T T y ][X δV η=∆
式中 T n i o x x x x x ][21 =X , T
y m y j y y y ][21δδδδ =δ
看出,BP 算法中,各层权值调整公式形式上都是一样的,均由3个因素决定,学习率η,本层输出的误差信号δ及本层输入信号Y (或X )。
其中输出层误差信号同网络的期望输出与实际输出之差有关,直接反映了输出误差,而各隐层的误差信号与前面各层的误差信号都有关,是从输出层开始逐层反传过来的。
反传过程可以简述为:
d 与o 比较得到输出层误差信号o δ→计算输出层权值调整量ΔW ;o δ通过隐层各节点反传→计算各隐层权值的调整量ΔV.
例 采用BP 网络映射下图曲线规律。
设计BP 网络结构如下:
权系数随机选取为:w 12=0.2,w 13=0.3,w 14=0.4,w 15=0.5, w 26=0.5,w 36=0.2,w 46=0.1,w 56=0.4。
取学习率η=1。
按图中曲线确定学习样本数据如下表(每0.05取一学习数据,共80对)
第一次学习,输入1
1x =0.0000(1节点第1次学习),5000.016
=d ,计算2、3、4、5单元状态i net :
0000.00000.011
11=∙==i i i w x w net i =2,3,4,5
计算2、3、4、5各隐层单元输出i y (i =2,3,4,5)
5.0)1/(1)(1=+==-i net i i e net f y
计算输出层单元6的状态值6net 及输出值16y
[]6.05.05.05.05.04.01.02.05.066-=⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢⎢⎣⎡==i T Y W net
6457.0)1/(1)1/(16.0166=+=+=--e e y net
反推确定第二层权系数变化:
0333.0)6457.01)(6457.05.0(6457.0)1)((1616161606-=--=--=y y d y i δ 106066i i i i y w w ηδ+= 5,4,3,2=i
第一次反传修正的输出层权为:
⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢
⎢⎣⎡=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡-∙+⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡=3833.00833.01833.04833.05.05.05.05.0)0333.0(14.01.02.05.06W
反推第一层权系数修正:
)1(11060611i i i i i y y w -=δδ 5,4,3,2=i
1
111011x w w i i i ηδ+=
[]T
i W 5.04.03.02.01=
第二次学习,0500.021=x ,5250.026=d
211x w net i i = 5,4,3,2=i
5025.0]1/[1]1/[1)0500.02.0()(222
112=+=+=⨯--e e y x w
5037.0]1/[1]1/[1)0500.03.0()
(22
113=+=+=⨯--e e
y x w
5050.0]1/[1)0500.04.0(24=+=⨯-e y 5062.025=y
计算6单元状态6net :
[]5713.05062.05050.05037.05025.03833.00833.01833.04833.066=⎥⎥⎥⎥
⎦
⎤
⎢⎢⎢
⎢⎣⎡==i T Y W net 6390.0)1/(1)(5713.062
6=+==-e net f y
按表中数据依次训练学习,学习次数足够高时,可能达到学习目的,实现权值成熟。
一般网络学习训练次数很高,采用手工计算是不可能的,需要用计算机程序求解。
3.4.3 BP 算法的程序实现
前面推导的BP 网络算法是BP 算法基础,称标准BP 算法。
目前神经网络的实现仍以软件编程为主。
现以如图的三层BP 网络为例,说明标准BP 算法的编程步骤:
图3.2 三层BP 网络结构
T l k o o o o O ][21 =——输出层输出向量;
][21m j V V V V V =—— 输入层到隐层间的权值矩阵; j V —— 隐层第j 个神经元对应的权列向量;
][21l k W W W W W =—— 隐层到输出层间的权值矩阵;
k W ——输出层第k 个神经元对应的权列向量;
d=T l k d d d d ][21 —— 网络期望输出向量。
程序可用一般高级语言编写,如C等,但考虑方便,最好采用MATLAB语言,特别是MATLAB环境中开发了工具箱(Toolboxes),其中神经网络开发工具(Neural Network)提供很丰富的手段来完成BP等ANN设计与分析。
Neural Network中提供了网络初始化函数用语构建基本网络,可自动生成权值,提供各种转移函数,提供各种训练或学习方法与手段,并实现仿真运算,监视网络训练误差等。
BP网络的训练,可概括归纳为输入已知数据,权值初始化,训练网络三大步。
用神经网络工具箱训练BP网络,权值初始化和训练网络都可调用BP网络的相应工具函数。
调用时,用户只需要将这些工具函数视为黑箱,知道输入什么得到什么即可,不必考虑工具函数内部究竟如何。
BP网络的一些重要函数和功能(与版本有关)如表3.1。
基本神经元模型:
传递函数 (转移函数):
线性传递函数purelin(s)即y=s;对数S型传递函数logsig(s),即y=1/(1+e-s);双曲正切S型传递函数tansig (s)即=tansigs,即y= (1-e-s)/(1+e-s)曲线。
3.4.4 多层前馈网络的主要能力
多层前馈网络是目前应用最多的神经网络,这主要归结于基于BP算法的多层前馈网络具有一些重要能力:
(1)非线性映射能力
………………………..
(2)泛化能力
…………………………………..
(3)容错能力
……………………………..
3.4.5 误差曲面与BP算法的局限性
3.5标准BP算法的改进
标准BP算法在应用中暴露出一些缺陷:
(1)易形成局部极小而得不到全局最优;
(2)训练次数多,学习效率低,收敛速度慢;(3)隐节点选取缺乏理论指导;
(4)训练时学习新样本有遗忘旧样本的趋势。
针对上述问题,国内外已提出一些有效的改进算法。
3.5.1增加动量项(惯性调整算法) △W(t)=ηδX+α△W(t-1)
α-动量系数,取(0,1)。
大都0.9左右 3.5.2自适应调整学习率
设一初始学习率,训练一批次权值调整后,看总误差E,若E ↑,则 η=βη β<1 若E ↓ 则
η=φη φ>1 实现合理步长调整。
3.5.3引入陡度因子
λ
/11net e
O -+= λ——陡度因子
采用压缩激活函数来改变误差函数,从而改变误差曲面的效果。
n e t
e O -+=
11。