1BP神经网络实现(JAVA代码)
bp神经网络
bp神经网络BP神经网络(Backpropagation Network)是一种被广泛应用于分类、预测和优化问题中的人工神经网络模型。
BP神经网络具有简单易懂、易于理解和易于实现的特点,因此在工程实践中被广泛应用。
BP神经网络的基本思想是将信息通过一层层的神经元传递,然后反向调节神经元的权重和偏置,从而实现对模型参数的优化。
BP神经网络通常包含输入层、隐层和输出层三个层次。
其中输入层用于接收输入数据,隐层用于处理输入数据,输出层用于给出模型的预测结果。
BP神经网络通过不断反向传播误差信号来调整各层神经元之间的连接权重,从而实现对模型参数的逐步优化。
BP神经网络的训练过程通常分为前向传播和反向传播两个阶段。
在前向传播阶段,输入数据被输入到神经网络中,经过一系列计算后得到输出结果。
在反向传播阶段,将输出结果与真实值进行比较,计算误差信号,并通过反向传播算法将误差信号逐层传递回到输入层,从而实现对神经网络参数(权重和偏置)的不断调整。
通过多次迭代,直到神经网络的输出结果与真实值的误差达到一定的精度要求为止。
BP神经网络的优点在于可以处理非线性问题,并且可以自适应地调整模型参数。
然而,BP神经网络也存在一些缺点,例如容易陷入局部极小值,训练速度较慢,需要大量的训练数据等等。
在实际应用中,BP神经网络已经被广泛应用于分类、预测和优化等方面。
例如,BP神经网络可以用于识别手写数字、预测股票市场走势、自动驾驶和机器人控制等方面。
另外,BP 神经网络还可以与其他机器学习算法相结合,共同解决各种复杂问题。
总之,BP神经网络是一种简单实用的人工神经网络模型,具有广泛的应用前景。
在实际应用中,需要根据具体问题对模型进行适当的改进和优化,以提高其预测精度和鲁棒性。
BP神经网络-本科生毕业设计论文-小论文
基于智能计算的水质预测预警系统的设计与实现温子铭1,刘双印1(1.广东海洋大学信息学院,广东湛江524088)摘要:及时准确地掌握水质变化趋势是确保水产品健康养殖的关键,为此,本设计采用智能计算与现代Web开发技术有机结合,以软件工程为指导,按照面向对象程序设计的方法,构建5种基于智能计算的水质预测预警模型;采用J2EE为开发工具设计实现了B/S架构的水质预测预警系统。
该系统主要有水质数据管理、水质数据趋势展示、水质指标溶解氧浓度预测、水质预警管理等功能模块组成,用户界面友好,水质预测精度较高,能够满足水产养殖水质管理的需要。
该系统的研制为提前掌握水质未来发展趋势、水污染预警提供基础数据和手段,为应对突发水质事件、水质调节、水产养殖生产管理与规划提供科学的决策依据,有一定的实用价值。
关键词:水产养殖;水质趋势;J2EE;水质预测预警系统;智能计算;Design and Implementation of Water Quality Predicting and Early Warning SystemBase on Smart ComputingWen Ziming, Liu Shuangyin(1. Information Institute of Guangdong Ocean University, Zhanjiang,GuangDong 524088) Abstract:Have a good command of water quality trends in time and accurately is the key to assure health growth of the aquatic products. Therefore, this design is combined with intelligent computing and modern web development technology, on the guidance of software engineer, and also established five kinds of water quality predicting and early warning models based on intelligent technology according to the measure of Object-Oriented Programming; We adopted J2EE as development tool to achieve the water quality predicting and early warning system based on B/S framework. This system mainly included water quality data management module, water quality data trend module, dissolved oxygen prediction module and water quality early warning module. It’s useful for users and can meet the needs of aquatic water quality management. The establishment of this system provide the basic data and methods to handling the future water quality trend and water pollution early warning. And also provide the scientific decision for dealing with the water pollution events, water quality adjustment, aquaculture management and plans. It has practical value.Key words: Aquaculture, water quality trend, J2EE, water quality predicting and early warning system, intelligent computing.1引言我国是水产养殖大国,也是世界上唯一一个养殖产量超过捕捞产量的国家, 水产养殖为解决食品供给、粮食安全、改善民生,增加农民收入等方面发挥了重要作用。
bp神经网络代码
bp神经网络代码
BP神经网络代码,是一种用于训练深度学习模型的反向传播算法。
它使用一系列的步骤,以每次迭代的方式来调整神经网络中权重的大小,从而使得它能够更准确地识别数据集中的特征。
BP神经网络代码的基本步骤如下:
1. 初始化权重:首先,选择一组随机初始权重参数。
2. 输入数据:然后,将数据输入神经网络,并将输入与权重相乘以计算输出。
3. 计算错误:接下来,通过比较预期输出和实际输出,计算网络的误差。
4. 反向传播:使用反向传播算法,根据误差调整权重参数,以减少误差。
5. 重复步骤2-4:重复步骤2-4,直到误差低到满足要求为止。
BP神经网络算法程序
BP神经网络算法程序一、BP神经网络算法原理BP神经网络算法包括输入层、隐藏层和输出层三个层次。
每个层次的神经元节点与下一层次的神经元节点之间存在权重系数。
神经元节点通过输入信号经过激活函数的处理得到输出信号,并将输出信号传递给下一层次的神经元节点。
反向传播过程中,首先根据误差评估结果计算输出层的误差信号,再根据该误差信号分别计算隐藏层和输入层的误差信号。
然后根据误差信号的计算结果,逐层更新网络的权重系数。
二、BP神经网络算法步骤1.初始化网络权重:随机初始化网络各层次之间的权重系数。
2.设置学习率和最大迭代次数。
3.迭代训练网络:重复以下步骤直到满足停止条件为止。
a)根据当前样本的输入信号,通过前向传播算法计算输出结果。
c)根据误差信号,通过反向传播算法更新网络的权重系数。
4.测试网络:使用独立的测试数据集,通过前向传播算法计算网络的输出结果,评估网络的泛化能力。
三、BP神经网络算法示例程序下面给出一个简单的使用Python编写的BP神经网络算法示例程序。
```pythonimport numpy as npclass BPNeuralNetwork:def __init__(self, input_dim, hidden_dim, output_dim): self.input_dim = input_dimself.hidden_dim = hidden_dimself.output_dim = output_dimself.W1 = np.random.randn(input_dim, hidden_dim)self.W2 = np.random.randn(hidden_dim, output_dim)def sigmoid(self, x):return 1 / (1 + np.exp(-x))def sigmoid_derivative(self, x):return x * (1 - x)def forward_propagation(self, X):self.z2 = np.dot(X, self.W1)self.a2 = self.sigmoid(self.z2)self.z3 = np.dot(self.a2, self.W2)self.y_hat = self.sigmoid(self.z3)return self.y_hatdef backward_propagation(self, X, y, lr):self.loss = y - self.y_hatdelta3 = self.loss * self.sigmoid_derivative(self.y_hat) dW2 = np.dot(self.a2.T, delta3)delta2 = np.dot(delta3, self.W2.T) *self.sigmoid_derivative(self.a2)dW1 = np.dot(X.T, delta2)self.W2 += lr * dW2self.W1 += lr * dW1def train(self, X, y, lr=0.1, epochs=1000):for i in range(epochs):y_hat = self.forward_propagation(X)self.backward_propagation(X, y, lr)def predict(self, X):return np.round(self.forward_propagation(X))#示例用法X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])y = np.array([[0], [1], [1], [0]])nn = BPNeuralNetwork(2, 2, 1)print("预测结果:")print(nn.predict(X))```以上是一个简单的BP神经网络算法示例程序,用于训练一个XOR逻辑门的分类模型。
bp神经网络算法步骤结合实例
bp神经网络算法步骤结合实例
BP神经网络算法步骤包括以下几个步骤:
1.输入层:将输入数据输入到神经网络中。
2.隐层:在输入层和输出层之间,通过一系列权值和偏置将输入数据进行处理,得到输出
数据。
3.输出层:将隐层的输出数据输出到输出层。
4.反向传播:通过反向传播算法来计算误差,并使用梯度下降法对权值和偏置进行调整,
以最小化误差。
5.训练:通过不断地进行输入、隐层处理、输出和反向传播的过程,来训练神经网络,使
其达到最优状态。
实例:
假设我们有一个BP神经网络,它的输入层有两个输入节点,隐层有三个节点,输出层有一个节点。
经过训练,我们得到了权值矩阵和偏置向量。
当我们给它输入一组数据时,它的工作流程如下:
1.输入层:将输入数据输入到神经网络中。
2.隐层:将输入数据与权值矩阵相乘,再加上偏置向量,得到输出数据。
3.输出层:将隐层的输出数据输出到输出层。
4.反向传播:使用反向传播算法计算误差,并使用梯度下降法调整权值和偏置向量,以最
小化误差。
5.训练:通过不断地输入、处理、输出和反向传播的过程,来训练神经网络,使其达到最
优状态。
这就是BP神经网络算法的基本流程。
在实际应用中,还需要考虑许多细节问题,如权值和偏置的初始值、学习率、激活函数等。
但是,上述流程是BP神经网络算法的基本框架。
bp神经网络算法原理
bp神经网络算法原理BP神经网络算法(Backpropagation algorithm)是一种监督学习的神经网络算法,其目的是通过调整神经网络的权重和偏置来实现误差的最小化。
BP神经网络算法基于梯度下降和链式法则,在网络的前向传播和反向传播过程中进行参数的更新。
在前向传播过程中,输入样本通过网络的各个神经元计算,直到达到输出层。
每个神经元都会对上一层的输入进行加权求和,并经过一个非线性激活函数得到输出。
前向传播的结果即为网络的输出。
在反向传播过程中,首先需要计算网络的输出误差。
误差是实际输出与期望输出的差异。
然后,从输出层开始,沿着网络的反方向,通过链式法则计算每个神经元的误差贡献,并将误差从输出层反向传播到输入层。
每个神经元根据自身的误差贡献,对权重和偏置进行调整。
这一过程可以看作是通过梯度下降来调整网络参数,以最小化误差。
具体而言,对于每个样本,BP神经网络算法通过以下步骤来更新网络的参数:1. 前向传播:将输入样本通过网络,计算得到网络的输出。
2. 计算误差:将网络的输出与期望输出进行比较,计算得到输出误差。
3. 反向传播:从输出层开始,根据链式法则计算每个神经元的误差贡献,并将误差沿着网络反向传播到输入层。
4. 参数更新:根据每个神经元的误差贡献,使用梯度下降方法更新神经元的权重和偏置。
5. 重复以上步骤,直到达到预设的训练停止条件,例如达到最大迭代次数或误差小于某个阈值。
总的来说,BP神经网络算法通过计算输出误差和通过反向传播调整网络参数的方式,实现对神经网络的训练。
通过不断迭代优化网络的权重和偏置,使得网络能够更准确地进行分类、回归等任务。
用Python实现BP神经网络(附代码)
⽤Python实现BP神经⽹络(附代码)⽤Python实现出来的机器学习算法都是什么样⼦呢?前两期线性回归及逻辑回归项⽬已发布(见⽂末链接),今天来讲讲BP神经⽹络。
BP神经⽹络全部代码https:///lawlite19/MachineLearning_Python/blob/master/NeuralNetwok/NeuralNetwork.py神经⽹络model先介绍个三层的神经⽹络,如下图所⽰输⼊层(input layer)有三个units(为补上的bias,通常设为1)表⽰第j层的第i个激励,也称为为单元unit为第j层到第j+1层映射的权重矩阵,就是每条边的权重所以可以得到:隐含层:输出层,其中,S型函数,也成为激励函数可以看出为3x4的矩阵,为1x4的矩阵==》j+1的单元数x(j层的单元数+1)代价函数假设最后输出的,即代表输出层有K个单元,其中,代表第i个单元输出与逻辑回归的代价函数差不多,就是累加上每个输出(共有K个输出)正则化L-->所有层的个数-->第l层unit的个数正则化后的代价函数为共有L-1层,然后是累加对应每⼀层的theta矩阵,注意不包含加上偏置项对应的theta(0)正则化后的代价函数实现代码:# 代价函数def nnCostFunction(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):length = nn_params.shape[0] # theta的中长度# 还原theta1和theta2Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1)Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1)# np.savetxt("Theta1.csv",Theta1,delimiter=',')m = X.shape[0]class_y = np.zeros((m,num_labels)) # 数据的y对应0-9,需要映射为0/1的关系# 映射yfor i in range(num_labels):class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值'''去掉theta1和theta2的第⼀列,因为正则化时从1开始'''Theta1_colCount = Theta1.shape[1]Theta1_x = Theta1[:,1:Theta1_colCount]Theta2_colCount = Theta2.shape[1]Theta2_x = Theta2[:,1:Theta2_colCount]# 正则化向theta^2term = np.dot(np.transpose(np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1)))),np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1))))'''正向传播,每次需要补上⼀列1的偏置bias'''a1 = np.hstack((np.ones((m,1)),X))z2 = np.dot(a1,np.transpose(Theta1))a2 = sigmoid(z2)a2 = np.hstack((np.ones((m,1)),a2))z3 = np.dot(a2,np.transpose(Theta2))h = sigmoid(z3)'''代价'''J = -(np.dot(np.transpose(class_y.reshape(-1,1)),np.log(h.reshape(-1,1)))+np.dot(np.transpose(1-class_y.reshape(-1,1)),np.log(1-h.reshape(-1,1)))-Lambda*term/2)/mreturn np.ravel(J)反向传播BP上⾯正向传播可以计算得到J(θ),使⽤梯度下降法还需要求它的梯度BP反向传播的⽬的就是求代价函数的梯度假设4层的神经⽹络,记为-->l层第j个单元的误差《===》(向量化)没有,因为对于输⼊没有误差因为S型函数的倒数为:,所以上⾯的和可以在前向传播中计算出来反向传播计算梯度的过程为:(是⼤写的)for i=1-m:--正向传播计算(l=2,3,4...L)-反向计算、...;--最后,即得到代价函数的梯度实现代码:# 梯度def nnGradient(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):length = nn_params.shape[0]Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1) Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1) m = X.shape[0]class_y = np.zeros((m,num_labels)) # 数据的y对应0-9,需要映射为0/1的关系# 映射yfor i in range(num_labels):class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值'''去掉theta1和theta2的第⼀列,因为正则化时从1开始'''Theta1_colCount = Theta1.shape[1]Theta1_x = Theta1[:,1:Theta1_colCount]Theta2_colCount = Theta2.shape[1]Theta2_x = Theta2[:,1:Theta2_colCount]Theta1_grad = np.zeros((Theta1.shape)) #第⼀层到第⼆层的权重Theta2_grad = np.zeros((Theta2.shape)) #第⼆层到第三层的权重Theta1[:,0] = 0;Theta2[:,0] = 0;'''正向传播,每次需要补上⼀列1的偏置bias'''a1 = np.hstack((np.ones((m,1)),X))z2 = np.dot(a1,np.transpose(Theta1))a2 = sigmoid(z2)a2 = np.hstack((np.ones((m,1)),a2))z3 = np.dot(a2,np.transpose(Theta2))h = sigmoid(z3)'''反向传播,delta为误差,'''delta3 = np.zeros((m,num_labels))delta2 = np.zeros((m,hidden_layer_size))for i in range(m):delta3[i,:] = h[i,:]-class_y[i,:]Theta2_grad = Theta2_grad+np.dot(np.transpose(delta3[i,:].reshape(1,-1)),a2[i,:].reshape(1,-1))delta2[i,:] = np.dot(delta3[i,:].reshape(1,-1),Theta2_x)*sigmoidGradient(z2[i,:])Theta1_grad = Theta1_grad+np.dot(np.transpose(delta2[i,:].reshape(1,-1)),a1[i,:].reshape(1,-1))'''梯度'''grad = (np.vstack((Theta1_grad.reshape(-1,1),Theta2_grad.reshape(-1,1)))+Lambda*np.vstack((Theta1.reshape(-1,1),Theta2.reshape(-1,1))))/mreturn np.ravel(grad)BP可以求梯度的原因实际是利⽤了链式求导法则因为下⼀层的单元利⽤上⼀层的单元作为输⼊进⾏计算⼤体的推导过程如下,最终我们是想预测函数与已知的y⾮常接近,求均⽅差的梯度沿着此梯度⽅向可使代价函数最⼩化。
BP神经网络详细代码
运用BP神经网络进行预测代码如下:clcclear allclose all%bp神经网络预测%输入输出赋值p=[493 372 445;372 445 176;445 176 235;176 235 378;235 378 429;378 429 561;429 561 651;561 651 467;651 467 527;467 527 668;527 668 841; 668 841 526;841 526 480;526 480 567;480 567 685]';t=[176 235 378 429 561 651 467 527 668 841 526 480 567 685 507];%数据归一化[p1ps]=mapminmax(p);[t1ts]=mapminmax(t);%数据集分配[trainsample.pvalsample.ptestsample.p] =dividerand(p0.70.150.15);[alsample.ttestsample.t] =dividerand(t0.70.150.15);%建立BP神经网络TF1='tansig';TF2='purelin';net=newff(minmax(p)[101]{TF1 TF2}'traingdm');%网络参数的设置net.trainParam.epochs=10000;%训练次数设置net.trainParam.goal=1e-7;%训练目标设置net.trainParam.lr=0.01;%学习率设置net.trainParam.mc=0.9;%动量因子的设置net.trainParam.show=25;%显示的间隔次数% 指定训练参数net.trainFcn='trainlm';[nettr]=train(nettrainsample.ptrainsample.t);%计算仿真[normtrainoutputtrainPerf]=sim(nettrainsample.p[][]trainsample.t);%训练数据,经BP得到的结果[normvalidateoutputvalidatePerf]=sim(netvalsample.p[][]valsample.t);%验证数据,经BP得到的结果[normtestoutputtestPerf]=sim(nettestsample.p[][]testsample.t);%测试数据,经BP得到的结果%计算结果反归一化,得到拟合数据trainoutput=mapminmax('reverse'normtrainoutputts);validateoutput=mapminmax('reverse'normvalidateoutputts);testoutput=mapminmax('reverse'normtestoutputts);%输入数据反归一化,得到正式值trainvalue=mapminmax('reverse'trainsample.tts);%正式的训练数据validatevalue=mapminmax('reverse'valsample.tts);%正式的验证数据testvalue=mapminmax('reverse'testsample.tts);%正式的测试数据%输入要预测的数据pnewpnew=[313256239]';pnewn=mapminmax(pnew);anewn=sim(netpnewn);anew=mapminmax('reverse'anewnts);%绝对误差的计算errors=trainvalue-trainoutput;%plotregression拟合图figureplotregression(trainvaluetrainoutput)%误差变化图figureplot(1:length(errors)errors'-b')title('误差变化图')%误差值的正态性的检验figurehist(errors);%频数直方图figurenormplot(errors);%Q-Q图[muhatsigmahatmucisigmaci]=normfit(errors);%参数估计均值方差均值的0.95置信区间方差的0.95置信区间[h1sigci]= ttest(errorsmuhat);%假设检验figure ploterrcorr(errors);%绘制误差的自相关图figure parcorr(errors);%绘制偏相关图。
BP神经网络算法原理
BP神经网络算法原理BP神经网络(Back-Propagation Neural Network)是一种常见的人工神经网络,被广泛应用于模式识别、数据处理、逼近函数、分类问题等许多领域。
BP神经网络通过学习和调整神经元的连接权重,实现从输入到输出的映射。
BP神经网络由输入层、隐藏层和输出层组成,输入层接收外部输入样本的信号,并将其传递给隐藏层。
隐藏层通过对输入的处理对不同属性进行特征提取,得到一组新的特征。
最后,输出层将经过隐藏层处理的特征映射到输出值,完成预测或分类任务。
BP神经网络的学习过程可以分为两个阶段:前向传播和反向传播。
在前向传播过程中,输入样本在网络中的输入层经过各个层的处理,最终得到输出层的结果。
在反向传播过程中,通过计算输出层的误差来调整每个神经元的连接权重,从而降低误差。
具体而言,BP神经网络的学习过程如下:1.权重初始化:初始化输入层与隐藏层之间、隐藏层与输出层之间的连接权重。
通常采用小的随机数进行初始化。
2.前向传播:将输入样本从输入层传递到输出层,计算每个神经元的输出值。
3.误差计算:计算输出层的误差,通常使用均方误差作为误差函数。
4.反向传播:将误差从输出层传递到输入层,根据输出层的误差调整每个神经元的连接权重。
这一步是BP算法的核心,通过梯度下降法不断更新权重,使得网络的输出与样本的实际输出更加接近。
5.权重更新:根据反向传播得到的调整量,更新每个连接权重。
6.重复上述步骤:不断重复前向传播和反向传播过程,直到达到预设的停止条件,比如误差小于一些阈值或达到预设的最大迭代次数。
通过多次迭代学习样本集,BP神经网络能够逐渐优化权重,提高模型的拟合能力和泛化能力。
在实际应用中,为了克服过拟合问题,可以采用正则化和交叉验证等方法进行改进。
总结来说,BP神经网络是一种通过反向传播算法来学习和调整神经元之间连接权重的人工神经网络。
它通过多次迭代优化权重,从而实现从输入到输出的映射,广泛应用于模式识别、数据处理和分类问题等领域。
神经网络编程实战:Java语言实现(原书第2版)
2 神经网 络学习
2.4 学习算法示例
2.4.1 δ规则
2.4.6 学 习机
01 06
05
2.4.5 另一种学习算 法——Hebbian学习
2.4.2 学习率
02
03
2.4.3 实 现δ规则
04
2.4.4 δ规则学习的核 心——train和
calcNewWeight方法
2 神经网络学习
2.2.1 监督 学习
1
2.2.2 无监 督学习
2
2.2 学习模式
2.3.1 寻找损失函 数最优下降方向
2.3.3 计算损失函 数
01
03
02
04
2.3.2 在学习过程 中更新权重
2.3.4 一般误差和 总体误差
2.3.5 神经网络的 迭代学习什么时候
停止比较好
05
2 神经网络学习
07
Part One
6 疾病分类识别
6 疾病分类识别
6.1 分类问题的 基础
6.2 逻辑回归
6.3 分类神经网 络
6.4 用神经网络 进行疾病识别
6.5 本章小结
6 疾病分类识别
01
6.1.1 分 类数据
02
6.1.2 处 理分类
数据
6.1 分类问题的基础
6 疾病分类识别
6.2.1 多分类 与二分类
1.2.5 额外参数——偏置
1 神经网络入门
1.2 人工神经网络
1.2.2 基本元素——人工神 经元
1.2.4 可变参数——权重
1.2.6 由部分到整体——层
1 神经网络入门
0
0
1
2
JAVA实现BP神经网络算法
JAVA实现BP神经网络算法BP神经网络是一种基于误差逆传播算法的人工神经网络模型,它可以用于解决分类、回归和模式识别等问题。
在本文中,将介绍BP神经网络的基本原理以及如何使用Java实现该算法。
首先,要了解BP神经网络的基本原理。
BP神经网络由输入层、隐藏层和输出层组成。
输入层负责接收输入数据,隐藏层用来处理输入数据并学习特征,输出层用来产生最终的输出结果。
BP神经网络的训练过程主要包括前向传播和反向传播两个阶段。
前向传播是指从输入层到输出层的过程,其中输入数据通过隐藏层传递到输出层,不断调整参数权重,直到产生最终的输出结果。
隐藏层中的每个神经元都会计算输入的加权和,并将其传递给激活函数进行激活,然后将结果传递给下一层。
反向传播是指从输出层到输入层的过程,其中通过比较输出结果和期望结果的差异来计算误差。
然后将误差沿着网络的方向向后传播,逐层调整权重和偏差,以减小误差。
反向传播使用梯度下降法来更新网络参数,直到达到一定的停止条件。
接下来,我们将介绍如何使用Java实现BP神经网络算法。
首先,我们需要定义一个神经元类,该类包含神经元的权重、偏差和激活函数。
```javapublic class Neuronprivate double[] weights; // 神经元的权重private double bias; // 神经元的偏差private Function<Double, Double> activationFunction; // 神经元的激活函数public Neuron(int inputSize, Function<Double, Double> activationFunction)this.weights = new double[inputSize];this.bias = 0;this.activationFunction = activationFunction;//初始化权重和偏差for (int i = 0; i < inputSize; i++)this.weights[i] = Math.random(;}this.bias = Math.random(;}//计算神经元的输出public double calculateOutput(double[] inputs)double sum = 0;for (int i = 0; i < inputs.length; i++)sum += inputs[i] * weights[i];sum += bias;return activationFunction.apply(sum);}```其次,我们需要定义一个神经网络类,该类包含多个神经元,以及前向传播和反向传播的方法。
BP神经网络原理及Python实现代码
BP神经⽹络原理及Python实现代码本⽂主要讲如何不依赖TenserFlow等⾼级API实现⼀个简单的神经⽹络来做分类,所有的代码都在下⾯;在构造的数据(通过程序构造)上做了验证,经过1个⼩时的训练分类的准确率可以达到97%。
完整的结构化代码见于:先来说说原理⽹络构造上⾯是⼀个简单的三层⽹络;输⼊层包含节点X1 , X2;隐层包含H1,H2;输出层包含O1。
输⼊节点的数量要等于输⼊数据的变量数⽬。
隐层节点的数量通过经验来确定。
如果只是做分类,输出层⼀般⼀个节点就够了。
从输⼊到输出的过程1.输⼊节点的输出等于输⼊,X1节点输⼊x1时,输出还是x1.2. 隐层和输出层的输⼊I为上层输出的加权求和再加偏置,输出为f(I) , f为激活函数,可以取sigmoid。
H1的输出为sigmoid(w1x1 + w2x2 + b)误差反向传播的过程Python实现构造测试数据# -*- coding: utf-8 -*-import numpy as npfrom random import random as rdn'''说明:我们构造1000条数据,每条数据有三个属性(⽤a1 , a2 , a3表⽰)a1 离散型取值 1 到 10 ,均匀分布a2 离散型取值 1 到 10 ,均匀分布a3 连续型取值 1 到 100 ,且符合正态分布各属性之间独⽴。
共2个分类(0 , 1),属性值与类别之间的关系如下,0 : a1 in [1 , 3] and a2 in [4 , 10] and a3 <= 501 : a1 in [1 , 3] and a2 in [4 , 10] and a3 > 500 : a1 in [1 , 3] and a2 in [1 , 3] and a3 > 301 : a1 in [1 , 3] and a2 in [1 , 3] and a3 <= 300 : a1 in [4 , 10] and a2 in [4 , 10] and a3 <= 501 : a1 in [4 , 10] and a2 in [4 , 10] and a3 > 500 : a1 in [4 , 10] and a2 in [1 , 3] and a3 > 301 : a1 in [4 , 10] and a2 in [1 , 3] and a3 <= 30'''def genData() :#为a3⽣成符合正态分布的数据a3_data = np.random.randn(1000) * 30 + 50data = []for i in range(1000) :#⽣成a1a1 = int(rdn()*10) + 1if a1 > 10 :a1 = 10#⽣成a2a2 = int(rdn()*10) + 1if a2 > 10 :a2 = 10#取a3a3 = a3_data[i]#计算这条数据对应的类别c_id = 0if a1 <= 3 and a2 >= 4 and a3 <= 50 :c_id = 0elif a1 <= 3 and a2 >= 4 and a3 > 50 :c_id = 1elif a1 <= 3 and a2 < 4 and a3 > 30 :c_id = 0elif a1 <= 3 and a2 < 4 and a3 <= 30 :c_id = 1elif a1 > 3 and a2 >= 4 and a3 <= 50 :c_id = 0elif a1 > 3 and a2 >= 4 and a3 > 50 :c_id = 1elif a1 > 3 and a2 < 4 and a3 > 30 :c_id = 0elif a1 > 3 and a2 < 4 and a3 <= 30 :c_id = 1else :print('error')#拼合成字串str_line = str(i) + ',' + str(a1) + ',' + str(a2) + ',' + str(a3) + ',' + str(c_id)data.append(str_line)return '\n'.join(data)激活函数# -*- coding: utf-8 -*-"""Created on Sun Dec 2 14:49:31 2018@author: congpeiqing"""import numpy as np#sigmoid函数的导数为 f(x)*(1-f(x))def sigmoid(x) :return 1/(1 + np.exp(-x))⽹络实现# -*- coding: utf-8 -*-"""Created on Sun Dec 2 14:49:31 2018@author: congpeiqing"""from activation_funcs import sigmoidfrom random import randomclass InputNode(object) :def __init__(self , idx) :self.idx = idxself.output = Nonedef setInput(self , value) :self.output = valuedef getOutput(self) :return self.outputdef refreshParas(self , p1 , p2) :passclass Neurode(object) :def __init__(self , layer_name , idx , input_nodes , activation_func = None , powers = None , bias = None) : self.idx = idxyer_name = layer_nameself.input_nodes = input_nodesif activation_func is not None :self.activation_func = activation_funcelse :#默认取 sigmoidself.activation_func = sigmoidif powers is not None :self.powers = powerselse :self.powers = [random() for i in range(len(self.input_nodes))]if bias is not None :self.bias = biaselse :self.bias = random()self.output = Nonedef getOutput(self) :self.output = self.activation_func(sum(map(lambda x : x[0].getOutput()*x[1] , zip(self.input_nodes, self.powers))) + self.bias) return self.outputdef refreshParas(self , err , learn_rate) :err_add = self.output * (1 - self.output) * errfor i in range(len(self.input_nodes)) :#调⽤⼦节点self.input_nodes[i].refreshParas(self.powers[i] * err_add , learn_rate)#调节参数power_delta = learn_rate * err_add * self.input_nodes[i].outputself.powers[i] += power_deltabias_delta = learn_rate * err_addself.bias += bias_deltaclass SimpleBP(object) :def __init__(self , input_node_num , hidden_layer_node_num , trainning_data , test_data) :self.input_node_num = input_node_numself.input_nodes = [InputNode(i) for i in range(input_node_num)]self.hidden_layer_nodes = [Neurode('H' , i , self.input_nodes) for i in range(hidden_layer_node_num)]self.output_node = Neurode('O' , 0 , self.hidden_layer_nodes)self.trainning_data = trainning_dataself.test_data = test_data#逐条训练def trainByItem(self) :cnt = 0while True :cnt += 1learn_rate = 1.0/cntsum_diff = 0.0#对于每⼀条训练数据进⾏⼀次训练过程for item in self.trainning_data :for i in range(self.input_node_num) :self.input_nodes[i].setInput(item[i])item_output = item[-1]nn_output = self.output_node.getOutput()#print('nn_output:' , nn_output)diff = (item_output-nn_output)sum_diff += abs(diff)self.output_node.refreshParas(diff , learn_rate)#print('refreshedParas')#结束条件print(round(sum_diff / len(self.trainning_data) , 4))if sum_diff / len(self.trainning_data) < 0.1 :breakdef getAccuracy(self) :cnt = 0for item in self.test_data :for i in range(self.input_node_num) :self.input_nodes[i].setInput(item[i])item_output = item[-1]nn_output = self.output_node.getOutput()if (nn_output > 0.5 and item_output > 0.5) or (nn_output < 0.5 and item_output < 0.5) :cnt += 1return cnt/(len(self.test_data) + 0.0)主调流程# -*- coding: utf-8 -*-"""Created on Sun Dec 2 14:49:31 2018@author: congpeiqing"""import osfrom SimpleBP import SimpleBPfrom GenData import genDataif not os.path.exists('data'):os.makedirs('data')#构造训练和测试数据data_file = open('data/trainning_data.dat' , 'w')data_file.write(genData())data_file.close()data_file = open('data/test_data.dat' , 'w')data_file.write(genData())data_file.close()#⽂件格式:rec_id,attr1_value,attr2_value,attr3_value,class_id#读取和解析训练数据trainning_data_file = open('data/trainning_data.dat')trainning_data = []for line in trainning_data_file :line = line.strip()fld_list = line.split(',')trainning_data.append(tuple([float(field) for field in fld_list[1:]]))trainning_data_file.close()#读取和解析测试数据test_data_file = open('data/test_data.dat')test_data = []for line in test_data_file :line = line.strip()fld_list = line.split(',')test_data.append(tuple([float(field) for field in fld_list[1:]]))test_data_file.close()#构造⼀个⼆分类⽹络输⼊节点3个,隐层节点10个,输出节点⼀个simple_bp = SimpleBP(3 , 10 , trainning_data , test_data)#训练⽹络simple_bp.trainByItem()#测试分类准确率print('Accuracy : ' , simple_bp.getAccuracy())#训练时长⽐较长,准确率可以达到97%以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
70行Java代码实现深度神经网络算法分享
70⾏Java代码实现深度神经⽹络算法分享对于现在流⾏的深度学习,保持学习精神是必要的——程序员尤其是架构师永远都要对核⼼技术和关键算法保持关注和敏感,必要时要动⼿写⼀写掌握下来,先不⽤关⼼什么时候⽤到——⽤不⽤是政治问题,会不会写是技术问题,就像军⼈不关⼼打不打的问题,⽽要关⼼如何打赢的问题。
程序员如何学习机器学习对程序员来说,机器学习是有⼀定门槛的(这个门槛也是其核⼼竞争⼒),相信很多⼈在学习机器学习时都会为满是数学公式的英⽂论⽂⽽头疼,甚⾄可能知难⽽退。
但实际上机器学习算法落地程序并不难写,下⾯是70⾏代码实现的反向多层(BP)神经⽹络算法,也就是深度学习。
其实不光是神经⽹络,逻辑回归、决策树C45/ID3、随机森林、贝叶斯、协同过滤、图计算、Kmeans、PageRank等⼤部分机器学习算法都能在100⾏单机程序内实现(以后考虑分享出来)。
机器学习的真正难度在于它为什么要这么计算,它背后的数学原理是什么,怎么推导得来的公式,⽹上⼤部分的资料都在介绍这部分理论知识,却很少告诉你该算法的计算过程和程序落地是怎么样的,对于程序员来说,你需要做的仅是⼯程化应⽤,⽽不需要证明出⼀项新的数学计算⽅法。
实际⼤部分机器学习⼯程师都是利⽤别⼈写好的开源包或者⼯具软件,输⼊数据和调整计算系数来训练结果,甚⾄很少⾃⼰实现算法过程。
但是掌握每个算法的计算过程仍然⾮常重要,这样你才能理解该算法让数据产⽣了什么样的变化,理解算法的⽬的是为了达到什么样的效果。
本⽂重点探讨反向神经⽹络的单机实现,关于神经⽹络的多机并⾏化, Fourinone 提供⾮常灵活完善的并⾏计算框架,我们只需要理解透单机程序实现,就能构思和设计出分布式并⾏化⽅案,如果不理解算法计算过程,⼀切思路将⽆法展开。
另外,还有卷积神经⽹络,主要是⼀种降维思想,⽤于图像处理,不在本⽂讨论范围。
神经⽹络过程描述:⾸先,要明确,神经⽹络做的是预测任务,相信你记得⾼中学过的最⼩⼆乘法,我们可以以此做⼀个不严谨但⽐较直观的类⽐:⾸先,我们要得到⼀个数据集和数据集的标记(最⼩⼆乘法中,我们也得到了⼀组组x,y的值)算法根据这个数据集和对应的标记,拟合⼀个能够表达这个数据集的函数参数(也就是最⼩⼆乘法中计算a, b的公式,神经⽹络中不过是这个公式没法直接得到)我们以此得到了拟合的函数(也就是最⼩⼆乘法中的拟合直线y^=ax+b)接下来,带⼊新的数据之后,就可以⽣成对应的预测值y^(在最⼩⼆乘法中,就是带⼊y^=ax+b得到我们预测的y^,神经⽹络算法也是的,只不过求得的函数⽐最⼩⼆乘法复杂得多)。
BP神经网络实现(Java代码)
BP神经网络实现(Java代码)神经网络的原理虽然理解起来不难,但是要是想实现它,还是需要做一些工作的,并且有很多细节性的东西需要注意。
通过参阅各种相关资料,以及参考网络上已有的资源,自己写了一个含有一个隐含层,且只能有一个输出单元的简单的BP网络,经过测试,达到了预期的效果。
需要说明的是,神经网络的每个输入都在[0,1]中,输出也在[0,1]中,在使用神经网络解决实际问题的时候,还需要对实际问题的输入输出进行归一化处理。
另外,尽量不要使得神经网络的输入或输出接近于0或1,这样会影响拟合效果。
我用正弦函数进行了一次测试,效果如图所示:以下是相关的代码:1.神经网络代码[java]view plaincopy1.package pkg1;2.3.import java.util.Scanner;4.5./*6. *7. */8.public class TestNeuro {9.10.private int INPUT_DIM=1;11.private int HIDDEN_DIM=20;12.private double LEARNING_RATE=0.05;13.double [][] input_hidden_weights=new double[INPUT_DIM][HIDDEN_DIM];14.double [] hidden_output_weights=new double[HIDDEN_DIM];15.double[] hidden_thresholds=new double[HIDDEN_DIM];16.double output_threshold;17.18.public static void main(String[]args){19. Scanner in=new Scanner(System.in);20. TestNeuro neuro=new TestNeuro(1,5);21. neuro.initialize();22.for(int i=0;i<10000;i++){23.double[] input=new double[1];24. input[0]=Math.random();25.double expectedOutput=input[0]*input[0];26.//System.out.println("input : "+input[0]+"\t\texpectedOutput : "+expectedOutput);27.//System.out.println("predict before training : "+neuro.predict(input));28. neuro.trainOnce(input, expectedOutput);29.//System.out.println("predict after training : "+neuro.predict(input));30.//in.next();31. }32.while(true){33.//neuro.printLinks();34.double[] input=new double[1];35. input[0]=in.nextDouble();36.double expectedOutput=in.nextDouble();37. System.out.println("predict before training : "+neuro.predict(input));38. neuro.trainOnce(input, expectedOutput);39. System.out.println("predict after training : "+neuro.predict(input));40.41. }42. }43.44.public TestNeuro(int input_dimension,int hidden_dimension){45.this.INPUT_DIM=input_dimension;46.this.HIDDEN_DIM=hidden_dimension;47.this.initialize();48. }49.50.51./**52. * 打印出本神经元网络各层之间的连接权重,以及各个神经元上的阈值的信息。
BP神经网络—java实现
BP神经⽹络—java实现神经⽹络的结构神经⽹络的⽹络结构由输⼊层,隐含层,输出层组成。
隐含层的个数+输出层的个数=神经⽹络的层数,也就是说神经⽹络的层数不包括输⼊层。
下⾯是⼀个三层的神经⽹络,包含了两层隐含层,⼀个输出层。
其中第⼀层隐含层的节点数为3,第⼆层的节点数为2,输出层的节点数为1;输⼊层为样本的两个特征X1,X2.图1 三层神经⽹络在神经⽹络中每⼀个节点的都与上⼀层的所有节点相连,称为全连接。
神经⽹络的上⼀层输出的数据是下⼀层的输⼊数据。
在图中的神经⽹络中,原始的输⼊数据,通过第⼀层隐含层的计算得出的输出数据,会传到第⼆层隐含层。
⽽第⼆层的输出,⼜会作为输出层的输⼊数据。
神经⽹络中的每⼀层(除了输⼊层)都是由神经元组成,也称为节点。
每⼀个神经元都相当于⼀个感知器。
如下图:图2 单个神经元在神经⽹络中,每个节点都将计算出特征矩阵X与权值矩阵的加权和,得到净输⼊e,然后通过激励函数f(e)得到该节点的输出y。
在图1中,每条连线都可以看做是⼀个权值。
在神经⽹络中,可以添加输出层节点的个数来解决多分类问题。
有四个类别需要分类则,则输出层的节点个数可以设为4个节点,每⼀个节点代表⼀个类别。
BP神经⽹络的训练过程神经⽹络的训练过程分为两个过程:1、向前传播得到预测数据;2、反向传播更新权重。
如下图所⽰:图3 神经⽹络的训练过程第⼀步、向前传播得到预测数据:向前传播的过程,即数据从输⼊层输⼊,经过隐含层,输出层的计算得到预测值,预测值为输出层的输出结果。
⽹络层的输出即,该层中所有节点(神经元)的输出值的集合。
我们以图⼀的神经⽹络结构为例,分析向前传播过程。
1.得到隐含层的输出y1,y2,y3:2.获取到第⼆层的隐含层输出y4,y5,输⼊的数据也就是第⼀层隐含层的输出数据y1,y2,y3。
3、通过输出层,得到最后的预测值y。
第⼆步、反向传播更新权重:根据样本的真实类标,计算模型预测的结果与真实类标的误差。
JAVA实现BP神经网络算法
JAVA实现BP神经⽹络算法⼯作中需要预测⼀个过程的时间,就想到了使⽤BP神经⽹络来进⾏预测。
简介BP神经⽹络(Back Propagation Neural Network)是⼀种基于BP算法的⼈⼯神经⽹络,其使⽤BP算法进⾏权值与阈值的调整。
在20世纪80年代,⼏位不同的学者分别开发出了⽤于训练多层感知机的反向传播算法,David Rumelhart和James McClelland提出的反向传播算法是最具影响⼒的。
其包含BP的两⼤主要过程,即⼯作信号的正向传播与误差信号的反向传播,分别负责了神经⽹络中输出的计算与权值和阈值更新。
⼯作信号的正向传播是通过计算得到BP神经⽹络的实际输出,误差信号的反向传播是由后往前逐层修正权值与阈值,为了使实际输出更接近期望输出。
(1)⼯作信号正向传播。
输⼊信号从输⼊层进⼊,通过突触进⼊隐含层神经元,经传递函数运算后,传递到输出层,并且在输出层计算出输出信号传出。
当⼯作信号正向传播时,权值与阈值固定不变,神经⽹络中每层的状态只与前⼀层的净输出、权值和阈值有关。
若正向传播在输出层获得到期望的输出,则学习结束,并保留当前的权值与阈值;若正向传播在输出层得不到期望的输出,则在误差信号的反向传播中修正权值与阈值。
(2)误差信号反向传播。
在⼯作信号正向传播后若得不到期望的输出,则通过计算误差信号进⾏反向传播,通过计算BP神经⽹络的实际输出与期望输出之间的差值作为误差信号,并且由神经⽹络的输出层,逐层向输⼊层传播。
在此过程中,每向前传播⼀层,就对该层的权值与阈值进⾏修改,由此⼀直向前传播直⾄输⼊层,该过程是为了使神经⽹络的结果与期望的结果更相近。
当进⾏⼀次正向传播和反向传播后,若误差仍不能达到要求,则该过程继续下去,直⾄误差满⾜精度,或者满⾜迭代次数等其他设置的结束条件。
推导请见BPNN结构该BPNN为单输⼊层单隐含层单输出层结构项⽬结构介绍⼀些⽤到的类ActivationFunction:激活函数的接⼝BPModel:BP模型实体类BPNeuralNetworkFactory:BP神经⽹络⼯⼚,包括训练BP神经⽹络,计算,序列化等功能BPParameter:BP神经⽹络参数实体类Matrix:矩阵实体类Sigmoid:Sigmoid传输函数,实现了ActivationFunction接⼝MatrixUtil:矩阵⼯具类实现代码Matrix实体类模拟了矩阵的基本运算⽅法。
BP神经网络演示程序及代码说明
BP神经网络演示程序及代码说明为了配合PPT讲解BP神经网络原理的需要,这几天写了这个基于BP神经网络的演示程序,主界面如图:关于BP神经网络的基本原理,我觉得没有太多的必要在这里讲得很细,如果读者不是很清楚,可以先看看相关书籍或论文,可以推荐几个如:1.<<Machine Learning>>的第4章,Tom.M.Mitchell著,此书非常好,把BP原理讲得非常透彻,由其是误差的公式推导,比别的书都说得清楚一点,该书出过中文版,由曾华军等人翻译.2.<<Explorations in Parallel Distributed Processing, A Handbook of Models, Programs, and Exercises >>,这本手册第5章就是历史上第一次提出将BP算法应用于神经网络的,非常值得一看.网上能下到最新版(第二版的DRAFT版)的PDF,时间是2010年2月份的,很新了.3.韩力群教授写的几本神经网络的书,都很不错,讲得比较浅显易懂4.<<Neural Networks A Systematic Introduction>>,这本书的第7章讲BP,讲得很细,值得看,电子版网上能下到.5.网上的教程也不少,比如这个: /articles/backpropagation-neural-network/6.实在理解不了,试着联系我吧,我也乐意与您沟通,我的联系方式在这个演示程序的About对话框内能找到.在这里主要提几点:1.BP神经网络属于监督学习范畴,除了给定训练样本数据外,必须给出该样本对应的标记2.学习率和冲量项设置有一定讲究,不能随意,大了可能不收敛,小了收敛慢3.隐藏层节点个数需要多少,没有理论指导,都是经验指导4.是采用标准梯度下降,还是delta法则,关系不大,只要学习率足够小,delta法则可逼近标准梯度下降法.5.BP神经网络的性能和样本训练前的前期处理有密切关系,识别率低,不一定是网络不好,可能是特征提取不好,特征组合有问题,等等,很多原因.下面讲一下,怎么运行这个演示程序:1.下载本文附带的压缩包,并解压至某路径,比如: D:\2.注册控件,可以双击那个reg_ax.bat文件即可,它会自动注册同一路径下的facerecognization.dll文件,这是我写的用于显示PGM图片的ActiveX控件,不注册的话,就不能显示图片了,显示效果如上面的截图(所有图片分辩率为32*30,所以有点小),注册后就不要移动这个dll文件,否则需要再次注册(明白COM组件的工作原理就会知道了)3.通过1,2两步,现在就可以正常运行BPNNTest.exe这个程序了.运行后界面如上图,不过这时还没有训练神经网络.下载人脸库:BP网络需要先训练,我写程序时使用的是CMU的人脸库,下载地址是:/afs//project/theo-8/faceimages/faces_4.tar.Z人脸图片用的是32*30分辨率,PGM格式的图片,文件名命名规则是:人名_人脸朝向_心情_是否戴太阳镜_4.pgm,例如:danieln_left_angry_open_4.pgm,因此,从这个文件名中,我们可以得到四个信息,分别是:人名,朝向,心情,是否戴太阳镜,而文件本身的数据可以作为训练网络的特征向量,而这四个信息则均可以用于特征向量对应的标记.将上面链接下载的人脸库解压至某一路径下,如D盘根目录下,会发现faces_4文件夹内有很多子文件夹,分别名为:an2i,at33...等,而这些子文件夹内就是各自的pgm图片文件.因为,BP神经网络需要训练和测试两个样本集,你可以随便把faces_4中的某个(或某几个)文件夹从中剪切出来,作为测试样本集,而其余的作为训练样本集.比如,将tammo文件夹从中剪切到D:\下.最终形成的目录结构应该类似于这样:训练样本集: D:\faces_4\很多子文件夹\很多pgm文件测试样本集: D:\tammo\很多pgm文件注意faces_4内都是目录,而tammo内都是pgm文件,这很重要,因为我现在程序写得就是按这个方式处理的.准备工作就续,现在就可以训练和测试网络了:1.选择训练集点击对话框左上角的Select按钮,弹出对话框,先择之前解压后的faces_4文件夹:选中faces_4文件夹后,点击OK按钮(你的电脑可能是"确定"按钮),程序会读取文件夹内所含PGM图片信息,并显示读到的第一张图片.2.训练BP网络2.1 你可以选择训练BP网络去学习什么功能,默认是学习Direction,即人脸朝向,你可以通过对话框左上角的ComboBox选择四种类型:人名,朝向,心情,是否戴太阳镜2.2 选择迭代次数(iterate time)或停止迭代误差(Stop Error),两者默认值为100000和0.003,即分别表示迭代到100000次时停止(不管误差多少),或迭代直到误差小于指定值时停止(可能会迭代很多很多次).这里说明一下,程序里,我为了让每张人脸图片都被训练到相同次数,使得这里的100000次是训练的下界,到达100000次迭代时, 可能还没有训练到样本集中最后一个样本,因此会多训练几次,如最上面的截图中,一共迭代了100215次.另外,由于程序使用的是delta法则来训练本样,这里的误差是每个样本训练完后的平均误差,而不是当前训练图片的误差.2.3 确定隐藏层神经元个数(Hidden layer units),默认为3个(网络只含一个隐藏层,多层网络其实也一样),由于所需隐单元个数的多少目前仍而理论依据,因此当隐层个数太少,无法达到识别率时,考虑调大一点,不过由于隐层个数调大后,权值会增加,训练会明显变慢.另外,当BP网络要学习目标比较复杂时,隐层单元个数不因过少,不然可能无法收敛.2.3* 为什么不用设置输入层和输出层单元个数? 因为,为了方便,程序自动读取图片,分析文件的分辩率自动确定输入层单元个数(没有做特征提取,就是图片像素数),通过分析样本集中目标值的可取个数,自动确定输出层单元个数,比如,分析样本集文件后,得到所有Direction可取的值就只有4种,于是,如果采用"1of n"方式设计输出层单元(本程序采用的方式),就有4个输出单元.2.4 确定学习速率(learning rate)和冲量(momentum),默认值都是0.3,我没尝试过很多值,大概设了一下,不要设太大,可能导致无法收敛,太小会收敛很慢,是很慢很慢,不信你把两个值都调成0.03,迭代100000次后的误差仍然很大.2.5 参数都设好了,点击"Train"按钮开始训练吧,对话框下方的"Status"会动态显示当前迭代的次数,而图片下方也会动态更新当前迭代中的图片路径.要说明的是:如果迭代次数少,很快就会训练完,如果次数多的话,就看你电脑的性能了,在我的老本本(T40p)上,迭代100000次,大概是90几秒,现在的电脑速度都很快,训练时间应该会更短.虽然我没有训练到将误差降到小于0.003以下(我的电脑老,且以上参数没有尝试优化过),但在训练100000次左右或更多的时候,识别精度已经可以达到80%左右,或以上(这和测试样本有关),另外由于创建神经网络时,我让隐层至输出层权值随机生成,就算同样训练100000次,结束时的误差也不会一样.总之一句,你有足够时间,并且电脑足够快,一是尝试调整学习率和冲量,二是迭代遍数多一点,让误差可以再小一点,这样识别精度可能会更高.2.5*为什么上面说是"可能",因为过度追求小的误差会导致过度拟合,这里不展开详述.2.6 训练完后,左边的列表框(Error List)会列出训练过程的一些信息,包括这次训练总共花了多少时间(最上一行),第几次(time)迭代,当前迭代误差(cur_err),平均误差(avg_err).3.测试BP网络测试功能,位于主对话框右上角,我做了两个,上面的一组"select"和"varify"按扭用于测试单张人脸图片,下面一组"select"和"varify"按扭用于批量测试人脸图片,并统计准确率.3.1 测试单张图片3.1.1 点右上第一个"Select"按钮弹出打开文件对话框:选中一张没有训练过的人脸图片(pgm格式),点击"Open"按钮(你的电脑可能是"打开"铵钮)3.1.2 然后点击右上的"Varify"按钮,会显示网络对选中图片的测试结果,结果显示在下面的列表框(Varify Result)内,内容如下:解释一下: 一条横线上面的四行表示: 网络第几个输出单元=值,横线下面的straight表示根据输出层每个单元的值得出的结果:人脸朝向是正面(straight).正确与否可通过与文件名相应信息比较可知.3.2 人脸图片批量测试3.2.1 点右上第二个"Select"按钮弹出打开文件夹对话框:选择之前存放测试样本集人脸图片的文件夹,如D:\tammo,这个文件夹内都是用于测试的pgm人脸图片. 如果操作无误,按钮左边会显示选中文夹中的第一张人脸图片.3.2.2 然后点击下面的"Varify"按钮,会显示网络对选中文夹内所有人脸图片的测试结果,结果显示在下面的列表框(Varify Result)内,内容形式如下:解释一下:由于文夹内可能会有很多人脸文件,于输出信息会有很多,但每个文件的测试输出信息都如3.1.2节中类似,要说明的有三点:(1)最上面输出被测试文件名.(2)输出结果和正确结果有比较, 如:straight<-->up,左边straight为网络输出结果,右边up为正确结果(从文件名中获取),由于两个内容不同,所以该图片测试结果是错误,即WRONG,如正确则显示RIGHT.(3)最后显示总的正确率,如上图:Accurecy:83.33%.4.保存和读取BP网络训练结果花了好长时间练训的网络,关闭软件后再打开又要重新再训练,太伤心了,于是我做了保存与读取功能.4.1 保存功能先要训练好网络,然后点击左下角的"Save"按钮,弹出如下保存对话框:选择要保存的径,取个好听的名字,然后点"Save"按钮,搞定.4.2 从已保存文件中加载BP网络点击左下角的"Load"按钮,弹出如下打开对话框:找到相应的.bp后缀的文件,点"Open",加载成功后,下方的"Status:"会显示:Load from 某路径文件名.到这里,这个演示程序的使用讲完了,下面简单讲讲程序代码的实现5.BP神经网络的实现BP神经网络的实现嘛,说实话,比较简单,只要你理解了BP的原理,加上一定的编程能力,实现这个算法就不难了,我用CBPNN类封装了BP网络,除了实现基本的BP网络的功能之外,添加了保存和加载网络的功能.目前只实现3层BPNN,下面把源码放上来:5.1 CBPNN类的头文件:/*This BPNN class is created by Vincent Gao(c_gao),2009-10-31.you cat use it as any purposes as you want,but you must keepthis comment on these files,if you have any problems,pleasecontact me at:e-mail: c_gao@blog: this class can create a three lays BackPropogation NeuralNetwork,to create it you can call the InitBPNN() function,to train the network,call Train().if you want to use this code in your project,please tell me thatthrough my e-mail. thanks.*/#pragma once#include <vector>#include <string>#define DEFAULT_ETA 0.05 //默认学习率#define DEFAULT_MOMENTUM 0 //默认冲量#define BPNN_SA VEFILE_FLAG "BPNN" //BP网络保存文件的标记#define BPNN_SA VEFILE_SEPCHAR '\n' //保存文件的分隔符#define ABS(x) (x)>0?(x):(-(x))typedef std::vector<std::pair<std::string,std::vector<double> > > target_type;class CBPNN{public:CBPNN(void);~CBPNN(void);public:bool InitBPNN(int nInput,int nOutput,int nHidden);bool LoadInputUnit(const double* data,int count,double scale);bool LoadTarget(const double* data,int count,double scale=1.0);double Train(double eta,double momentum);void Test(const double* data,int nDimentions,double scale,std::vector<double>& vecOutput);const double* GetOutput();bool SaveBPNNFile(const char* sSavePath,const char* sTargetName,int nIterateTime,double fStopError,target_type* pvecTarget=NULL);bool LoadBPNNFile(const char* sSavePath,target_type* pvecTarget);protected:void ReleaseBPNN();double Sigmoid(double x);//激活函数void LayerForward();double OutputError();double HiddenError();void AdjustWeights();protected:int m_nInput;int m_nOutput;int m_nHidden;double* m_InputUnit;double* m_HiddenUnit;double* m_OutputUnit;//即如图(先保存o1单元的所有权,再保存o2的权,上层同理)// output layer o// / \// hidden layer o1 o2// /|\// input layer o o o//最下层为输入层,最上层为输出层,即网络走向:从下向上double* m_I2HWeight;double* m_H2OWeight;double* m_preI2HWeight;double* m_preH2OWeight;double* m_OutputError;double* m_HiddenError;double* m_Target;double m_eta;//learning ratedouble m_momentum;//momentum for updating the weight};简单说明:激活函数使用sigmoid函数,输入层至隐藏层权值保存在m_I2HWeight 内,隐藏层至输出层权值保存在m_H2OWeight 内,m_preI2HWeight和m_preH2OWeight记录上次迭代中的delta权值,用于计算权值更新公式中的冲量项.m_OutputError和m_HiddenError分别保存输出层和隐藏层的误差.m_InputUnit,m_HiddenUnit和m_OutputUnit分别保存输入向量值,隐藏层输出值和输出层输出值,m_Target用于保存目标向量值.m_eta和m_momentum分别是学习率和冲量.5.2 CBPNN类的源码(CPP)文件#include "stdafx.h" //如果不用VC,或用VC但不用预编译头,请不要include stdafx.h这个文件#include "BPNN.h"#include "time.h"#include "math.h"CBPNN::CBPNN(void){m_nInput=0;m_nOutput=0;m_nHidden=0;m_InputUnit=NULL;m_HiddenUnit=NULL;m_OutputUnit=NULL;m_I2HWeight=NULL;m_H2OWeight=NULL;m_OutputError=NULL;m_HiddenError=NULL;m_Target=NULL;m_preI2HWeight=NULL;m_preH2OWeight=NULL;m_eta=m_momentum=0.0;}CBPNN::~CBPNN(void){ReleaseBPNN();}bool CBPNN::InitBPNN(int nInput,int nOutput,int nHidden) {ReleaseBPNN();m_nInput=nInput+1;m_nOutput=nOutput;m_nHidden=nHidden+1;m_InputUnit = new double[m_nInput];if(!m_InputUnit)return false;m_OutputUnit= new double[m_nOutput];if(!m_OutputUnit)return false;m_HiddenUnit= new double[m_nHidden];if(!m_HiddenUnit)return false;m_OutputError= new double[m_nOutput];if(!m_OutputError)return false;m_HiddenError= new double[m_nHidden];if(!m_HiddenError)return false;m_Target= new double[m_nOutput];if(!m_Target)return false;memset(m_InputUnit,0,sizeof(double)*(m_nInput));memset(m_OutputUnit,0,sizeof(double)*(m_nOutput));memset(m_HiddenUnit,0,sizeof(double)*(m_nHidden));memset(m_OutputError,0,sizeof(double)*(m_nOutput));memset(m_HiddenError,0,sizeof(double)*(m_nHidden));memset(m_Target,0,sizeof(double)*(m_nOutput));int nI2HW=(m_nHidden-1)*(m_nInput);int nH2OW=(m_nHidden)*(m_nOutput);m_I2HWeight= new double[nI2HW];if(!m_I2HWeight)return false;m_H2OWeight= new double[nH2OW];if(!m_H2OWeight)return false;srand( (unsigned)time( NULL ) );double r=0.0;int i=0;for(i=0; i<nI2HW; i++)m_I2HWeight[i]=0;//rand()*1.0/RAND_MAX;//0.000005;//-0.005+rand()*1.0/RAND_ MAX;//-0.05到0.05之间for(i=0; i<nH2OW; i++)m_H2OWeight[i]=rand()*1.0/RAND_MAX/100;//rand()*1.0/RAND_MAX/10000;//-0.5 +rand()*1.0/RAND_MAX;m_preI2HWeight= new double[nI2HW];m_preH2OWeight= new double[nH2OW];memset(m_preI2HWeight,0,sizeof(double)*nI2HW);memset(m_preH2OWeight,0,sizeof(double)*nH2OW);// memset(m_I2HWeight,0,sizeof(double)*nInput*nHidden);// memset(m_H2OWeight,0,sizeof(double)*nHidden*nOutput);m_eta=DEFAULT_ETA;m_momentum=DEFAULT_MOMENTUM;return true;}void CBPNN::ReleaseBPNN(){if(m_InputUnit)delete [] m_InputUnit;if(m_HiddenUnit)delete [] m_HiddenUnit;if(m_OutputUnit)delete [] m_OutputUnit;if(m_I2HWeight)delete [] m_I2HWeight;if(m_H2OWeight)delete [] m_H2OWeight;if(m_OutputError)delete [] m_OutputError;if(m_HiddenError)delete [] m_HiddenError;if(m_Target)delete[] m_Target;if(m_preH2OWeight)delete m_preH2OWeight;if(m_preI2HWeight)delete m_preI2HWeight;m_InputUnit=NULL;m_HiddenUnit=NULL;m_OutputUnit=NULL;m_I2HWeight=NULL;m_H2OWeight=NULL;m_OutputError=NULL;m_HiddenError=NULL;m_Target=NULL;m_preH2OWeight=NULL;m_preI2HWeight=NULL;}bool CBPNN::LoadInputUnit(const double* data,int count,double scale) {if(count != m_nInput-1)return false;//m_InputUnit[0] 即x0 始终为1for(int i=0; i<count; i++)m_InputUnit[i+1]=data[i]/scale;m_InputUnit[0]=1.0;return true;}bool CBPNN::LoadTarget(const double* data,int count,double scale){if(count != m_nOutput)return false;//m_Target[0] 即x0 始终为1for(int i=0; i<count; i++)m_Target[i]=data[i]/scale;return true;}double CBPNN::Sigmoid(double x){return (1.0 / (1.0 + exp(-x)));}void CBPNN::LayerForward(){double sum;int i=0,j=0;m_InputUnit[0] = 1.0;for (i = 1; i < m_nHidden; i++){sum = 0.0;for (j = 0; j < m_nInput; j++)sum += m_I2HWeight[(i-1)*m_nInput+j] * m_InputUnit[j];//按.h文件中的顺序格式来访问weight[i][j]m_HiddenUnit[i] = Sigmoid(sum);}//////////////////////////////////////////////////////////////////////////m_HiddenUnit[0]=1.0;for(i=0; i < m_nOutput; i++){sum=0.0;for(j=0; j < m_nHidden; j++)sum+=m_H2OWeight[i*m_nHidden+j] * m_HiddenUnit[j];m_OutputUnit[i]=Sigmoid(sum);}}double CBPNN::OutputError(){double o, t, errsum;errsum = 0.0;for (int i = 0; i < m_nOutput; i++){o = m_OutputUnit[i];t = m_Target[i];m_OutputError[i] = o * (1.0 - o) * (t - o);errsum += ABS(m_OutputError[i]);}return errsum;}double CBPNN::HiddenError(){double h, sum, errsum;errsum = 0.0;//对网络的每个隐藏单元计算它的误差项for (int i = 1; i < m_nHidden; i++){h = m_HiddenUnit[i];sum = 0.0;for (int j= 0; j < m_nOutput; j++){sum += m_OutputError[j] * m_H2OWeight[j*m_nOutput+i];//按.h文件中的顺序格式来访问m_H2OWeight[i][j]}m_HiddenError[i] = h * (1.0 - h) * sum;errsum += ABS(m_HiddenError[i]);}return errsum;}void CBPNN::AdjustWeights(){int i=0,j=0;double delta_w=0.0;for(j=0; j<m_nOutput; j++){for(i=0; i<m_nHidden; i++){delta_w = ( ( m_eta * m_OutputError[j] * m_HiddenUnit[i])+(m_momentum*m_preH2OWeight[j*m_nHidden+i]) );m_H2OWeight[j*m_nHidden+i]+=delta_w;m_preH2OWeight[j*m_nHidden+i]=delta_w;}}//////////////////////////////////////////////////////////////////////////for(j=1; j<m_nHidden; j++){for(i=0; i<m_nInput; i++){delta_w=( ( m_eta * m_HiddenError[j] * m_InputUnit[i])+(m_momentum*m_preI2HWeight[(j-1)*m_nInput+i]) );m_I2HWeight[(j-1)*m_nInput+i]+=delta_w;m_preI2HWeight[(j-1)*m_nInput+i]=delta_w;}}}double CBPNN::Train(double eta,double momentum){m_eta=eta;m_momentum=momentum;double err_o=0.0;double err_h=0.0;double err=0.0;//1.LayerForward();//2.err_o=OutputError();err_h=HiddenError();//3.AdjustWeights();err=err_o+err_h;return err;}const double* CBPNN::GetOutput(){return m_OutputUnit;}void CBPNN::Test(const double* data,int nDimentions,double scale,std::vector<double>& vecOutput){LoadInputUnit(data,nDimentions,scale);LayerForward();vecOutput.clear();for(int i=0; i<m_nOutput; i++){vecOutput.push_back(m_OutputUnit[i]);}}//将训练好的神经网络保存至文件bool CBPNN::SaveBPNNFile(const char* sSavePath,const char* sTargetName,int nIterateTime,double fStopError,target_type* pvecTarget){FILE* fp=fopen(sSavePath,"w");if(fp == NULL)return false;if(pvecTarget && pvecTarget->size() <=0 )return false;if(pvecTarget && ((*pvecTarget)[0].second).size() <= 0 )return false;if(pvecTarget && ((*pvecTarget)[0].second).size() != m_nOutput)return false;int i=0;fprintf(fp,"%s%c",BPNN_SA VEFILE_FLAG,BPNN_SA VEFILE_SEPCHAR);fprintf(fp,"%s%c",sTargetName,BPNN_SA VEFILE_SEPCHAR);//"Direction" or other Targetfprintf(fp,"%d%c",nIterateTime,BPNN_SA VEFILE_SEPCHAR);//Iterate Timefprintf(fp,"%lf%c",fStopError,BPNN_SA VEFILE_SEPCHAR);//fStopError,注意lf符号fprintf(fp,"%lf%c",m_eta,BPNN_SA VEFILE_SEPCHAR);//eta, the learning ratefprintf(fp,"%lf%c",m_momentum,BPNN_SA VEFILE_SEPCHAR);//momentumfprintf(fp,"%d%c",m_nInput,BPNN_SAVEFILE_SEPCHAR);//count of input unitfprintf(fp,"%d%c",m_nHidden,BPNN_SA VEFILE_SEPCHAR);//count of input unitfprintf(fp,"%d%c",m_nOutput,BPNN_SA VEFILE_SEPCHAR);//count of input unitint nI2HW=(m_nHidden-1)*(m_nInput);int nH2OW=(m_nHidden)*(m_nOutput);fprintf(fp,"%d%c",nI2HW,BPNN_SA VEFILE_SEPCHAR);fprintf(fp,"%d%c",nH2OW,BPNN_SA VEFILE_SEPCHAR);if(pvecTarget != NULL){for(target_type::iterator it=pvecTarget->begin(); it!=pvecTarget->end(); it++){fprintf(fp,"%s%c",it->first.c_str(),BPNN_SA VEFILE_SEPCHAR);for(i=0; i<m_nOutput; i++)fprintf(fp,"%lf%c",(it->second)[i],BPNN_SA VEFILE_SEPCHAR);}}//保存三层单元值xij// for(i=0; i<m_nInput; i++)// fprintf(fp,"%lf%c",m_InputUnit[i],BPNN_SA VEFILE_SEPCHAR);// for(i=0; i<m_nHidden; i++)// fprintf(fp,"%lf%c",m_HiddenUnit[i],BPNN_SA VEFILE_SEPCHAR); // for(i=0; i<m_nOutput; i++)// fprintf(fp,"%lf%c",m_OutputUnit[i],BPNN_SA VEFILE_SEPCHAR);//保存两层权值wijfor(i=0; i<nI2HW; i++)fprintf(fp,"%lf%c",m_I2HWeight[i],BPNN_SA VEFILE_SEPCHAR);for(i=0; i<nH2OW; i++)fprintf(fp,"%lf%c",m_H2OWeight[i],BPNN_SA VEFILE_SEPCHAR);fclose(fp);return true;}//从文件读取网络的各参数值bool CBPNN::LoadBPNNFile(const char* sSavePath,target_type* pvecTarget) {FILE* fp=fopen(sSavePath,"r");if(fp == NULL)return false;char temp[100];fscanf(fp,"%s",temp);if(strcmp(temp,BPNN_SA VEFILE_FLAG) != 0){fclose(fp);return false;}fscanf(fp,"%s",temp);int nIterateTime;double fStopError;double eta;double momentum;int nInput;int nHidden;int nOutput;int nI2HW;int nH2OW;fscanf(fp,"%d",&nIterateTime);fscanf(fp,"%lf",&fStopError);fscanf(fp,"%lf",&eta);fscanf(fp,"%lf",&momentum);fscanf(fp,"%d",&nInput);fscanf(fp,"%d",&nHidden);fscanf(fp,"%d",&nOutput);fscanf(fp,"%d",&nI2HW);fscanf(fp,"%d",&nH2OW);//根据读到的参数创建BP神经网络InitBPNN(nInput-1,nOutput,nHidden-1);int i=0;std::string target_name;double ftemp;std::vector<double> target_vector;if(pvecTarget != NULL){pvecTarget->clear();for(i=0; i<nOutput; i++){fscanf(fp,"%s",temp);target_name=temp;target_vector.clear();for(int j=0; j<m_nOutput; j++){fscanf(fp,"%lf",&ftemp);target_vector.push_back(ftemp);}pvecTarget->push_back(std::pair<std::string,std::vector<double> > (target_name,target_vector));}}for(i=0; i<nI2HW; i++){fscanf(fp,"%lf",&(m_I2HWeight[i]));// sprintf(a,"%lf",m_I2HWeight[i]);// MessageBox(NULL,A2T(a),_T(""),MB_OK);}for(i=0; i<nH2OW; i++)fscanf(fp,"%lf%c",&(m_H2OWeight[i]));fclose(fp);return true;}简单说明:我注释写得不多,而且一般都是中英文结合(可能包含语法错误^_^),需要说明的一点是,输入层单元的第一个结点和隐藏层的第一个结点都为偏置单元,注意看 LayerForward()里的两行:m_InputUnit[0] = 1.0;和m_HiddenUnit[0] = 1.0; 就是了,偏置的输出永远为1,这里固定就行.而输出层是没有偏置单元的.那么对于上面演示程序启动后,在不改任何参数的情况下(3个隐单元和4个输出单元),构造的网络如下图:上图中,我将偏置单元用蓝色实心圆圈表示.其输出固定为1.05.3 怎么使用该CBPNN类很容易,在实例化对象后,分两训练(从文件加载也可以)和测试两步走:5.3.1 训练第一步,调用InitBPNN(输入层单元数,输出层单元数,隐层单元数),注意这里的单元数不包括偏置单元.第二步,调用LoadInputUnit(), 第一参数为指向导入输入层数据的指针,第二个参数为数据的个数(不包括偏置单元),第三个参数是对导入数据的缩放参数,因为,PGM图片是256阶灰度的,而现在要求(有很多理由)输入层的值为0~1之间的数,于是用255作为第三个参数可将值缩放在0~1之内.第三步, 调用LoadTarget(),参数同LoadInputUnit(),意思也一样.第四步, 调用Train(学习率,冲量参数)5.3.1 测试训练网络或从保存的网络加载以后:第一步,调用Test(), 前三个参数同LoadInputUnit(),最后一个参数是返回型变量,这里用了STL的vector作为输出向量的容器第二步,在第一步调用后,得到返回的第四个参数就是BP网络的测试结果.写了那么多,也不知道说明白了没有,本来还想讲一下PGM文件图片格式的,现在不想讲了,有机会再讲吧,源代码在压缩包内common文件夹中的PGMFile.cpp和PGMFile.h两个文件内,自己看吧,很简单的.下面讲一下附件源代码怎么编译使用6.源代码的编译与运行压缩包内facerecognization.rar为所有源码,开发环境是VC6,一共两个工程,第一个工程facerecognization是显示PGM图片的ActiveX控件,第二个工程BPNNTest演示程序,由于我在程序里用了很多STL容器,而VC6对标准STL的支持非常糟糕,因此我使用是的sgi的stl3.3版,需要下载并配置到VC6内,另外,演示程序BPNNTest工程,是基于WTL的(而不是MFC),因此也要下载WTL并安装.6.1 给VC6配置sgi的stl如果你用的是VC6以后的版本,这步可以跳过,因为VC6以后的版本都对标准STL支持得很高sgi-stl是开源且免费的,从sgi官网地地: /tech/stl/download.html 下载下来后,解压至某路径下,然后打开VC6,选菜单Tools->Options,在弹出的对话框内点选Directories 标签页,Show directories for:处要选择Include files,然后将刚才stl的路径添加进去,并移到最上面(这样就优先使用sgi的stl,而不是VC6的stl).完成后如下图这样:6.2 安装WTL7.1,请先关掉VCWTL也是开源的,而且还是微软的开源项目,最好下个WTL7.1版:/tools/downtools.asp?id=131, 如果你用的是VC6以后的版本,可以考虑去sourceforge下载一个最新版的WTL: :/projects/wtl/files/ ,安装过程如下:6.2.1 运行下载回来的exe文件或解压zip文件(视你下载的文件类型而定)至某一路径,如D:\6.2.2 进入解压后的路径里,找到AppWiz60文件夹,运行里面的setup.js 脚本程序,将自动给你的VC添加一个WTL工程模板(新建工程时就会看到).6.2.3 退回上一级目录,进入include目录,将其中的所有文件拷入VC6系统include目录内,我的位置在: C:\Program Files\Microsoft Visual Studio\VC98\Include .至此,搞定,可以编译源码了!不写了,累死了,写了一整天…。
学习日记(2.19BP神经网络完整代码解读)
学习⽇记(2.19BP神经⽹络完整代码解读)BP⽹络实现⼿写数字识别代码解读1.添加偏置#添加偏置temp=np.ones([X.shape[0],X.shape[1]+1])temp[:,0:-1]=XX=tempnp.ones()函数numpy.ones()函数的功能是返回⼀个全都是1的N维数组,其中shape(⽤来指定返回数组的⼤⼩)、dtype(数组元素的类型)、order(是否以内存中的C或Fortran连续(⾏或列)顺序存储多维数据)。
后两个参数都是可选的,⼀般只需设定第⼀个参数。
shape[]的功能是: 0查询⾏数,1查询列数temp=np.ones([X.shape[0],X.shape[1]+1])#在这⾥的作⽤就是先产⽣⼀个和X⼀样多⾏但是多⼀列的全部是1的数组temp[:,0:-1]=X#⽤X数组的值覆盖整个新数组的所有⾏,第⼀列到最后⼀列,最后⼀列依旧全是1X=temp#再把整个增加⼀列偏置的数组给数据集X,得到带有偏置的数据集举⼀个⼩例⼦:import numpy as npfrom sklearn.datasets import load_digitsfrom sklearn.preprocessing import LabelBinarizerfrom sklearn.model_selection import train_test_splitX=np.array([[1,2,3],[1,2,3],[1,2,3]])#使⽤python中的数组使⼀定要先numpy.arrayprint('原来的数组:\n',X)temp=np.ones([X.shape[0],X.shape[1]+1])temp[:,0:-1]=XX=tempprint('添加偏置后的数组:\n',X)运⾏结果:2.随机选取⼀个数据并将其转换为2维i =np.random.randint(X.shape[0])#随机选取⼀个数据x=[X[i]]x=np.atleast_2d(x)#转为2维数据numpy.random.randint(low, high=None, size=None, dtype='l')⽤于产⽣随机数,随机数组low: int⽣成的数值最低要⼤于等于low。
人工智能-BP神经网络算法的简单实现
人工神经网络是一种模仿人脑结构及其功能的信息处理系统,能提高人们对信息处理的智能化水平。
它是一门新兴的边缘和交叉学科,它在理论、模型、算法等方面比起以前有了较大的发展,但至今无根本性的突破,还有很多空白点需要努力探索和研究。
1 人工神经网络研究背景神经网络的研究包括神经网络基本理论、网络学习算法、网络模型以及网络应用等方面。
其中比较热门的一个课题就是神经网络学习算法的研究.近年来己研究出许多与神经网络模型相对应的神经网络学习算法,这些算法大致可以分为三类:有监督学习、无监督学习和增强学习。
在理论上和实际应用中都比较成熟的算法有以下三种:(1) 误差反向传播算法(Back Propagation,简称BP 算法);(2)模拟退火算法;(3) 竞争学习算法。
目前为止,在训练多层前向神经网络的算法中,BP 算法是最有影响的算法之一。
但这种算法存在不少缺点,诸如收敛速度比较慢,或者只求得了局部极小点等等。
因此,近年来,国外许多专家对网络算法进行深入研究,提出了许多改进的方法。
主要有:(1) 增加动量法:在网络权值的调整公式中增加一动量项,该动量项对某一时刻的调整起阻尼作用。
它可以在误差曲面出现骤然起伏时,减小振荡的趋势,提高网络训练速度;(2) 自适应调节学习率:在训练中自适应地改变学习率,使其该大时增大,该小时减小。
使用动态学习率,从而加快算法的收敛速度;(3) 引入陡度因子:为了提高BP 算法的收敛速度,在权值调整进入误差曲面的平坦区时,引入陡度因子,设法压缩神经元的净输入,使权值调整脱离平坦区。
此外,很多国内的学者也做了不少有关网络算法改进方面的研究,并把改进的算法运用到实际中,取得了一定的成果:(1)王晓敏等提出了一种基于改进的差分进化算法,利用差分进化算法的全局寻优能力,能够快速地得到BP 神经网络的权值,提高算法的速度;(2) 董国君等提出了一种基于随机退火机制的竞争层神经网络学习算法,该算法将竞争层神经网络的串行迭代模式改为随机优化模式,通过采用退火技术避免网络收敛到能量函数的局部极小点,从而得到全局最优值;(3) 赵青提出一种分层遗传算法与BP 算法相结合的前馈神经网络学习算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
BP神经网络实现(Java代码)神经网络的原理虽然理解起来不难,但是要是想实现它,还是需要做一些工作的,并且有很多细节性的东西需要注意。
通过参阅各种相关资料,以及参考网络上已有的资源,自己写了一个含有一个隐含层,且只能有一个输出单元的简单的BP网络,经过测试,达到了预期的效果。
需要说明的是,神经网络的每个输入都在[0,1]中,输出也在[0,1]中,在使用神经网络解决实际问题的时候,还需要对实际问题的输入输出进行归一化处理。
另外,尽量不要使得神经网络的输入或输出接近于0或1,这样会影响拟合效果。
我用正弦函数进行了一次测试,效果如图所示:以下是相关的代码:1.神经网络代码[java]view plaincopy1.package pkg1;2.3.import java.util.Scanner;4.5./*6.*7.*/8.public class TestNeuro{9.10.private int INPUT_DIM=1;11.private int HIDDEN_DIM=20;12.private double LEARNING_RATE=0.05;13.double[][]input_hidden_weights=new double[INPUT_DIM][HIDDEN_DIM];14.double[]hidden_output_weights=new double[HIDDEN_DIM];15.double[]hidden_thresholds=new double[HIDDEN_DIM];16.double output_threshold;17.18.public static void main(String[]args){19.Scanner in=new Scanner(System.in);20.TestNeuro neuro=new TestNeuro(1,5);21.neuro.initialize();22.for(int i=0;i<10000;i++){23.double[]input=new double[1];24.input[0]=Math.random();25.double expectedOutput=input[0]*input[0];26.//System.out.println("input:"+input[0]+"\t\texpectedOutput:"+expectedOutput);27.//System.out.println("predict before training:"+neuro.predict(input));28.neuro.trainOnce(input,expectedOutput);29.//System.out.println("predict after training:"+neuro.predict(input));30.//in.next();31.}32.while(true){33.//neuro.printLinks();34.double[]input=new double[1];35.input[0]=in.nextDouble();36.double expectedOutput=in.nextDouble();37.System.out.println("predict before training:"+neuro.predict(input));38.neuro.trainOnce(input,expectedOutput);39.System.out.println("predict after training:"+neuro.predict(input));40.41.}42.}43.44.public TestNeuro(int input_dimension,int hidden_dimension){45.this.INPUT_DIM=input_dimension;46.this.HIDDEN_DIM=hidden_dimension;47.this.initialize();48.}49.50.51./**52.*打印出本神经元网络各层之间的连接权重,以及各个神经元上的阈值的信息。
53.*/54.void print(){55.System.out.println("隐含层阈值:");56.for(int i=0;i<HIDDEN_DIM;i++){57.System.out.print(hidden_thresholds[i]+"");58.}System.out.println();59.System.out.println("输出层阈值:");60.System.out.println(output_threshold);61.62.System.out.println("连接权重:*********************");63.System.out.println("输入层与隐含层的连接");64.for(int i=0;i<INPUT_DIM;i++){65.for(int j=0;j<HIDDEN_DIM;j++){66.System.out.print(input_hidden_weights[i][j]+"");67.}System.out.println();68.}69.System.out.println("隐含层到输出层的连接");70.for(int i=0;i<HIDDEN_DIM;i++){71.System.out.print(hidden_output_weights[i]+"");72.}System.out.println();73.System.out.println("*********************************");74.}75.76./**77.*初始化,对所有的权值产生一个(0,1)之间的随机double型值78.*/79.void initialize(){80.81.//输入层到隐含层的连接权重82.for(int i=0;i<INPUT_DIM;i++){83.for(int j=0;j<HIDDEN_DIM;j++){84.input_hidden_weights[i][j]=Math.random();85.}86.}87.//隐含层到输出层的连接权重88.for(int i=0;i<HIDDEN_DIM;i++){89.hidden_output_weights[i]=Math.random();90.}91.//隐含层的阈值92.for(int i=0;i<HIDDEN_DIM;i++){93.hidden_thresholds[i]=Math.random();94.}95.//输出层的阈值96.output_threshold=Math.random();97.}98.99./**100.*激励函数101.*@param x102.*@return103.*/104.double function(double x){105.return1/(1+Math.pow(Math.E,-x));106.}107.108./**109.*给定一个输入,进行预测110.*@param input111.*@return112.*/113.double predict(double[]input){114.double[]hiddenValues=new double[HIDDEN_DIM]; 115.for(int i=0;i<hiddenValues.length;i++){116.double sum=0;117.for(int j=0;j<input.length;j++){118.sum+=input[j]*input_hidden_weights[j][i]; 119.}120.sum+=hidden_thresholds[i];//再加上本神经元的阈值121.hiddenValues[i]=function(sum);122.}123.124.125.double sum=0;126.for(int i=0;i<HIDDEN_DIM;i++){127.sum+=hiddenValues[i]*hidden_output_weights[i]; 128.}129.sum+=output_threshold;//输出层神经元的阈值130.return function(sum);131.}132.133./**134.*进行一次训练135.*@param input136.*@param expectedOutput137.*/138.void trainOnce(double[]input,double expectedOutput){139.double[]hiddenValues=new double[HIDDEN_DIM];140.double[]hiddenParams=new double[HIDDEN_DIM];141.142.for(int i=0;i<hiddenValues.length;i++){143.double sum=0;144.for(int j=0;j<input.length;j++){145.sum+=input[j]*input_hidden_weights[j][i];146.}147.sum+=hidden_thresholds[i];//148.hiddenValues[i]=function(sum);149.hiddenParams[i]=sum;150.}151.152.double sum=0;153.for(int i=0;i<HIDDEN_DIM;i++){154.sum+=hiddenValues[i]*hidden_output_weights[i];155.}156.sum+=output_threshold;//157.double outputValue=function(sum);158.double outputParam=sum;159.//System.out.println("实际输出");160.161./*162.*调整权值和阈值163.*/164.165.for(int i=0;i<input.length;i++){166.double factor=(expectedOutput-outputValue)*outputValue*(1-outpu tValue)*LEARNING_RATE*input[i];167.for(int j=0;j<HIDDEN_DIM;j++){168.double delta=factor*hidden_output_weights[j]*hiddenValues[j] *(1-hiddenValues[j]);169.//System.out.println("输入层到隐含层连接的权重调整:delta="+delta+"\t\t weight="+input_hidden_weights[i][j]);170.input_hidden_weights[i][j]+=delta;171.}172.}173.double factor=(expectedOutput-outputValue)*outputValue*(1-outputVal ue)*LEARNING_RATE;174.for(int i=0;i<hidden_thresholds.length;i++){175.double delta=factor*hidden_output_weights[i]*hiddenValues[i]*(1 -hiddenValues[i]);176.hidden_thresholds[i]+=delta;177.}178.179.//System.out.println("hidden_output_weights:"+hidden_output_weigh ts.length);180.for(int i=0;i<hidden_output_weights.length;i++){181.//w+=(exp-act)*df/dw182.//df/dw=x(1-x)*hiddenj183.double delta=factor*hiddenValues[i];184.//System.out.println("隐含层到输出层连接的权值调整:delta="+delta+"\t\t weight="+hidden_output_weights[i]);185.hidden_output_weights[i]+=delta;186.187.}188.double delta=(expectedOutput-outputValue)*outputValue*(1-outputValue)*LEARNING_RATE;189.output_threshold+=delta;190.if(Math.abs(outputValue-expectedOutput)>0.1){191.//System.out.println(input[0]+"\t\t"+outputValue+"\t\t"+expecte dOutput);192.}193.194.195.196.}197.198.}2.测试代码[java]view plaincopy1.package pkg1;2.3.import java.awt.Graphics;4.import java.util.Scanner;5.6.import javax.swing.JFrame;7.8.public class DisplayNeuro extends javax.swing.JPanel{9.10.public static final int SIDE_LENGTH=200;11.12.TestNeuro neuro;//=new TestNeuro();13./**14.*@param args15.*/16.public static void main(String[]args){17.//TODO Auto-generated method stub18.DisplayNeuro dn=new DisplayNeuro();19.JFrame jFrame=new JFrame();20.jFrame.setBounds(100,100,300,300);21.jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);22.jFrame.add(dn);23.jFrame.setVisible(true);24.25.TestNeuro neuro=new TestNeuro(1,20);26.dn.neuro=neuro;27.Scanner in=new Scanner(System.in);28.dn.repaint();29.for(int i=0;i<100000000;i++){30.double[]input=new double[1];31.input[0]=Math.random()/2+0.25;32.double expectedOutput=(Math.sin(3.14*(input[0]-0.25)*2*4)+1)/8*3+0.125;33.//System.out.println("input:"+input[0]+"\t\texpectedOutput:"+expectedOutput);34.//System.out.println("predict before training:"+neuro.predict(input));35.neuro.trainOnce(input,expectedOutput);36.//System.out.println("predict after training:"+neuro.predict(input));37.38.if(i%100000==0){39.40.System.out.println("input please");41.//in.next();42.//neuro.initialize();43.dn.repaint();44.}45.46.}47.}48.49.50.@Override51.public void paint(Graphics arg0){52.//TODO Auto-generated method stub53.super.paint(arg0);54.55.for(double x=0.25;x<0.75;x+=0.005){56.double[]input=new double[1];57.input[0]=x;58.double y=neuro.predict(input);59.arg0.fillRect((int)(x*SIDE_LENGTH),(int)((1-y)*SIDE_LENGTH),1,1);60.}61.62.63.}64.65.66.}。