课程作业要求实现一个BPNN。这次尝试使用Java实现了一个。现共享之。版权属于大家。关于BPNN的原理,就不赘述了。

下面是BPNN的实现代码。类名为BP。

package ml;

import java.util.Random;

/**

* BPNN.

*

* @author RenaQiu

*

*/

public class BP {

/**

* input vector.

*/

private final double[] input;

/**

* hidden layer.

*/

private final double[] hidden;

/**

* output layer.

*/

private final double[] output;

/**

* target.

*/

private final double[] target;

/**

* delta vector of the hidden layer .

*/

private final double[] hidDelta;

/**

* output layer of the output layer.

*/

private final double[] optDelta;

/**

* learning rate.

*/

private final double eta;

/**

* momentum.

*/

private final double momentum;

/**

* weight matrix from input layer to hidden layer.

*/

private final double[][] iptHidWeights;

/**

* weight matrix from hidden layer to output layer.

*/

private final double[][] hidOptWeights;

/**

* previous weight update.

*/

private final double[][] iptHidPrevUptWeights;

/**

* previous weight update.

*/

private final double[][] hidOptPrevUptWeights;

public double optErrSum = 0d;

public double hidErrSum = 0d;

private final Random random;

/**

* Constructor.

*

* Note: The capacity of each layer will be the parameter

* plus 1. The additional unit is used for smoothness.

*

*

* @param inputSize

* @param hiddenSize

* @param outputSize

* @param eta

* @param momentum

* @param epoch

*/

public BP(int inputSize, int hiddenSize, int outputSize, double eta,

double momentum) {

input = new double[inputSize + 1];

hidden = new double[hiddenSize + 1];

output = new double[outputSize + 1];

target = new double[outputSize + 1];

hidDelta = new double[hiddenSize + 1];

optDelta = new double[outputSize + 1];

iptHidWeights = new double[inputSize + 1][hiddenSize + 1];

hidOptWeights = new double[hiddenSize + 1][outputSize + 1];

random = new Random(19881211);

randomizeWeights(iptHidWeights);

randomizeWeights(hidOptWeights);

iptHidPrevUptWeights = new double[inputSize + 1][hiddenSize + 1];

hidOptPrevUptWeights = new double[hiddenSize + 1][outputSize + 1];

this.eta = eta;

this.momentum = momentum;

}

private void randomizeWeights(double[][] matrix) {

for (int i = 0, len = matrix.length; i != len; i++)

for (int j = 0, len2 = matrix[i].length; j != len2; j++) {

double real = random.nextDouble();

matrix[i][j] = random.nextDouble() > 0.5 ? real : -real;

}

}

/**

* Constructor with default eta = 0.25 and momentum = 0.3.

*

* @param inputSize

* @param hiddenSize

* @param outputSize

* @param epoch

*/

public BP(int inputSize, int hiddenSize, int outputSize) {

this(inputSize, hiddenSize, outputSize, 0.25, 0.9);

}

/**

* Entry method. The train data should be a one-dim vector.

*

* @param trainData

* @param target

*/

public void train(double[] trainData, double[] target) {

loadInput(trainData);

loadTarget(target);

forward();

calculateDelta();

adjustWeight();

}

/**

* Test the BPNN.

*

* @param inData

* @return

*/

public double[] test(double[] inData) {

if (inData.length != input.length - 1) {

throw new IllegalArgumentException("Size Do Not Match.");

}

System.arraycopy(inData, 0, input, 1, inData.length);

forward();

return getNetworkOutput();

}

/**

* Return the output layer.

*

* @return

*/

private double[] getNetworkOutput() {

int len = output.length;

double[] temp = new double[len - 1];

for (int i = 1; i != len; i++)

temp[i - 1] = output[i];

return temp;

}

/**

* Load the target data.

*

* @param arg

*/

private void loadTarget(double[] arg) {

if (arg.length != target.length - 1) {

throw new IllegalArgumentException("Size Do Not Match.");

}

System.arraycopy(arg, 0, target, 1, arg.length);

}

/**

* Load the training data.

*

* @param inData

*/

private void loadInput(double[] inData) {

if (inData.length != input.length - 1) {

throw new IllegalArgumentException("Size Do Not Match.");

}

System.arraycopy(inData, 0, input, 1, inData.length);

}

/**

* Forward.

*

* @param layer0

* @param layer1

* @param weight

*/

private void forward(double[] layer0, double[] layer1, double[][] weight) {

// threshold unit.

layer0[0] = 1.0;

for (int j = 1, len = layer1.length; j != len; ++j) {

double sum = 0;

for (int i = 0, len2 = layer0.length; i != len2; ++i)

sum += weight[i][j] * layer0[i];

layer1[j] = sigmoid(sum);

}

}

/**

* Forward.

*/

private void forward() {

forward(input, hidden, iptHidWeights);

forward(hidden, output, hidOptWeights);

}

/**

* Calculate output error.

*/

private void outputErr() {

double errSum = 0;

for (int idx = 1, len = optDelta.length; idx != len; ++idx) {

double o = output[idx];

optDelta[idx] = o * (1d - o) * (target[idx] - o);

errSum += Math.abs(optDelta[idx]);

}

optErrSum = errSum;

}

/**

* Calculate hidden errors.

*/

private void hiddenErr() {

double errSum = 0;

for (int j = 1, len = hidDelta.length; j != len; ++j) {

double o = hidden[j];

double sum = 0;

for (int k = 1, len2 = optDelta.length; k != len2; ++k)

sum += hidOptWeights[j][k] * optDelta[k];

hidDelta[j] = o * (1d - o) * sum;

errSum += Math.abs(hidDelta[j]);

}

hidErrSum = errSum;

}

/**

* Calculate errors of all layers.

*/

private void calculateDelta() {

outputErr();

hiddenErr();

}

/**

* Adjust the weight matrix.

*

* @param delta

* @param layer

* @param weight

* @param prevWeight

*/

private void adjustWeight(double[] delta, double[] layer,

double[][] weight, double[][] prevWeight) {

layer[0] = 1;

for (int i = 1, len = delta.length; i != len; ++i) {

for (int j = 0, len2 = layer.length; j != len2; ++j) {

double newVal = momentum * prevWeight[j][i] + eta * delta[i]

* layer[j];

weight[j][i] += newVal;

prevWeight[j][i] = newVal;

}

}

}

/**

* Adjust all weight matrices.

*/

private void adjustWeight() {

adjustWeight(optDelta, hidden, hidOptWeights, hidOptPrevUptWeights);

adjustWeight(hidDelta, input, iptHidWeights, iptHidPrevUptWeights);

}

/**

* Sigmoid.

*

* @param val

* @return

*/

private double sigmoid(double val) {

return 1d / (1d + Math.exp(-val));

}

}

为了验证正确性,我写了一个测试用例,目的是对于任意的整数(int型),BPNN在经过训练之后,能够准确地判断出它是奇数还是偶数,正数还是负数。首先对于训练的样本(是随机生成的数字),将它转化为一个32位的向量,向量的每个分量就是其二进制形式对应的位上的0或1。将目标输出视作一个4维的向量,[1,0,0,0]代表正奇数,[0,1,0,0]代表正偶数,[0,0,1,0]代表负奇数,[0,0,0,1]代表负偶数。

训练样本为1000个,学习200次。

package ml;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import java.util.Random;

public class Test {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

BP bp = new BP(32, 15, 4);

Random random = new Random();

List list = new ArrayList();

for (int i = 0; i != 1000; i++) {

int value = random.nextInt();

list.add(value);

}

for (int i = 0; i != 200; i++) {

for (int value : list) {

double[] real = new double[4];

if (value >= 0)

if ((value & 1) == 1)

real[0] = 1;

else

real[1] = 1;

else if ((value & 1) == 1)

real[2] = 1;

else

real[3] = 1;

double[] binary = new double[32];

int index = 31;

do {

binary[index--] = (value & 1);

value >>>= 1;

} while (value != 0);

bp.train(binary, real);

}

}

System.out.println("训练完毕,下面请输入一个任意数字,神经网络将自动判断它是正数还是复数,奇数还是偶数。");

while (true) {

byte[] input = new byte[10];

System.in.read(input);

Integer value = Integer.parseInt(new String(input).trim());

int rawVal = value;

double[] binary = new double[32];

int index = 31;

do {

binary[index--] = (value & 1);

value >>>= 1;

} while (value != 0);

double[] result = bp.test(binary);

double max = -Integer.MIN_VALUE;

int idx = -1;

for (int i = 0; i != result.length; i++) {

if (result[i] > max) {

max = result[i];

idx = i;

}

}

switch (idx) {

case 0:

System.out.format("%d是一个正奇数\n", rawVal);

break;

case 1:

System.out.format("%d是一个正偶数\n", rawVal);

break;

case 2:

System.out.format("%d是一个负奇数\n", rawVal);

break;

case 3:

System.out.format("%d是一个负偶数\n", rawVal);

break;

}

}

}

}

运行结果截图如下:

这个测试的例子非常简单。大家可以根据自己的需要去使用BP这个类。

大小: 15.9 KB

4

0

分享到:

2012-03-27 22:38

浏览 44276

分类:互联网

评论

57 楼

HiccupHiccup

2016-04-21

请问楼主  误差计算用的什么方法呢?

56 楼

cnmyh

2015-09-23

按照动量算法公式Δx(k+1)=ηΔx(k)+α(1-η)∂E(k)/∂x(k),但是楼主的代码double newVal = momentum * prevWeight[j][i] + eta * delta[i]* layer[j];怎么少了(1-momentum)部分,能否解释下?

55 楼

zhc0822

2015-08-05

Albert_ygy 写道

楼主你好,看完你的代码,我有两个疑问:1.成员变量momentum没太理解。它起什么作用?2.楼主采用的权值调整是通过每一层的输出误差来调整上一层的权值,而我查的资料是通过最后一层的输出层来逐层往前调整的。这种差异对结果是否有影响呢?求楼主解答,谢谢!

1. momentum 用于平滑weight的change

2. 请仔细看adjustWeight()方法

54 楼

Albert_ygy

2015-08-01

楼主你好,看完你的代码,我有两个疑问:1.成员变量momentum没太理解。它起什么作用?2.楼主采用的权值调整是通过每一层的输出误差来调整上一层的权值,而我查的资料是通过最后一层的输出层来逐层往前调整的。这种差异对结果是否有影响呢?求楼主解答,谢谢!

53 楼

zhc0822

2015-05-18

Thare_Lam 写道

Thare_Lam 写道

lz你好,首先非常感谢你的分享.

我认真研究了下你的代码,和书上的算法步骤是一样的,就是少了个阈值.我现在也在用java实现一个bp网络,但我的数据是6维的,一共有8类数据.我想请教下输出层改怎么设定?是8位,哪一位为1就代表哪一类还是3位,用二进制来表示各类?我感觉这两种方法都怪怪的.我自己按照你的代码敲了一遍,然后用自己的数据去算,算出的结果误差非常大(以上两种输出层设置方法都试了),经常是基本上全部都算成同一类了(我也是把输出最大的那个设为1).lz能帮我看看这应该怎么设计吗?

额 我发现改小了momentum和eta后准确率就到80%左右了 不知道这个准确率算不算高呢

多谢留言。momentum, eta, 隐层数目需要自己微调。80%的准确率高不高倒不好说,跟训练次数、训练集大小和测试集大小等有关系。尤其需要注意的是,训练次数并非越多越好,过多epoch会导致过拟合(overfitting)。

52 楼

Thare_Lam

2015-05-11

Thare_Lam 写道

lz你好,首先非常感谢你的分享.

我认真研究了下你的代码,和书上的算法步骤是一样的,就是少了个阈值.我现在也在用java实现一个bp网络,但我的数据是6维的,一共有8类数据.我想请教下输出层改怎么设定?是8位,哪一位为1就代表哪一类还是3位,用二进制来表示各类?我感觉这两种方法都怪怪的.我自己按照你的代码敲了一遍,然后用自己的数据去算,算出的结果误差非常大(以上两种输出层设置方法都试了),经常是基本上全部都算成同一类了(我也是把输出最大的那个设为1).lz能帮我看看这应该怎么设计吗?

额 我发现改小了momentum和eta后准确率就到80%左右了 不知道这个准确率算不算高呢

51 楼

Thare_Lam

2015-05-11

lz你好,首先非常感谢你的分享.

我认真研究了下你的代码,和书上的算法步骤是一样的,就是少了个阈值.我现在也在用java实现一个bp网络,但我的数据是6维的,一共有8类数据.我想请教下输出层改怎么设定?是8位,哪一位为1就代表哪一类还是3位,用二进制来表示各类?我感觉这两种方法都怪怪的.我自己按照你的代码敲了一遍,然后用自己的数据去算,算出的结果误差非常大(以上两种输出层设置方法都试了),经常是基本上全部都算成同一类了(我也是把输出最大的那个设为1).lz能帮我看看这应该怎么设计吗?

50 楼

zhc0822

2015-04-27

qingqingzijin2014 写道

想知道楼主的代码的输出,是不可能是负数吗?训练了900组了,还是不出负数。。

可以输出负数(图里就有例子)

想知道楼主的代码的输出,是不可能是负数吗?训练了900组了,还是不出负数。。

特地注册了个号来赞楼主

47 楼

zhc0822

2015-03-30

木叶纷飞 写道

double real = random.nextDouble();

matrix[i][j] = random.nextDouble() > 0.5 ? real : -real;

请问这两行代码中,为什么要将权值这样设定,而不是直接

matrix[i][j] = random.nextDouble(),我运行了一下,这个是错误的,不明白到底这个初始化到底为什么这样子

-1~1

46 楼

木叶纷飞

2015-03-17

double real = random.nextDouble();

matrix[i][j] = random.nextDouble() > 0.5 ? real : -real;

请问这两行代码中,为什么要将权值这样设定,而不是直接

matrix[i][j] = random.nextDouble(),我运行了一下,这个是错误的,不明白到底这个初始化到底为什么这样子

45 楼

beaticesmile

2014-09-10

您好,我想问一下,我是想利用BP神经网络实现时序预测,需要有3个数据输入,得出一个预测值的输出,需要修改哪几个地方呢?刚开始学习神经网络,继续使用该算法实现一个预测模型。所以,拜托拜托,帮帮我~楼主

44 楼

不注册

2014-08-07

非常感谢分享!

不过对其中有一个小细节不太理解,

即 "让所有数组大小加1", 并且在实际使用过程中给每层都加了一个输出值固定为1的神经元..

注释里提到的是"for smoothness", 以及另一处forward()里面标记了一个"threshold unit"

我个人的理解是这个算是一个常量, 和回归里用到的误差项类似?

请问可以稍微解释一下这个threashold unit的作用吗?

或者有没有什么paper是研究这个的

望不吝解惑

多谢

43 楼

lj745280746

2014-06-22

你好,我照着使用js重写了一遍,能正常运行了,但还有些不理解。

optDelta[idx] = o * (1d - o) * (target[idx] - o);

hidDelta[j] = o * (1d - o) * sum;

double newVal = momentum * prevWeight[j][i] + eta * delta[i]

* layer[j];

为什么要这样算,这三个公式有什么含义?

42 楼

zhc0822

2013-11-28

766085346 写道

你好,我想问下,已知1到10  10个数字,我想预测第11个,第十二个  这个怎么实现?关于bp算法我是小白,还望楼主赐教

不好意思,我不明白你的问题。能举个例子否?

41 楼

zhc0822

2013-11-28

公子芒 写道

还有个问题,你的forwar函数,里面都是采用的 layer1[j] = sigmoid(sum); 方法??

输入层到隐藏层的传输函数是sigmoid是对的,但是你的隐藏层到输出层的传输函数难道也是sigmoid?

private void forward() {

forward(input, hidden, iptHidWeights);

forward(hidden, output, hidOptWeights);

}

??

对的,都是sigmoid函数。

40 楼

766085346

2013-11-13

你好,我想问下,已知1到10  10个数字,我想预测第11个,第十二个  这个怎么实现?关于bp算法我是小白,还望楼主赐教

39 楼

公子芒

2013-05-01

还有个问题,你的forwar函数,里面都是采用的 layer1[j] = sigmoid(sum); 方法??

输入层到隐藏层的传输函数是sigmoid是对的,但是你的隐藏层到输出层的传输函数难道也是sigmoid?

private void forward() {

forward(input, hidden, iptHidWeights);

forward(hidden, output, hidOptWeights);

}

??

38 楼

公子芒

2013-05-01

公子芒 写道

仔细看了,也运行测试了。不过感觉总有些地方不对。看你的程序应该是动量BP算法。(MOBP)

private void outputErr() {

........

[b]optDelta[idx] = o * (1d - o) * (target[idx] - o); [/b]

}[size=medium][/size]

如果按照书上的推导,这部分应该是 optDelta[idx] = -2* 1 * (target[idx] - o);(输出层的敏感度,按照线性函数来推的话应该是f(n)其导数为1)

同样的 下一个方法也有些问题:

private void hiddenErr() {

..............

hidDelta[j] = o * (1d - o) * sum;

}

应该写成: hidDelta[j] = o * (1d - o) * sum;(这个后面是否为sum还不确定)。(隐藏层的传输函数是Log-Sigmoid,其导数是f(n)=a(1-a) 。 同时其敏感度受前一层即第二层的敏感度影响,应该是如上所写的)

正好在学习BP神经网络,你的代码十分清爽优雅,学习了~

我也不知道自己说的是否正确,请指正

抱歉,第二个方法   private void hiddenErr() {......}是正确的,后面的也是sum。

sum代表了 输出权值和输出敏感度的内积和。

bp神经网络java代码_BP神经网络的Java实现相关推荐

  1. 【Java 代码实例 13】Java操作pdf的工具类itext

    目录 一.什么是iText? 二.引入jar 1.项目要使用iText,必须引入jar包 2.输出中文,还要引入下面```itext-asian.jar```包 3.设置pdf文件密码,还要引入下面` ...

  2. 如何用70行Java代码实现神经网络算法

    为什么80%的码农都做不了架构师?>>>    http://geek.csdn.net/news/detail/56086 对于现在流行的深度学习,保持学习精神是必要的--程序员尤 ...

  3. 人工神经网络matlab代码,matlab神经网络30例代码

    如何在matlab中建立多层bp神经网络 当你用newff的时候,里面有一个参数可以控制层数,比如说:P = [0 1 2 3 4 5 6 7 8 9 10];T = [0 1 2 3 4 3 2 1 ...

  4. asp java 变量_ASP_用stack变量优化Java代码,  java程序包含了大量的对象 - phpStudy...

    用stack变量优化Java代码 java程序包含了大量的对象,我们需要了解它们是从哪里被访问的,变量存储于何处对程序的性能有显著的影响--尤其是某些需要被频繁访问的变量. 我们写一个Java类,在其 ...

  5. java代码识别_识别Java中的代码气味

    java代码识别 作为软件开发人员,我们不仅要编写有效的代码,而且还要编写可维护的代码,这是我们的责任. Martin Fowler在他的<重构:改进现有代码的设计>中将代码气味定义为: ...

  6. 大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据

    大数据 java 代码示例 这是称为" Functional Java by Example"的系列文章的第7部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序 ...

  7. jsp java代码_jsp内的java代码不执行,急啊!!大家来看看!

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 我的jsp页面上的java代码和html代码是穿插的, 用System.out.println去跟踪的时候, 内的代码都不执行, html都是执行的! 怎 ...

  8. linux怎样写java代码,linux 怎么写java

    linux 怎么写java 一.环境安装 由于使用 yum 或者 apt-get 命令 安装 openjdk 可能存在类库不全,从而导致用户在安装后运行相关工具时可能报错的问题,所以此处我们推荐采用手 ...

  9. java代码自动抠图_Opencv java实现人脸抠图和行为识别

    基于java的OpenCV环境搭建(Windows平台上ecplise) https://blog..net/qq_32447301/article/details/78494913 https:// ...

  10. java 代码加壳,关于java加壳和代码混淆

    在C中,进行,首要经过加壳的方法.所谓加壳,即是先将程序代码加密,然后用特定的程序加载器,将代码解密后加载进内存,这样能够在避免代码的反编译,当然,有加壳东西,也有解壳东西,尽管不能100%避免cra ...

最新文章

  1. 虚拟化--015 配置VMware View Event database失败:
  2. 聊一聊深度学习的activation function
  3. python locust最新版_python locust 性能测试:locust安装和一些参数介绍
  4. elementui 搭建布局页面路由_【项目实践】使用Vue.js和ElementUI快速实现后台管理系统的界面布局...
  5. mac catalina删除系统多余文件 内存不足_macOS Catalina Patcher(如何在旧mac上安装Catalina系统)...
  6. Linux——curl(转)
  7. 实战经验:从内存故障到CPU过高诊断-直播预告
  8. 【rabbitmq安装教程】centos7下安装rabbitMQ
  9. delphi 中文转 ascii编码_【转】Python 中文编码
  10. 电子商务的未来谁主宰?
  11. 极米H5搭载全新CCB流明,树电影色彩亮度新标杆
  12. 小A与小姐姐给气球涂色[dp + 快速幂]
  13. LICEcap:GIF屏幕录制工具
  14. [Windows10]Win10如何获取最高管理员权限
  15. Thread.currentThread()方法 Runnable
  16. C语言经典练习题(2)——“冒泡排序(Bubble Sort)“
  17. 【搜集】前端面试题总结
  18. 【专题1: MCU详解】 之 【1.3.嵌入式存储介质和启动详解】
  19. 陶瓷天线的选型(一)
  20. PDF转PPT免费软件哪个好?告诉你几个PDF转PPT的软件

热门文章

  1. jeesit1.27使用(2)-图片处理
  2. SwiftUI Button精品组件之完美的SwiftUI抖动按钮效果(教程含源码)
  3. spss软件测试题题库,spss题库_Spss软件可以算试题的区分度吗怎么算_淘题吧
  4. Jamovi 教程:比SPSS还好用的统计软件,强烈安利
  5. java 查看native方法_Java-如何查看java里的native方法?
  6. php lwm2m,理解COAP/LWM2M/MQTT协议和TCP/UDP协议的关系
  7. 康末otdr测试软件丢失,利用OTDR快速定位光缆线路故障-测试测量-与非网
  8. dax和m的区别_Power BI中的两种语言:M函数和DAX函数
  9. 关系抽取(分类)总结【转载】
  10. 竞品分析:得物APP、nice APP、识货APP