简单BP神经网络的Java实现
2017-03-24 10:56
316 查看
初学神经网络,利用Java实现简单的BP,现记录下来。
1、BP.java文件,具体功能见代码注释
/**
* 简单BP网络的Java实现
* 3层网络
* 激活函数sigmoid
* 注意:
* 1、输入层的神经元个数和训练集的列数一致,训练集的每一行为一个特征向量。
* 2、输出层神经元的个数和标签的列数一致,标签的每一列相当于一个特征向量训练的结果
* @author yuliyan
*/
public class BP extends Matrix{
public double[][] x;//训练集
public double[][] y;//标签
public double[][] v;//输入层到隐藏层的权值
public double[][] w;//隐藏层到输出层的权值
public double lr;//学习率
public BP(double[][] x,double[][] y,int input,int hidden,int output,double lr) {
this.x= x;
this.y=y;
this.v= weigth(input, hidden);
this.w= weigth(hidden, output);
this.lr=lr;
}
/**
* 初始化权值
* @param row
* @param col
* @return
*/
public static double[][] weigth(int row,int col){
double[][] result = new double[row][col];
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
result[i][j] = Math.random()*2-1;
}
}
return result;
}
/**
* 训练一次
*/
public void train(){
//隐藏层输出
double[][] L1 = sigmoid(matrixmultiple(x, v));//4*5
//输出层输出
double[][] L2 = sigmoid(matrixmultiple(L1, w));//4*3
//隐藏层到输出层权值调整
double[][] delta_2 = matrix_mu(matrixsub(y,L2),dsigmoid(L2));//(y-L2)*dsigmoid(L2) 4*3
w= matrixadd(w, matrixmultiple(matrixmultiple(T(L1), delta_2), lr));
//输入层到隐藏层权值调整
double[][] delta_1 = matrix_mu(matrixmultiple(delta_2,T(w)),dsigmoid(L1));
v = matrixadd(v, matrixmultiple(matrixmultiple(T(x), delta_1), lr));
}
/**
* 多次迭代训练
* @param range 迭代次数
*/
public void train(int range){
for(int i=0;i<range;i++){
train();
if(i%100==0){
//隐藏层输出
double[][] L1 = sigmoid(matrixmultiple(x, v));
//输出层输出
double[][] L2 = sigmoid( matrixmultiple(L1, w));
double temp = 0;
for(int j=0;j<
4000
;y.length;j++){
for(int k=0;k<y[0].length;k++)
temp+=Math.abs(y[j][k]-L2[j][k]);
}
//输出误差
System.out.println("error:"+temp/(y.length*y[0].length));
}
}
}
/**
* 根据训练结果输出预测值
* @param test 测试集
* @param test_y 测试结果
*/
public void predict(double[][] test,double[][] test_y){
double[][] L1 = sigmoid(matrixmultiple(test, v));
//输出层输出
double[][] L2 = sigmoid( matrixmultiple(L1, w));
System.out.println("预测值:");
for(int j=0;j<L2.length;j++){
for(int k=0;k<L2[0].length;k++)
System.out.print(L2[j][k]+" ");
System.out.println();
}
System.out.println("实际值:");
for(int j=0;j<L2.length;j++){
for(int k=0;k<L2[0].length;k++)
System.out.print(test_y[j][k] +" ");
System.out.println();
}
}
public static void main(String[] args) {
double[][] x = {
{1,0,0,0,0,0},
{1,0,0,0,0,1},
{1,0,0,0,1,0},
{1,0,0,1,0,0},
{1,0,1,0,0,0},
{1,1,0,0,0,0},
{1,0,0,0,1,1},
{1,0,0,1,1,0},
{1,0,1,1,0,0},
{1,1,1,0,0,0},
{1,0,0,1,1,1},
{1,0,1,1,1,0},
{1,1,1,1,0,0},
{1,0,1,1,1,1},
{1,1,1,1,1,0}
};
double[][] y = {
{0,0,0,1},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{1,0,0,0},
{1,0,0,0},
{1,0,0,0},
{0,0,1,1},
{0,0,1,1},
};
int input = 6;
int hidden = 50;
int output = 4;
double[][] test = {
{1,1,0,0,0,0},
{1,0,0,0,0,1},
{1,1,1,0,0,0},
{1,1,1,1,1,0}
};
double[][] test_y = {
{0,0,1,0},
{0,0,1,0},
{0,1,0,0},
{0,0,1,1}
};
double lr = 0.11;
//初始化初值
BP bp = new BP(x, y, input, hidden, output, lr);
//训练20000次
bp.train(20000);
//输出预测
bp.predict(test,test_y);
}
}
3、运行截图
1、BP.java文件,具体功能见代码注释
/**
* 简单BP网络的Java实现
* 3层网络
* 激活函数sigmoid
* 注意:
* 1、输入层的神经元个数和训练集的列数一致,训练集的每一行为一个特征向量。
* 2、输出层神经元的个数和标签的列数一致,标签的每一列相当于一个特征向量训练的结果
* @author yuliyan
*/
public class BP extends Matrix{
public double[][] x;//训练集
public double[][] y;//标签
public double[][] v;//输入层到隐藏层的权值
public double[][] w;//隐藏层到输出层的权值
public double lr;//学习率
public BP(double[][] x,double[][] y,int input,int hidden,int output,double lr) {
this.x= x;
this.y=y;
this.v= weigth(input, hidden);
this.w= weigth(hidden, output);
this.lr=lr;
}
/**
* 初始化权值
* @param row
* @param col
* @return
*/
public static double[][] weigth(int row,int col){
double[][] result = new double[row][col];
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
result[i][j] = Math.random()*2-1;
}
}
return result;
}
/**
* 训练一次
*/
public void train(){
//隐藏层输出
double[][] L1 = sigmoid(matrixmultiple(x, v));//4*5
//输出层输出
double[][] L2 = sigmoid(matrixmultiple(L1, w));//4*3
//隐藏层到输出层权值调整
double[][] delta_2 = matrix_mu(matrixsub(y,L2),dsigmoid(L2));//(y-L2)*dsigmoid(L2) 4*3
w= matrixadd(w, matrixmultiple(matrixmultiple(T(L1), delta_2), lr));
//输入层到隐藏层权值调整
double[][] delta_1 = matrix_mu(matrixmultiple(delta_2,T(w)),dsigmoid(L1));
v = matrixadd(v, matrixmultiple(matrixmultiple(T(x), delta_1), lr));
}
/**
* 多次迭代训练
* @param range 迭代次数
*/
public void train(int range){
for(int i=0;i<range;i++){
train();
if(i%100==0){
//隐藏层输出
double[][] L1 = sigmoid(matrixmultiple(x, v));
//输出层输出
double[][] L2 = sigmoid( matrixmultiple(L1, w));
double temp = 0;
for(int j=0;j<
4000
;y.length;j++){
for(int k=0;k<y[0].length;k++)
temp+=Math.abs(y[j][k]-L2[j][k]);
}
//输出误差
System.out.println("error:"+temp/(y.length*y[0].length));
}
}
}
/**
* 根据训练结果输出预测值
* @param test 测试集
* @param test_y 测试结果
*/
public void predict(double[][] test,double[][] test_y){
double[][] L1 = sigmoid(matrixmultiple(test, v));
//输出层输出
double[][] L2 = sigmoid( matrixmultiple(L1, w));
System.out.println("预测值:");
for(int j=0;j<L2.length;j++){
for(int k=0;k<L2[0].length;k++)
System.out.print(L2[j][k]+" ");
System.out.println();
}
System.out.println("实际值:");
for(int j=0;j<L2.length;j++){
for(int k=0;k<L2[0].length;k++)
System.out.print(test_y[j][k] +" ");
System.out.println();
}
}
public static void main(String[] args) {
double[][] x = {
{1,0,0,0,0,0},
{1,0,0,0,0,1},
{1,0,0,0,1,0},
{1,0,0,1,0,0},
{1,0,1,0,0,0},
{1,1,0,0,0,0},
{1,0,0,0,1,1},
{1,0,0,1,1,0},
{1,0,1,1,0,0},
{1,1,1,0,0,0},
{1,0,0,1,1,1},
{1,0,1,1,1,0},
{1,1,1,1,0,0},
{1,0,1,1,1,1},
{1,1,1,1,1,0}
};
double[][] y = {
{0,0,0,1},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{1,0,0,0},
{1,0,0,0},
{1,0,0,0},
{0,0,1,1},
{0,0,1,1},
};
int input = 6;
int hidden = 50;
int output = 4;
double[][] test = {
{1,1,0,0,0,0},
{1,0,0,0,0,1},
{1,1,1,0,0,0},
{1,1,1,1,1,0}
};
double[][] test_y = {
{0,0,1,0},
{0,0,1,0},
{0,1,0,0},
{0,0,1,1}
};
double lr = 0.11;
//初始化初值
BP bp = new BP(x, y, input, hidden, output, lr);
//训练20000次
bp.train(20000);
//输出预测
bp.predict(test,test_y);
}
}
2、矩阵的一些基本操作
public abstract class Matrix { /** * 矩阵相乘 * @param a * @param b * @return */ public double[][] matrixmultiple(int[][] a,double[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(a_col!=b_row){ System.out.println("检查矩阵是否能相乘"); return null; } double[][] result = new double[a_row][b_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<b_col;j++){ double temp = 0; for(int k=0;k<a_col;k++){ temp+= a[i][k]*b[k][j]; } result[i][j] = temp; } } return result; } /** * 矩阵相乘 * @param a * @param b * @return */ public double[][] matrixmultiple(double[][] a,int[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(a_col!=b_row){ System.out.println("检查矩阵是否能相乘"); return null; } double[][] result = new double[a_row][b_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<b_col;j++){ double temp = 0; for(int k=0;k<a_col;k++){ temp+= a[i][k]*b[k][j]; } result[i][j] = temp; } } return result; } /** * 矩阵相乘 * @param a * @param b * @return */ public double[][] matrixmultiple(double[][] a,double[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(a_col!=b_row){ System.out.println("检查矩阵是否能相乘"); return null; } double[][] result = new double[a_row][b_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<b_col;j++){ double temp = 0; for(int k=0;k<a_col;k++){ temp+= a[i][k]*b[k][j]; } result[i][j] = temp; } } return result; } /** * 矩阵和一个数相乘 * @param a * @param b * @return */ public double[][] matrixmultiple(double[][] a,double b){ int a_row = a.length,a_col = a[0].length; double[][] result = new double[a_row][a_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<a_col;j++){ result[i][j] = a[i][j]*b; } } return result; } /** * 矩阵和一个数相乘 * @param b * @param a * @return */ public double[][] matrixmultiple(double b,double[][] a){ int a_row = a.length,a_col = a[0].length; double[][] result = new double[a_row][a_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<a_col;j++){ result[i][j] = a[i][j]*b; } } return result; } /** * 矩阵按位相乘 * @param a * @param b * @return */ public double[][] matrix_mu(double[][] a,double[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(a_row!=b_row||a_col!=b_col){ System.out.println("检查矩阵是否能*相乘"); return null; } double[][] result = new double[a_row][a_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<a_col;j++){ result[i][j] = a[i][j]*b[i][j]; } } return result; } /** * 矩阵按位相加 * @param a * @param b * @return */ public double[][] matrixadd(double[][] a,double[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(!(a_row==b_row&&a_col==b_col)){ System.out.println("检查两个矩阵是否可以相加"); return null; } double[][] result = new double[a_row][a_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<a_col;j++){ result[i][j] = a[i][j]+b[i][j]; } } return result; } /** * 矩阵按位相减 * @param a * @param b * @return */ public double[][] matrixsub(double[][] a,double[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(!(a_row==b_row&&a_col==b_col)){ System.out.println("检查两个矩阵是否可以相减"); return null; } double[][] result = new double[a_row][a_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<a_col;j++){ result[i][j] = a[i][j]-b[i][j]; } } return result; } /** * 矩阵按位相减 * @param a * @param b * @return */ public double[][] matrixsub(double[][] a,int[][] b){ int a_row = a.length,a_col = a[0].length; int b_row = b.length,b_col = b[0].length; if(!(a_row==b_row&&a_col==b_col)){ System.out.println("检查两个矩阵是否可以相减"); return null; } double[][] result = new double[a_row][a_col]; for(int i=0;i<a_row;i++){ for(int j=0;j<a_col;j++){ result[i][j] = a[i][j]-b[i][j]; } } return result; } /** * 矩阵转置 * @param a * @return */ public double[][] T(double[][] a){ int row = a.length,col = a[0].length; double[][] result = new double[col][row]; for(int i=0;i<col;i++){ for(int j=0;j<row;j++){ result[i][j] = a[j][i]; } } return result; } /** * 矩阵转置 * @param a * @return */ public int[][] T(int[][] a){ int row = a.length,col = a[0].length; int[][] result = new int[col][row]; for(int i=0;i<col;i++){ for(int j=0;j<row;j++){ result[i][j] = a[j][i]; } } return result; } /** * sigmoid激活函数 * @param x * @return */ public double sigmoid(double x){ return 1d/(1d+Math.exp(-x)); } /** * sigmoid求导 * @param x * @return */ public double dsigmoid(double x){ return x*(1d-x); } /** * 对一个矩阵求sigmoid * @param x * @return */ public double[][] sigmoid(double[][] x){ int row = x.length,col = x[0].length; double[][] result = new double[row][col]; for(int i=0;i<row;i++){ for(int j=0;j<col;j++){ result[i][j] = sigmoid(x[i][j]); } } return result; } /** * 对于一个矩阵求sigmoid倒数 * @param x * @return */ public double[][] dsigmoid(double[][] x){ int row = x.length,col = x[0].length; double[][] result = new double[row][col]; for(int i=0;i<row;i++){ for(int j=0;j<col;j++){ result[i][j] = dsigmoid(x[i][j]); } } return result; }}
3、运行截图
相关文章推荐
- 使用Java实现对dbf文件的简单读写
- 基于Java实现简单Http服务器之一
- 用java实现简单url负载均衡以及容错
- 在java中实现调用简单的c程序
- 由Java实现简单的文本编辑器
- http断点续传简单实现(java)
- 一个简单的冒泡排序和快速排序算法java实现
- 基于Java实现简单Http服务器之一
- JSP应用 java反射简单实现
- 用Java简单实现文件分割与合并
- 用java实现简单的email正则表达式判断
- 用java实现简单的多线程下载
- 一个简单的用JAVA实现的屏幕抓图(源代码)
- 用java实现简单的网络通信,相当于一个最简单的控制台qq(附代码) 推荐
- 使用异或进行简单的密码加密(JAVA实现)
- 今天的问题:一个简单的例子,请帮我解开“接口实现Java‘隐藏实现细目’”的迷惑。
- 用Java简单实现文件分割与合并
- 用Java实现的字符串简单加密
- http断点续传简单实现(java)
- Java程序国际化的简单实现