bp神经网络java代码_BP神经网络的Java实现
课程作业要求实现一个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实现相关推荐
- 【Java 代码实例 13】Java操作pdf的工具类itext
目录 一.什么是iText? 二.引入jar 1.项目要使用iText,必须引入jar包 2.输出中文,还要引入下面```itext-asian.jar```包 3.设置pdf文件密码,还要引入下面` ...
- 如何用70行Java代码实现神经网络算法
为什么80%的码农都做不了架构师?>>> http://geek.csdn.net/news/detail/56086 对于现在流行的深度学习,保持学习精神是必要的--程序员尤 ...
- 人工神经网络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 ...
- asp java 变量_ASP_用stack变量优化Java代码, java程序包含了大量的对象 - phpStudy...
用stack变量优化Java代码 java程序包含了大量的对象,我们需要了解它们是从哪里被访问的,变量存储于何处对程序的性能有显著的影响--尤其是某些需要被频繁访问的变量. 我们写一个Java类,在其 ...
- java代码识别_识别Java中的代码气味
java代码识别 作为软件开发人员,我们不仅要编写有效的代码,而且还要编写可维护的代码,这是我们的责任. Martin Fowler在他的<重构:改进现有代码的设计>中将代码气味定义为: ...
- 大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据
大数据 java 代码示例 这是称为" Functional Java by Example"的系列文章的第7部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序 ...
- jsp java代码_jsp内的java代码不执行,急啊!!大家来看看!
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 我的jsp页面上的java代码和html代码是穿插的, 用System.out.println去跟踪的时候, 内的代码都不执行, html都是执行的! 怎 ...
- linux怎样写java代码,linux 怎么写java
linux 怎么写java 一.环境安装 由于使用 yum 或者 apt-get 命令 安装 openjdk 可能存在类库不全,从而导致用户在安装后运行相关工具时可能报错的问题,所以此处我们推荐采用手 ...
- java代码自动抠图_Opencv java实现人脸抠图和行为识别
基于java的OpenCV环境搭建(Windows平台上ecplise) https://blog..net/qq_32447301/article/details/78494913 https:// ...
- java 代码加壳,关于java加壳和代码混淆
在C中,进行,首要经过加壳的方法.所谓加壳,即是先将程序代码加密,然后用特定的程序加载器,将代码解密后加载进内存,这样能够在避免代码的反编译,当然,有加壳东西,也有解壳东西,尽管不能100%避免cra ...
最新文章
- 虚拟化--015 配置VMware View Event database失败:
- 聊一聊深度学习的activation function
- python locust最新版_python locust 性能测试:locust安装和一些参数介绍
- elementui 搭建布局页面路由_【项目实践】使用Vue.js和ElementUI快速实现后台管理系统的界面布局...
- mac catalina删除系统多余文件 内存不足_macOS Catalina Patcher(如何在旧mac上安装Catalina系统)...
- Linux——curl(转)
- 实战经验:从内存故障到CPU过高诊断-直播预告
- 【rabbitmq安装教程】centos7下安装rabbitMQ
- delphi 中文转 ascii编码_【转】Python 中文编码
- 电子商务的未来谁主宰?
- 极米H5搭载全新CCB流明,树电影色彩亮度新标杆
- 小A与小姐姐给气球涂色[dp + 快速幂]
- LICEcap:GIF屏幕录制工具
- [Windows10]Win10如何获取最高管理员权限
- Thread.currentThread()方法 Runnable
- C语言经典练习题(2)——“冒泡排序(Bubble Sort)“
- 【搜集】前端面试题总结
- 【专题1: MCU详解】 之 【1.3.嵌入式存储介质和启动详解】
- 陶瓷天线的选型(一)
- PDF转PPT免费软件哪个好?告诉你几个PDF转PPT的软件
热门文章
- jeesit1.27使用(2)-图片处理
- SwiftUI Button精品组件之完美的SwiftUI抖动按钮效果(教程含源码)
- spss软件测试题题库,spss题库_Spss软件可以算试题的区分度吗怎么算_淘题吧
- Jamovi 教程:比SPSS还好用的统计软件,强烈安利
- java 查看native方法_Java-如何查看java里的native方法?
- php lwm2m,理解COAP/LWM2M/MQTT协议和TCP/UDP协议的关系
- 康末otdr测试软件丢失,利用OTDR快速定位光缆线路故障-测试测量-与非网
- dax和m的区别_Power BI中的两种语言:M函数和DAX函数
- 关系抽取(分类)总结【转载】
- 竞品分析:得物APP、nice APP、识货APP