aima.core.learning.neural.Layer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aima-core Show documentation
Show all versions of aima-core Show documentation
AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.
package aima.core.learning.neural;
import aima.core.util.Util;
import aima.core.util.math.Matrix;
import aima.core.util.math.Vector;
/**
* Artificial Intelligence A Modern Approach (3rd Edition): page 729
*
*
* Feed-forward networks are usually arranged in layers, such that each unit
* receives input only from units in the immediately preceding layer.
*
* @author Ravi Mohan
* @author Mike Stampone
*/
public class Layer {
// vectors are represented by n * 1 matrices;
private final Matrix weightMatrix;
Vector biasVector, lastBiasUpdateVector;
private final ActivationFunction activationFunction;
private Vector lastActivationValues, lastInducedField;
private Matrix lastWeightUpdateMatrix;
private Matrix penultimateWeightUpdateMatrix;
private Vector penultimateBiasUpdateVector;
private Vector lastInput;
public Layer(Matrix weightMatrix, Vector biasVector, ActivationFunction af) {
activationFunction = af;
this.weightMatrix = weightMatrix;
lastWeightUpdateMatrix = new Matrix(weightMatrix.getRowDimension(),
weightMatrix.getColumnDimension());
penultimateWeightUpdateMatrix = new Matrix(
weightMatrix.getRowDimension(),
weightMatrix.getColumnDimension());
this.biasVector = biasVector;
lastBiasUpdateVector = new Vector(biasVector.getRowDimension());
penultimateBiasUpdateVector = new Vector(biasVector.getRowDimension());
}
public Layer(int numberOfNeurons, int numberOfInputs,
double lowerLimitForWeights, double upperLimitForWeights,
ActivationFunction af) {
activationFunction = af;
this.weightMatrix = new Matrix(numberOfNeurons, numberOfInputs);
lastWeightUpdateMatrix = new Matrix(weightMatrix.getRowDimension(),
weightMatrix.getColumnDimension());
penultimateWeightUpdateMatrix = new Matrix(
weightMatrix.getRowDimension(),
weightMatrix.getColumnDimension());
this.biasVector = new Vector(numberOfNeurons);
lastBiasUpdateVector = new Vector(biasVector.getRowDimension());
penultimateBiasUpdateVector = new Vector(biasVector.getRowDimension());
initializeMatrix(weightMatrix, lowerLimitForWeights,
upperLimitForWeights);
initializeVector(biasVector, lowerLimitForWeights, upperLimitForWeights);
}
public Vector feedForward(Vector inputVector) {
lastInput = inputVector;
Matrix inducedField = weightMatrix.times(inputVector).plus(biasVector);
Vector inducedFieldVector = new Vector(numberOfNeurons());
for (int i = 0; i < numberOfNeurons(); i++) {
inducedFieldVector.setValue(i, inducedField.get(i, 0));
}
lastInducedField = inducedFieldVector.copyVector();
Vector resultVector = new Vector(numberOfNeurons());
for (int i = 0; i < numberOfNeurons(); i++) {
resultVector.setValue(i, activationFunction
.activation(inducedFieldVector.getValue(i)));
}
// set the result as the last activation value
lastActivationValues = resultVector.copyVector();
return resultVector;
}
public Matrix getWeightMatrix() {
return weightMatrix;
}
public Vector getBiasVector() {
return biasVector;
}
public int numberOfNeurons() {
return weightMatrix.getRowDimension();
}
public int numberOfInputs() {
return weightMatrix.getColumnDimension();
}
public Vector getLastActivationValues() {
return lastActivationValues;
}
public Vector getLastInducedField() {
return lastInducedField;
}
public Matrix getLastWeightUpdateMatrix() {
return lastWeightUpdateMatrix;
}
public void setLastWeightUpdateMatrix(Matrix m) {
lastWeightUpdateMatrix = m;
}
public Matrix getPenultimateWeightUpdateMatrix() {
return penultimateWeightUpdateMatrix;
}
public void setPenultimateWeightUpdateMatrix(Matrix m) {
penultimateWeightUpdateMatrix = m;
}
public Vector getLastBiasUpdateVector() {
return lastBiasUpdateVector;
}
public void setLastBiasUpdateVector(Vector v) {
lastBiasUpdateVector = v;
}
public Vector getPenultimateBiasUpdateVector() {
return penultimateBiasUpdateVector;
}
public void setPenultimateBiasUpdateVector(Vector v) {
penultimateBiasUpdateVector = v;
}
public void updateWeights() {
weightMatrix.plusEquals(lastWeightUpdateMatrix);
}
public void updateBiases() {
Matrix biasMatrix = biasVector.plusEquals(lastBiasUpdateVector);
Vector result = new Vector(biasMatrix.getRowDimension());
for (int i = 0; i < biasMatrix.getRowDimension(); i++) {
result.setValue(i, biasMatrix.get(i, 0));
}
biasVector = result;
}
public Vector getLastInputValues() {
return lastInput;
}
public ActivationFunction getActivationFunction() {
return activationFunction;
}
public void acceptNewWeightUpdate(Matrix weightUpdate) {
/*
* penultimate weightupdates maintained only to implement VLBP later
*/
setPenultimateWeightUpdateMatrix(getLastWeightUpdateMatrix());
setLastWeightUpdateMatrix(weightUpdate);
}
public void acceptNewBiasUpdate(Vector biasUpdate) {
setPenultimateBiasUpdateVector(getLastBiasUpdateVector());
setLastBiasUpdateVector(biasUpdate);
}
public Vector errorVectorFrom(Vector target) {
return target.minus(getLastActivationValues());
}
//
// PRIVATE METHODS
//
private static void initializeMatrix(Matrix aMatrix, double lowerLimit,
double upperLimit) {
for (int i = 0; i < aMatrix.getRowDimension(); i++) {
for (int j = 0; j < aMatrix.getColumnDimension(); j++) {
double random = Util.generateRandomDoubleBetween(lowerLimit,
upperLimit);
aMatrix.set(i, j, random);
}
}
}
private static void initializeVector(Vector aVector, double lowerLimit,
double upperLimit) {
for (int i = 0; i < aVector.size(); i++) {
double random = Util.generateRandomDoubleBetween(lowerLimit,
upperLimit);
aVector.setValue(i, random);
}
}
}