/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.neuroph.contrib.matrixmlp; import org.neuroph.core.Connection; import org.neuroph.core.Layer; import org.neuroph.core.Neuron; import org.neuroph.core.transfer.Tanh; import org.neuroph.core.transfer.TransferFunction; import org.neuroph.nnet.comp.BiasNeuron; /** * Matrix based layer optimized for backpropagation * @author Zoran Sevarac */ public class MatrixMlpLayer implements MatrixLayer { Layer sourceLayer; /** * Number of neurons in this layer */ int neuronsCount = 0; /** * Number of inputs from previous layer */ int inputsCount = 0; double[][] weights; double[][] deltaWeights; boolean useBias; // double[] biases; // double[] deltaBiases; double[] inputs; double[] netInput; double[] outputs; double[] errors; TransferFunction transferFunction = new Tanh(); MatrixLayer previousLayer = null; MatrixLayer nextLayer = null; // vidi konstruktore za MLayer // public MatrixBackPropLayer(int inputSize, int outputSize, TransferFunction transferFunction) { // inputs = new double[inputSize]; // outputs = new double[outputSize]; // weights = new double[outputSize][inputSize]; // // this.transferFunction = transferFunction; // } public MatrixMlpLayer(Layer sourceLayer, MatrixLayer previousLayer, TransferFunction transferFunction) { this.sourceLayer = sourceLayer; this.previousLayer = previousLayer; if (!(previousLayer instanceof MatrixInputLayer)) ((MatrixMlpLayer)previousLayer).setNextLayer(this); this.transferFunction = transferFunction; this.neuronsCount = sourceLayer.getNeuronsCount(); // if (sourceLayer.getNeuronAt(neuronsCount-1) instanceof BiasNeuron) this.neuronsCount = this.neuronsCount -1; this.inputsCount = previousLayer.getOutputs().length; outputs = new double[neuronsCount]; // biases = new double[neuronsCount]; // deltaBiases = new double[neuronsCount]; inputs = new double[inputsCount]; netInput = new double[neuronsCount]; weights = new double[neuronsCount][inputsCount]; deltaWeights = new double[neuronsCount][inputsCount]; errors = new double[neuronsCount]; copyNeuronsToMatrices(); } public MatrixLayer getPreviousLayer() { return previousLayer; } public void setPreviousLayer(MatrixLayer previousLayer) { this.previousLayer = previousLayer; } public MatrixLayer getNextLayer() { return nextLayer; } public void setNextLayer(MatrixLayer nextLayer) { this.nextLayer = nextLayer; } // maybe omit the sourceLayer parmeter public void copyNeuronsToMatrices() { int neuronIdx = 0, connIdx = 0; for(Neuron neuron : this.sourceLayer.getNeurons()) { if (neuron instanceof BiasNeuron) { this.useBias = true; } outputs[neuronIdx] = neuron.getOutput(); // should we copy net inputs also? weightedSums or netInputs = neuron.getNetInput() connIdx = 0; for(Connection conn : neuron.getInputConnections()) { weights[neuronIdx][connIdx] = conn.getWeight().getValue(); connIdx++; } neuronIdx++; } } public void copyMatricesToNeurons() { // assume full conectivity } public double[] getInputs() { return this.inputs; } public double[] getOutputs() { return this.outputs; } public void setInputs(double[] inputs) { this.inputs = inputs; } public void setOutputs(double[] outputs) { this.outputs = outputs; } public double[][] getWeights() { return weights; } // public double[] getBiases() { // return biases; // } // public void setBiases(double[] biases) { // this.biases = biases; // } public void getInputsFromPreviousLayer() { this.inputs = this.previousLayer.getOutputs(); } @Override final public void calculate() { this.inputs = previousLayer.getOutputs(); for (int i = 0; i < neuronsCount; i++) { netInput[i] = 0; for (int j = 0; j < inputs.length; j++) { netInput[i] += inputs[j] * weights[i][j]; } // netInput[i] = netInput[i] + biases[i]; outputs[i] = transferFunction.getOutput(netInput[i]); } if (useBias) outputs[neuronsCount-1] = 1; // this one is bias neuron } public int getNeuronsCount() { return outputs.length; } public double[] getErrors() { return errors; } public void setErrors(double[] errors) { this.errors = errors; } public TransferFunction getTransferFunction() { return transferFunction; } public double[] getNetInput() { return netInput; } public void saveCurrentWeights() { System.arraycopy(weights, 0, deltaWeights, 0, weights.length); // System.arraycopy(biases, 0, deltaBiases, 0, biases.length); } // public double[] getDeltaBiases() { // return deltaBiases; // } public double[][] getDeltaWeights() { return deltaWeights; } public void sync() { // synchronize matrix and object structures } }