java实现简单的两层层神经网络算法

java实现简单的两层层神经网络算法

最近学习了神经网络算法,学的过程全部是用python实现的,我平时用java较多,所以我就尝试使用java来实现这个算法,完整代码在我的github地址,java没有numpy,所以我自己实现了一个类专门进行矩阵计算

package com.network.array;

/**
 * 此类主要解决矩阵运算方面的数学问题(仅支持2维的运算)
 * @author root
 */
public class Array {
	// 需要进行运算的数据对象
	private double[] data ;
	// 矩阵的维度 行
	private int h ;
	// 矩阵的维度 列
	private int w ;
	// 用于随即产生矩阵
	public static Random random = Random.random ;
	// 用于产生一个全部为0的矩阵
	public static Zero zero = Zero.zero ;
	
	//给定维度和数据大小创建矩阵
	public Array(int w , int maxLength) {
		this.w = w ;
		this.h = 0 ;
		this.data = new double[maxLength] ;
	}
	
	// 给定维度创建矩阵
	public Array(int w) {
		this.w = w ;
		this.h = 0 ;
		this.data = new double[100] ;
	}
	
	// 扩大数组容量
	private double[] copyArr(double[] source , int len) {
		double[] target = new double[len] ;
		System.arraycopy(source, 0, target, 0, source.length);
		return target ;
	}
	
	// 获取矩阵结构
	public int[] shape() {
		int[] temp = new int[] {w , h} ;
		return temp ;
	}
	
	// 重置矩阵结构
	public void reshape(int w , int h) {
		this.w = w ;
		this.h = h ;
	}
	
	// 此方法时给矩阵乘法提供的 默认时操作矩阵的最后一位
	public void push(int w_index , int h_index , double a) {
		// 判断数组大小是否足够
		if((h_index)*w + w_index + 1 >= data.length) {
			data = copyArr(data, (w*h + 2)*2) ;
		}
		data[h_index*w + w_index] = a ;
		h = h_index+1 ;
	}
	
	// 往矩阵中添加数据
	public void push(double[] a) throws Exception {
		if(a.length != this.w) {
			throw new Exception("维度不匹配");
		}
		// 判断数组大小是否足够
		if(w*h + a.length >= data.length) {
			data = copyArr(data, (w*h + a.length)*2) ;
		}
		for(int i=0 ; i<a.length ; i++) {
			data[w*h+i] = a[i] ;
		}
		h++ ;
	}
	
	// 往矩阵中添加数据
	public void push(Array arr) throws Exception {
		int target_w = arr.shape()[0] ;
		int target_h = arr.shape()[1] ;
		if(target_w != this.w) {
			throw new Exception("维度不匹配");
		}
		double[] target = arr.getData() ;
		int size = this.w*this.h ;
		// 判断数组大小是否足够
		if(w*h + target_w*target_h >= data.length) {
			data = copyArr(data, (w*h + target_w*target_h)*2) ;
		}
		// 将目标数组填入
		for(int i = 0 , len = target_w*target_h ; i < len ; i++) {
			this.data[size+i] = target[i] ;
		}
		h += target_h ;
	}
	
	// 矩阵点乘
	public Array dot(Array arr) throws Exception {
		// 判断两个矩阵是否能够相乘
		int target_w = arr.shape()[0] ;
		int target_h = arr.shape()[1] ;
		if(this.w != target_h) {
			throw new Exception("矩阵无法相乘");
		}
		// 当前对象的矩阵数据
		double[] source = this.data ;
		// 目标对象的矩阵数据
		double[] target = arr.getData() ;
		// 创建相乘后的矩阵
		Array result = new Array(target_w) ;
		for(int i = 0 , len = this.h * target_w ; i < len ; i++) {
			int temp_w = i%target_w ;
			int temp_h = i/target_w ;
			// 计算1矩阵i行和2矩阵j列的乘积
			double d = 0 ;
			for(int j = 0 ; j < this.w ; j++) {
				d += source[temp_h*this.w+j]*target[temp_w+j*target_w] ;
			}
			result.push(temp_w , temp_h , d);
		}
		return result ;
	}
	
	// 矩阵某个维度求和
	public Array sum(int axios) {
		Array result = null ;
		int lenX ;
		int lenY ;
		if (axios == 0) {
			result = new Array(this.w) ;
			lenX = this.w ;
			lenY = this.h ;
		}else {
			result = new Array(1) ;
			lenX = this.h ;
			lenY = this.w ;
		}
		for(int i = 0 ; i < lenX ; i++) {
			double sum = 0 ;
			for(int j = 0 ; j < lenY ; j++) {
				sum += this.data[axios == 0 ? j*this.w+i : i*this.w+j] ;
			}
			result.push(axios == 0 ? i : 0 , axios == 0 ? 0 : i , sum);
		}
		return result ;
	}
	。。。。。。
	代码总共有400多行,所以只粘贴了一部分,完整代码请到我的github下载

上面是神经网络所需要的数学工具类,然后我们来写神经网络算法

前向传播forward
// 训练数据
Array batch_x = xTrain.I(batchMask) ;
// 数据标记
Array batch_t = tTrain.I(batchMask) ;

// 1.前向传播
Array a1 = batch_x.dot(this.w1).add(this.b1) ;
//激活函数sigmoid
Array z1 = a1.sigmoid() ;
Array a2 = z1.dot(this.w2).add(this.b2) ;
//激活函数softmax
Array y  = a2.softmax() ;
反向传播backward
// 2.反向传播
// 2.1求softmax函数的反向传播(y - t)
Array dy = y.sub(batch_t).div(batch_x.shape()[1]) ;
// 矩阵点乘的反向传播 输入信号的转置点乘后端传过来的矩阵
Array dw2 = z1.T().dot(dy) ;
Array db2 = dy.sum(0) ;
// 求dx
Array dx = dy.dot(this.w2.T()) ;
// 2.2求sigmoid的反向传播 (1 - y)*y
Array dz = z1.sub(1).mul(-1).mul(z1).mul(dx) ;
Array dw1 = batch_x.T().dot(dz) ;
Array db1 = dz.sum(0) ;
梯度下降
// 更新权值
this.w1 = this.w1.sub(dw1.mul(this.learningRate)) ;
this.b1 = this.b1.sub(db1.mul(this.learningRate)) ;
this.w2 = this.w2.sub(dw2.mul(this.learningRate)) ;
this.b2 = this.b2.sub(db2.mul(this.learningRate)) ;

以上就是核心代码了

你可能感兴趣的:(java实现简单的两层层神经网络算法)