日撸代码300行:第71天(BP神经网络基础类)

代码来自闵老师”日撸 Java 三百行(71-80天):

日撸 Java 三百行(71-80天,BP 神经网络)_闵帆的博客-CSDN博客

实现了一个抽象类,包含两个抽象方法forward和backPropagation。

argmax方法是为了找出当前数组的最大值,用于输出层确定最终标签。

方法train用来训练网络,有反向传递环节。

test用于测试,计算分类精度,没有反向传递。

package machinelearning.ann;

import java.io.FileReader;
import java.util.Arrays;
import java.util.Random;

import weka.core.Instances;

/**
 * 
 * General ANN. Two methods are abstract: forward and backPropagation.
 * 
 * @author WX873
 *
 */
public abstract class GeneralAnn {
	
	/**
	 * The whole dataset.
	 */
	Instances dataset;
	
	/**
	 * Number of layers. It is counted according to nodes instead of edges.
	 */
	int numLayers;
	
	/**
	 * The number of nodes for each layer, e.g., [3, 4, 6, 2] means that there
	 * are 3 input nodes (conditional attributes), 2 hidden layers with 4 and 6
	 * nodes, respectively, and 2 class values (binary classification).
	 */
	int[] layerNumNodes;
	
	/**
	 * Momentum coefficient.
	 */
	public double mobp;
	
	/**
	 * Learning rate.
	 */
	public double learningRate;
	
	/**
	 * For random number generation.
	 */
	Random random = new Random();
	
	/**
	 * ********************************************************************
	 * The first constructor.
	 * 
	 * @param paraFilename     The arff filename.
	 * @param paraLayerNumNodes   The number of nodes for each layer (may be different).
	 * @param paraLearningRate    Learning rate.
	 * @param paraMobp           Momentum coefficient.
	 * ********************************************************************
	 */
	public GeneralAnn(String paraFilename, int[] paraLayerNumNodes, double paraLearningRate, double paraMobp) {
		// Step 1. Read data.
		try {
			FileReader tempReader = new FileReader(paraFilename);
			dataset = new Instances(tempReader);
			// The last attribute is the decision class.
			dataset.setClassIndex(dataset.numAttributes() - 1);
			tempReader.close();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("Error occurred while trying to read \'" + paraFilename
					+ "\' in GeneralAnn constructor.\r\n" + e);
		}//of try
		
		// Step 2. Accept parameters.
		layerNumNodes = paraLayerNumNodes;
		numLayers = layerNumNodes.length;      //
		// Adjust if necessary.
		layerNumNodes[0] = dataset.numAttributes() - 1;    //第一层节点数等于条件属性个数
		layerNumNodes[numLayers - 1] = dataset.numClasses();   //最后一层节点数等于类别个数
		learningRate = paraLearningRate;
		mobp = paraMobp;
		
	}//of the first constructor
	
	/**
	 * ******************************************
	 * Forward prediction.
	 * 
	 * @param paraInput   The input data of one instance.
	 * @return   The data at the output end.
	 * ******************************************
	 */
	public abstract double[] forward(double[] paraInput);
	
	/**
	 * ***********************************************
	 * Back propagation.
	 * 
	 * @param paraTarget  For 3-class data, it is [0, 0, 1], [0, 1, 0] or [1, 0, 0].
	 * ***********************************************
	 */
	public abstract void backPropagation(double[] paraTarget);
	
	/**
	 * ************************************************
	 * Train using the dataset.
	 * ************************************************
	 */
	public void train() {
		double[] tempInput = new double[dataset.numAttributes() - 1];
		double[] tempTarget = new double[dataset.numClasses()];
		for (int i = 0; i < dataset.numInstances(); i++) {
			//Fill the data.
			for (int j = 0; j < tempInput.length; j++) {
				tempInput[j] = dataset.instance(i).value(j);
			}//of for j
			
			// Fill the class label.
			Arrays.fill(tempTarget, 0);
			tempTarget[(int) dataset.instance(i).classValue()] = 1;  //标签对应的位置为1,其他位置为0;
			
			//Train with this instance.
			forward(tempInput);
			backPropagation(tempTarget);
		}//of for i
	}//of train
	
	/**
	 * **************************************************
	 * Get the index corresponding to the max value of the array.
	 * @param paraArray
	 * @return  The index.
	 * **************************************************
	 */
	public static int argmax(double[] paraArray) {
		int resultIndex = -1;
		double tempMax = -1e10;
		for (int i = 0; i < paraArray.length; i++) {
			if (tempMax < paraArray[i]) {
				tempMax = paraArray[i];
				resultIndex = i;
			}//of if
		}//of for i
		
		return resultIndex;
	}//of argmax
	
	/**
	 * *****************************************************
	 * Test using the dataset.
	 * 
	 * @return  The precision.
	 * *****************************************************
	 */
	public double test() {
		double[] tempInput = new double[dataset.numAttributes() - 1];
		
		double tempNumCorrect = 0;
		double[] tempPrediction;
		int tempPredictedClass = -1;
		
		for (int i = 0; i < dataset.numInstances(); i++) {
			//Fill the data.
			for (int j = 0; j < tempInput.length; j++) {
				tempInput[j] = dataset.instance(i).value(j);
			}//of for j
			
			// Train with this instance.
			tempPrediction = forward(tempInput);
			tempPredictedClass = argmax(tempPrediction);
			if (tempPredictedClass == (int)dataset.instance(i).classValue()) {
				tempNumCorrect++;
			}//of if
		}//of for i
		
		System.out.println("Correct: " + tempNumCorrect + " out of " + dataset.numInstances());
		
		return tempNumCorrect / dataset.numInstances();
	}//of test
}//of GeneralAnn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值