转自 huaweizte123的CSDN博客  链接 https://blog.csdn.net/huaweizte123/article/details/78803045

第一步、向前传播得到预测数据:向前传播的过程,即数据从输入层输入,经过隐含层,输出层的计算得到预测值,预测值为输出层的输出结果。网络层的输出即,该层中所有节点(神经元)的输出值的集合。我们以图一的神经网络结构为例,分析向前传播过程。

1.得到隐含层的输出y1,y2,y3

2.获取到第二层的隐含层输出y4,y5,输入的数据也就是第一层隐含层的输出数据y1,y2,y3

3、通过输出层,得到最后的预测值y。

第二步、反向传播更新权重:根据样本的真实类标,计算模型预测的结果与真实类标的误差。然后将该误差反向传播到各个隐含层。计算出各层的误差,再根据各层的误差,更新权重。

1.计算输出层的误差:其中z为该样本的类标

2计算第二层隐含层的误差

3.计算第一次隐含层的误差:

4、更新权重:新的权值=原权值+学习速率×该节点的误差×激励函数的导函数的值(f(e)的倒数)×与该节点相连的输入值

4.1更新输入层与第一层隐含层之间的权值:

4.2更新第一层隐含层与第二层隐含层之间的权值

4.3更新第二层隐含层与输出层之间的权值

以上就是反向传播的过程。误差从输出层反向的传到输入层,然后再从输入层向前更新权值。

BP神经网络的设计与实现

(一) BP神经网络的设计

1.设计网络的结构:

本次实验采用java语言实现。设计了包含一个隐含层的神经网络,即一个2层的神经网络。

每层都含有一个一维X特征矩阵即为输入数据,一个二维W权值矩阵,一个一维的误差矩阵error,同时该神经网络中还包含了一个一维的目标矩阵target,记录样本的真实类标。

X特征矩阵:第一层隐含层的X矩阵的长度为输入层输入数据的特征个数+1,隐含层的X矩阵的长度则是上一层的节点的个数+1,X[0]=1。

W权值矩阵:第一维的长度设计为节点(即神经元)的个数,第二维的长度设计为上一层节点的个数+1;W[0][0]为该节点的偏置量

error误差矩阵:数组长度设计为该层的节点个数。

目标矩阵target:输出层的节点个数与其一致。

激活函数:采用sigmoid函数:1/1+e-x

2.神经网络的计算过程

按照以上的设计,向前传播得到下一层的输出结果,如图所示:

求误差过程,如图所示:

反向传播过程,调整权值,如图所示:

(二) BP神经网络的实现

一、向前传播得到预测数据:

1.初始化权值
2.训练数据集:
  2.1、导入训练数据集和目标值;
  2.2、向前传播得到输出值;
    2.2.1、获取隐含层的输出
    2.2.2、获取输出层的输出
二、反向传播更新权重
 1、获取输出层的误差;
 2、获取隐含层的误差;
 3、更新隐含层的权值;
 4、更新输出层的权值;
三.测试神经网络
  3.3 向前传播得到预测值;

代码如下:

1 public class Bp {
2
3 private double[] hide1_x;//// 输入层即第一层隐含层的输入;hide1_x[数据的特征数目+1], hide1_x[0]为1
4 private double[][] hide1_w;// 隐含层权值,hide1_w[本层的节点的数目][数据的特征数目+1];hide_w[0][0]为偏置量
5 private double[] hide1_errors;// 隐含层的误差,hide1_errors[节点个数]
6
7 private double[] out_x;// 输出层的输入值即第二次层隐含层的输出 out_x[上一层的节点数目+1], out_x[0]为1
8 private double[][] out_w;// 输出层的权值 hide1_w[节点的数目][上一层的节点数目+1]//
9 // out_w[0][0]为偏置量
10 private double[] out_errors;// 输出层的误差 hide1_errors[节点个数]
11
12 private double[] target;// 目标值,target[输出层的节点个数]
13
14 private double rate;// 学习速率
15
16 public Bp(int input_node, int hide1_node, int out_node, double rate) {
17 super();
18
19 // 输入层即第一层隐含层的输入
20 hide1_x = new double[input_node + 1];
21
22 // 第一层隐含层
23 hide1_w = new double[hide1_node][input_node + 1];
24 hide1_errors = new double[hide1_node];
25
26 // 输出层
27 out_x = new double[hide1_node + 1];
28 out_w = new double[out_node][hide1_node + 1];
29 out_errors = new double[out_node];
30
31 target = new double[out_node];
32
33 // 学习速率
34 this.rate = rate;
35 init_weight();// 1.初始化网络的权值
36 }
37
38 /**
39 * 初始化权值
40 */
41 public void init_weight() {
42
43 set_weight(hide1_w);
44 set_weight(out_w);
45 }
46
47 /**
48 * 初始化权值
49 *
50 * @param w
51 */
52 private void set_weight(double[][] w) {
53 for (int i = 0, len = w.length; i != len; i++)
54 for (int j = 0, len2 = w[i].length; j != len2; j++) {
55 w[i][j] = 0;
56 }
57 }
58
59 /**
60 * 获取原始数据
61 *
62 * @param Data
63 * 原始数据矩阵
64 */
65 private void setHide1_x(double[] Data) {
66 if (Data.length != hide1_x.length - 1) {
67 throw new IllegalArgumentException("数据大小与输出层节点不匹配");
68 }
69 System.arraycopy(Data, 0, hide1_x, 1, Data.length);
70 hide1_x[0] = 1.0;
71 }
72
73 /**
74 * @param target
75 * the target to set
76 */
77 private void setTarget(double[] target) {
78 this.target = target;
79 }
80
81 /**
82 * 2.训练数据集
83 *
84 * @param TrainData
85 * 训练数据
86 * @param target
87 * 目标
88 */
89 public void train(double[] TrainData, double[] target) {
90 // 2.1导入训练数据集和目标值
91 setHide1_x(TrainData);
92 setTarget(target);
93
94 // 2.2:向前传播得到输出值;
95 double[] output = new double[out_w.length + 1];
96 forword(hide1_x, output);
97
98 // 2.3、方向传播:
99 backpropagation(output);
100
101 }
102
103 /**
104 * 反向传播过程
105 *
106 * @param output
107 * 预测结果
108 */
109 public void backpropagation(double[] output) {
110
111 // 2.3.1、获取输出层的误差;
112 get_out_error(output, target, out_errors);
113 // 2.3.2、获取隐含层的误差;
114 get_hide_error(out_errors, out_w, out_x, hide1_errors);
115 //// 2.3.3、更新隐含层的权值;
116 update_weight(hide1_errors, hide1_w, hide1_x);
117 // * 2.3.4、更新输出层的权值;
118 update_weight(out_errors, out_w, out_x);
119 }
120
121 /**
122 * 预测
123 *
124 * @param data
125 * 预测数据
126 * @param output
127 * 输出值
128 */
129 public void predict(double[] data, double[] output) {
130
131 double[] out_y = new double[out_w.length + 1];
132 setHide1_x(data);
133 forword(hide1_x, out_y);
134 System.arraycopy(out_y, 1, output, 0, output.length);
135
136 }
137
138
139 public void update_weight(double[] err, double[][] w, double[] x) {
140
141 double newweight = 0.0;
142 for (int i = 0; i < w.length; i++) {
143 for (int j = 0; j < w[i].length; j++) {
144 newweight = rate * err[i] * x[j];
145 w[i][j] = w[i][j] + newweight;
146 }
147
148 }
149 }
150
151 /**
152 * 获取输出层的误差
153 *
154 * @param output
155 * 预测输出值
156 * @param target
157 * 目标值
158 * @param out_error
159 * 输出层的误差
160 */
161 public void get_out_error(double[] output, double[] target, double[] out_error) {
162 for (int i = 0; i < target.length; i++) {
163 out_error[i] = (target[i] - output[i + 1]) * output[i + 1] * (1d - output[i + 1]);
164 }
165
166 }
167
168 /**
169 * 获取隐含层的误差
170 *
171 * @param NeLaErr
172 * 下一层的误差
173 * @param Nextw
174 * 下一层的权值
175 * @param output 下一层的输入
176 * @param error
177 * 本层误差数组
178 */
179 public void get_hide_error(double[] NeLaErr, double[][] Nextw, double[] output, double[] error) {
180
181 for (int k = 0; k < error.length; k++) {
182 double sum = 0;
183 for (int j = 0; j < Nextw.length; j++) {
184 sum += Nextw[j][k + 1] * NeLaErr[j];
185 }
186 error[k] = sum * output[k + 1] * (1d - output[k + 1]);
187 }
188 }
189
190 /**
191 * 向前传播
192 *
193 * @param x
194 * 输入值
195 * @param output
196 * 输出值
197 */
198 public void forword(double[] x, double[] output) {
199
200 // 2.2.1、获取隐含层的输出
201 get_net_out(x, hide1_w, out_x);
202 // 2.2.2、获取输出层的输出
203 get_net_out(out_x, out_w, output);
204
205 }
206
207 /**
208 * 获取单个节点的输出
209 *
210 * @param x
211 * 输入矩阵
212 * @param w
213 * 权值
214 * @return 输出值
215 */
216 private double get_node_put(double[] x, double[] w) {
217 double z = 0d;
218
219 for (int i = 0; i < x.length; i++) {
220 z += x[i] * w[i];
221 }
222 // 2.激励函数
223 return 1d / (1d + Math.exp(-z));
224 }
225
226 /**
227 * 获取网络层的输出
228 *
229 * @param x
230 * 输入矩阵
231 * @param w
232 * 权值矩阵
233 * @param net_out
234 * 接收网络层的输出数组
235 */
236 private void get_net_out(double[] x, double[][] w, double[] net_out) {
237
238 net_out[0] = 1d;
239 for (int i = 0; i < w.length; i++) {
240 net_out[i + 1] = get_node_put(x, w[i]);
241 }
242
243 }
244
245 }

  

(二) BP神经网络的测试

用上面实现的BP神经网络来训练模型,自动判断它是正数还是复数,奇数还是偶数.

1 public class Test {
2
3 /**
4 * @param args
5 * @throws IOException
6 */
7 public static void main(String[] args) throws IOException {
8
9
10 Bp bp = new Bp(32, 15, 4, 0.05);
11
12 Random random = new Random();
13
14 List<Integer> list = new ArrayList<Integer>();
15 for (int i = 0; i != 6000; i++) {
16 int value = random.nextInt();
17 list.add(value);
18 }
19
20 for (int i = 0; i !=25; i++) {
21 for (int value : list) {
22 double[] real = new double[4];
23 if (value >= 0)
24 if ((value & 1) == 1)
25 real[0] = 1;
26 else
27 real[1] = 1;
28 else if ((value & 1) == 1)
29 real[2] = 1;
30 else
31 real[3] = 1;
32
33 double[] binary = new double[32];
34 int index = 31;
35 do {
36 binary[index--] = (value & 1);
37 value >>>= 1;
38 } while (value != 0);
39
40 bp.train(binary, real);
41
42
43
44 }
45 }
46
47
48
49
50 System.out.println("训练完毕,下面请输入一个任意数字,神经网络将自动判断它是正数还是复数,奇数还是偶数。");
51
52 while (true) {
53
54 byte[] input = new byte[10];
55 System.in.read(input);
56 Integer value = Integer.parseInt(new String(input).trim());
57 int rawVal = value;
58 double[] binary = new double[32];
59 int index = 31;
60 do {
61 binary[index--] = (value & 1);
62 value >>>= 1;
63 } while (value != 0);
64
65 double[] result =new double[4];
66 bp.predict(binary,result);
67
68
69 double max = -Integer.MIN_VALUE;
70 int idx = -1;
71
72 for (int i = 0; i != result.length; i++) {
73 if (result[i] > max) {
74 max = result[i];
75 idx = i;
76 }
77 }
78
79 switch (idx) {
80 case 0:
81 System.out.format("%d是一个正奇数\n", rawVal);
82 break;
83 case 1:
84 System.out.format("%d是一个正偶数\n", rawVal);
85 break;
86 case 2:
87 System.out.format("%d是一个负奇数\n", rawVal);
88 break;
89 case 3:
90 System.out.format("%d是一个负偶数\n", rawVal);
91 break;
92 }
93 }
94 }
95 }

在BP神经网络中, 学习速率,训练集,以及训练次数,都会影响到最终模型的泛化能力。因此,在设计模型时,节点的个数,学习速率的大小,以及训练次数都是需要考虑的。

【学习笔记】BP神经网络的更多相关文章

  1. CNN学习笔记:神经网络表示

    CNN学习笔记:神经网络表示 双层神经网络模型 在一个神经网络中,当你使用监督学习训练它的时候,训练集包含了输入x还有目标输出y.隐藏层的含义是,在训练集中,这些中间节点的真正数值,我们是不知道的,即 ...

  2. TensorFlow学习笔记——深层神经网络的整理

    维基百科对深度学习的精确定义为“一类通过多层非线性变换对高复杂性数据建模算法的合集”.因为深层神经网络是实现“多层非线性变换”最常用的一种方法,所以在实际中可以认为深度学习就是深度神经网络的代名词.从 ...

  3. TensorFlow 深度学习笔记 卷积神经网络

    Convolutional Networks 转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Is ...

  4. 学习笔记DL003:神经网络第二、三次浪潮,数据量、模型规模,精度、复杂度,对现实世界冲击

    神经科学,依靠单一深度学习算法解决不同任务.视觉信号传送到听觉区域,大脑听学习处理区域学会“看”(Von Melchner et al., 2000).计算单元互相作用变智能.新认知机(Fukushi ...

  5. Neural Networks and Deep Learning学习笔记ch1 - 神经网络

    近期開始看一些深度学习的资料.想学习一下深度学习的基础知识.找到了一个比較好的tutorial,Neural Networks and Deep Learning,认真看完了之后觉得收获还是非常多的. ...

  6. TensorFlow深度学习笔记 循环神经网络实践

    转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程地址 视频/字幕下载 加 ...

  7. tensorflow学习笔记六----------神经网络

    使用mnist数据集进行神经网络的构建 import numpy as np import tensorflow as tf import matplotlib.pyplot as plt from ...

  8. MATLAB神经网络(1) BP神经网络的数据分类——语音特征信号分类

    1.1 案例背景 1.1.1 BP神经网络概述 BP神经网络是一种多层前馈神经网络,该网络的主要特点是信号前向传递,误差反向传播.在前向传递中,输入信号从输入层经隐含层逐层处理,直至输出层.每一层的神 ...

  9. [DL学习笔记]从人工神经网络到卷积神经网络_1_神经网络和BP算法

    前言:这只是我的一个学习笔记,里边肯定有不少错误,还希望有大神能帮帮找找,由于是从小白的视角来看问题的,所以对于初学者或多或少会有点帮助吧. 1:人工全连接神经网络和BP算法 <1>:人工 ...

  10. 数模学习笔记(五)——BP神经网络

    1.BP神经网络是一种前馈型网络(各神经元接受前一层的输入,并输出给下一层,没有反馈),分为input层,hide层,output层 2.BP神经网络的步骤: 1)创建一个神经网络:newff a.训 ...

随机推荐

  1. Keepalived & LVS: 实现web的负载均衡和高可用

    目录 1. 环境介绍2. LVS DR模型中Realserver上的准备3. ha上的准备4. 配置keepalived5. 测试Realserver的切换6. failback页面测试7. keep ...

  2. 纯JavaScript实现页面行为的录制

    在网上有个开源的rrweb项目,该项目采用TypeScript编写(不了解该语言的可参考之前的<TypeScript躬行记>),分为三大部分:rrweb-snapshot.rrweb和rr ...

  3. [RAC] 1. 安装Oracle RAC时,不能验证ASMSNMP密码问题的解决(ORA-01031或ORA-01017)

      1."ORA-01031: insufficient privileges" [grid@node1 bin]$ orapwd file=/u01/app/11.2.0/gri ...

  4. layui表格增删改查与上传图片+Api

    API  控制器1 主要用于增删改查已经反填数据查询 using System; using System.Collections.Generic; using System.Data.SqlClie ...

  5. 对c语言中static函数的理解

    先看看前两篇博客:个人对头文件的理解.对声明和定义的理解. static 函数只在定义该static函数的cpp中可见,在其他cpp中是不可见的. 举个例子,我建立了一个project,该projec ...

  6. js + php服务器推送see(自定义推送时间)

    //javascript code var source = new EventSource("./main.php"); source.onmessage=function(ev ...

  7. Postman之命令测试

    前言 今天我们来学习一下Postman的命令行测试 1.先安装node.js ,https://nodejs.org/en/#home-downloadhead 2.安装cnpm npm instal ...

  8. 在Linux实例上自动安装并运行VNC Server

    #!/bin/bash ######################################### #Function: install vnc server #Usage: bash ins ...

  9. android wifi断开原因分析

    最近在解bug的过程中经常遇到密码正确但处于saved的状态,总结原因有已下几种: 1 在ASSOCIATING阶段由于丢包导致ASSOC REJECT 03-16 09:22:12.440 D/Wi ...

  10. SparkShuffle机制

    在早期版本的Spark中,shuffle过程没有磁盘读写操作,是纯内存操作,后来发现效率较低,且极易引发OOME,较新版本的Shuffle操作都加入了磁盘读写进行了改进. 1.未经优化的HashShu ...