神经网络的结构

神经网络的网络结构由输入层,隐含层,输出层组成。隐含层的个数+输出层的个数=神经网络的层数,也就是说神经网络的层数不包括输入层。下面是一个三层的神经网络,包含了两层隐含层,一个输出层。其中第一层隐含层的节点数为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]为14     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]为18     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 w51      */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 Data63      *            原始数据矩阵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 target75      *            the target to set76      */77     private void setTarget(double[] target) {78         this.target = target;79     }80 81     /**82      * 2.训练数据集83      * 84      * @param TrainData85      *            训练数据86      * @param target87      *            目标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 args5      * @throws IOException6      */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. bp神经网络代码_机器学习(周志华)课后习题——第五章——神经网络

    5.1 试述将线性函数 用作神经元激活函数的缺陷. 答: 使用线性函数作为激活函数时,无论是在隐藏层还是在输出层(无论传递几层),其单元值(在使用激活函数之前)都还是输入 的线性组合,这个时候的神经网 ...

  2. BP神经网络原理及其应用,bp神经网络的工作原理

    1.BP神经网络的工作原理 人工神经网络就是模拟人思维的第二种方式.这是一个非线性动力学系统,其特色在于信息的分布式存储和并行协同处理.虽然单个神经元的结构极其简单,功能有限,但大量神经元构成的网络系 ...

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

    说明: 1.本文以截图形式转载自http://blog.csdn.net/zhongkejingwang/article/details/44514073 2.转载供个人学习研究,对部分内容做出个人笔 ...

  4. mlp神经网络和bp神经网络,bp神经网络lm算法原理

    MATLAB中训练LM算法的BP神经网络 1.初始权值不一样,如果一样,每次训练结果是相同的 2.是 3.在train之前修改权值,IW,LW,b,使之相同 4.取多次实验的均值 一点浅见,仅供参考 ...

  5. BP神经网络算法基本原理,bp神经网络算法的原理

    BP人工神经网络方法 (一)方法原理人工神经网络是由大量的类似人脑神经元的简单处理单元广泛地相互连接而成的复杂的网络系统.理论和实践表明,在信息处理方面,神经网络方法比传统模式识别方法更具有优势. 人 ...

  6. python bp神经网络代码实现预测,用Python实现BP神经网络(附代码)

    用Python实现出来的机器学习算法都是什么样子呢? 前两期线性回归及逻辑回归项目已发布(见文末链接),今天来讲讲BP神经网络. BP神经网络 全部代码 https://github.com/lawl ...

  7. BP神经网络代码超通俗解释(MATLAB)

    clc;clear; %BP神经网络 xy=rand(2,200); %随机生成200组自变量,一组变量包含x,y,可以看成第一行为x1,x2,...x200,第二行为y1,y2,...y200; z ...

  8. bp神经网络代码_精通数据科学笔记 神经网络

    本章讨论一种全新的建模理念,它不关心模型的假设以及相应的数学推导,也就是说不关心模型的可解释性,其核心内容是模型实现,虽然到目前为止,人们还无法理解,但在某些特定场景里预测效果却非常好.我们把这种模型 ...

  9. bp神经网络和softmax原理_BP人工神经网络常用传递函数

    BP 网络常用传递函数 BP 网络的传递函数有多种. Log-sigmoid 型函数的输入值可取任意值, 输出值在 0 和 1 之间: tan-sigmod 型传递函数 tansig 的输入值可取任意 ...

  10. 机器学习(一):BP神经网络(含代码及注释)

    目录 人工神经网络 神经网络分类 BP神经网络 代码实现 人工神经网络 人们利用数学模型来模仿生物神经元传递信息以及做出决策等等.       下图神经网络数学模型可以等效为输入矩阵X与系数矩阵W相乘 ...

最新文章

  1. 做一些Spring AOP做过的事,封装 jdk动态代理成为一个黑盒子
  2. angularjs-数据同步时机ng-model-options
  3. JavaEE 7 正式发布
  4. NOIP模拟测试19「count·dinner·chess」
  5. Qt 编写应用程序升级的配置文件json 生成工具
  6. 制作自定义工作流(WWF)设计器
  7. stm32f103r8t6的晶振频率_STM32F103R8T6[1]
  8. LINQ-查询表达式基础
  9. 超硬核详解SpringClould之Gateway网管【含源码例子】
  10. [C#] LINQ之GroupBy
  11. 抖音计算机音乐的id,抖音卡点音乐叫什么名字 抖音卡点bgm介绍
  12. 状压DP——子集DP
  13. linux下anjuta_[分享] Linux下用Anjuta写个Hello World 的C++程序竟如此简单!
  14. 企业邮箱提升企业效率
  15. HTML期末学生作业~html+css+javascript仿猫眼电影在线网站[毕业设计]
  16. 明星开餐饮店,逃不过凉凉的魔咒?
  17. 低成本成FS68001A、FS68003无线充SOC芯片
  18. (31)2021-01-20(JSON字符串和本地存储)
  19. 苹果电脑可以装windows系统吗_iPhone 可以装 windows 了,想不想试试?
  20. Webmail邮件***实战技术总结

热门文章

  1. VC6.0和VC2012的全局对象的释放!!!
  2. 小米手机换图标后不变的解决办法
  3. python opencv中文文档_OpenCV中文官方文档
  4. r9270公版bios_R9280,R9270,HD7000,VBE7007.系显卡全套修改超频刷BIOS工具
  5. jdbc驱动加载过程
  6. 暴走漫画系列之高仿淘宝收货地址(附demo)
  7. 社团挖掘算法——BGLL算法
  8. Mac 安装svn客户端+idea配置svn
  9. c语言函数实现顺序线性表,数据结构C语言实现——顺序线性表SqList
  10. 【PAT】1105 Spiral Matrix(柳婼的思想详细解读)