神经网络的结构

神经网络的网络结构由输入层,隐含层,输出层组成。隐含层的个数+输出层的个数=神经网络的层数,也就是说神经网络的层数不包括输入层。下面是一个三层的神经网络,包含了两层隐含层,一个输出层。其中第一层隐含层的节点数为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。

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

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神经网络—java实现的更多相关文章

  1. BP神经网络—java实现(转载)

    神经网络的结构 神经网络的网络结构由输入层,隐含层,输出层组成.隐含层的个数+输出层的个数=神经网络的层数,也就是说神经网络的层数不包括输入层.下面是一个三层的神经网络,包含了两层隐含层,一个输出层. ...

  2. 用java写bp神经网络(一)

    根据前篇博文<神经网络之后向传播算法>,现在用java实现一个bp神经网络.矩阵运算采用jblas库,然后逐渐增加功能,支持并行计算,然后支持输入向量调整,最后支持L-BFGS学习算法. ...

  3. BP神经网络的直观推导与Java实现

    人工神经网络模拟人体对于外界刺激的反应.某种刺激经过人体多层神经细胞传递后,可以触发人脑中特定的区域做出反应.人体神经网络的作用就是把某种刺激与大脑中的特定区域关联起来了,这样我们对于不同的刺激就可以 ...

  4. JAVA实现BP神经网络算法

    工作中需要预测一个过程的时间,就想到了使用BP神经网络来进行预测. 简介 BP神经网络(Back Propagation Neural Network)是一种基于BP算法的人工神经网络,其使用BP算法 ...

  5. 数据挖掘系列(9)——BP神经网络算法与实践

    神经网络曾经很火,有过一段低迷期,现在因为深度学习的原因继续火起来了.神经网络有很多种:前向传输网络.反向传输网络.递归神经网络.卷积神经网络等.本文介绍基本的反向传输神经网络(Backpropaga ...

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

    什么是BP网络 BP网络的数学原理 BP网络算法实现 转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/44514073  上一篇 ...

  7. BP神经网络的手写数字识别

    BP神经网络的手写数字识别 ANN 人工神经网络算法在实践中往往给人难以琢磨的印象,有句老话叫“出来混总是要还的”,大概是由于具有很强的非线性模拟和处理能力,因此作为代价上帝让它“黑盒”化了.作为一种 ...

  8. 【学习笔记】BP神经网络

    转自 huaweizte123的CSDN博客  链接 https://blog.csdn.net/huaweizte123/article/details/78803045 第一步.向前传播得到预测数 ...

  9. BP神经网络原理及python实现

    [废话外传]:终于要讲神经网络了,这个让我踏进机器学习大门,让我读研,改变我人生命运的四个字!话说那么一天,我在乱点百度,看到了这样的内容: 看到这么高大上,这么牛逼的定义,怎么能不让我这个技术宅男心 ...

随机推荐

  1. HTTP和WSGI协议

    HTTP协议简介 超文本传输协议(HyperText Transfer Protocol)是一种应用层协议.HTTP是万维网的数据通信的基础.设计HTTP最初的目的是为了提供一种发布和接收HTML页面 ...

  2. Django之model详解

    Django中的页面管理后台 Djano中自带admin后台管理模块,可以通过web页面去管理,有点想php-admin,使用步骤: 在项目中models.py 中创建数据库表 class useri ...

  3. PAT 甲级 1048 Find Coins (25 分)(较简单,开个数组记录一下即可)

    1048 Find Coins (25 分)   Eva loves to collect coins from all over the universe, including some other ...

  4. ubuntu18.04开机提示welcome to emergency mode! after logging in type...的解决办法

    开机就是报错,进不了系统. 原因是我的ubuntu电脑绑定了之前的移动硬盘,而我开机的时候并没有插着移动硬盘. 所以解决办法是,在此命令行下,以root用户的身份(我这里默认是root用户),vim ...

  5. Flutter easyrefresh示例 上拉加载+下拉刷新

    官方示例,简单改了下,实现功能为主. 代码如下: import 'dart:async'; import 'package:flutter/material.dart'; import 'packag ...

  6. 接着上次的python爬虫,今天进阶一哈,局部解析爬取网页数据

    *解析网页数据的仓库 用Beatifulsoup基于lxml包lxml包基于html和xml的标记语言的解析包.可以去解析网页的内容,把我们想要的提取出来. 第一步.导入两个包,项目中必须包含beau ...

  7. (IStool)64位软件安装在32位操作系统时给出提示

    需求:64位的软件当在32位操作系统下安装时,需要提示用户不能在32位操作系统中进行安装 实现:打包时启用64位模式(打包工具用的是Inno Setup 5) 安装脚本段需要添加以下代码: [Setu ...

  8. Egret入门学习日记 --- 第十篇(书中 2.9~2.13节 内容)

    第十篇(书中 2.9~2.13节 内容) 好的 2.9节 开始! 总结一下重点: 1.之前通过 ImageLoader 类加载图片的方式,改成了 RES.getResByUrl 的方式. 跟着做: 重 ...

  9. (一)MVC项目

    一.整体架构: 注:取自其他文章,最后的NewFile.html纯用于测试错误,完全不用. 二.具体代码: 1.User.java package common; public class User ...

  10. 【VS开发】【数据库开发】libevent windows下基于VS2010的编译

    libevent是一个常用的网络库,下面就看看在windows下面编译测试的过程吧. 一 环境 系统:win8.1编译器:VS2013官方下载地址:http://libevent.org/版本:2.0 ...