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.
* <p>
* <strong>Note:</strong> The capacity of each layer will be the parameter
* plus 1. The additional unit is used for smoothness.
* </p>
*
* @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<Integer> list = new ArrayList<Integer>();
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;
}
}
}
}
分享到:
相关推荐
利用java实现bp神经网络,给定了UCI数据库的疝气病证预测病马数据,使用训练集训练BP神经网络并预测测试集的标签,错误率控制在30%以下。
使用Java实现BP神经网络进行回归分析,并利用训练好的神经网络实现空气质量的评级。
java实现的bp神经网络算法,代码超级简单,里面有实际数据例子,一看就懂!
Java实现BP神经网络,内含BP神经网络类,采用MNIST数据集,包含服务器和客户端程序,可在服务器训练后使客户端直接使用训练结果,界面有画板,可以手写数字
BP神经网络算法的java实现
中科大自然计算的小作业,使用梯度下降的bp神经网络实现iris数据的分类,上传上来与大家分享,顺便捞一点难得的下载积分
用于BP神经网络算法,可以用于工程预测。
BP神经网络的java实现
使用java语言编写的BP神经网络算法,实现了BP算法的功能
用JAVA写的BP神经网络,2*3*1,可以扩展网络结构
采用三层前馈BP神经网络实现标准人脸YALE数据库的识别,编程语言为C系列语言。 二、BP神经网络的结构和学习算法 实验中建议采用如下最简单的三层BP神经网络,输入层为 ,有n个神经元节点,输出层具有m个神经元,网络...
BP神经网络的实现
用java实现bp神经网络算法,具有可视化的界面
BP神经网络JAVA实现源码(含两套训练测试数据) 并实现了训练结果的保存 以及对保存的训练结果的加载测试使用
机器学习之BP神经网络案例.pdf
一个含有一个隐含层,且只能有一个输出单元的简单的BP网络,经过测试,达到了预期的效果。
Java实现BP神经网络算法并演示绘制曲线,顺便写了一个基于神经网络的数字识别的小程序
典型的BP神经网络学习算法,以及内部讲解,包括神经元个数,层数详细说明具体该怎么设定,简单的事例,快速明白交叉熵函数在反向传播过程的作用
BP神经网络算法源代码,文件为JAVA语言编写的,编译环境为Eclipse
BP算法的JAVA实现,BP神经网络的数学原理及其算法实现,实验使用IRIS数据集,BP神经网络,BP即Back Propagation的缩写,也就是反向传播的意思,顾名思义,将什么反向传播?文中将会解答。不仅如此,关于隐层的含义...