Package org.encog.neural.bam

Source Code of org.encog.neural.bam.BAM

/*
* Encog(tm) Core v3.0 - Java Version
* http://www.heatonresearch.com/encog/
* http://code.google.com/p/encog-java/
* Copyright 2008-2011 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*  
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.neural.bam;

import org.encog.mathutil.matrices.Matrix;
import org.encog.ml.BasicML;
import org.encog.ml.data.MLData;
import org.encog.neural.NeuralNetworkError;
import org.encog.neural.networks.NeuralDataMapping;

/**
* Bidirectional associative memory (BAM) is a type of neural network
* developed by Bart Kosko in 1988. The BAM is a recurrent neural network
* that works similarly that allows patterns of different lengths to be
* mapped bidirectionally to other patterns. This allows it to act as
* almost a two-way hash map. During training the BAM is fed pattern pairs.
* The two halves of each pattern do not have to be the to be of the
* same length. However all patterns must be of the same overall structure.
* The BAM can be fed a distorted pattern on either side and will attempt
* to map to the correct value.
*
* @author jheaton
*
*/
public class BAM extends BasicML {

  /**
   * Serial id.
   */
  private static final long serialVersionUID = 1L;

  /**
   * Neurons in the F1 layer.
   */
  private int f1Count;
 
  /**
   * Neurons in the F2 layer.
   */
  private int f2Count;

  /**
   * The weights between the F1 and F2 layers.
   */
  private Matrix weightsF1toF2;
 
  /**
   * The weights between the F1 and F2 layers.
   */
  private Matrix weightsF2toF1;

  /**
   * Default constructor, used mainly for persistence.
   */
  public BAM() {

  }

  /**
   * Construct the BAM network.
   * @param theF1Count The F1 count.
   * @param theF2Count The F2 count.
   */
  public BAM(final int theF1Count, final int theF2Count) {
    this.f1Count = theF1Count;
    this.f2Count = theF2Count;

    this.weightsF1toF2 = new Matrix(f1Count, f2Count);
    this.weightsF2toF1 = new Matrix(f2Count, f1Count);
  }

  /**
   * Add a pattern to the neural network.
   *
   * @param inputPattern
   *            The input pattern.
   * @param outputPattern
   *            The output pattern(for this input).
   */
  public final void addPattern(final MLData inputPattern,
      final MLData outputPattern) {

    int weight;

    for (int i = 0; i < this.f1Count; i++) {
      for (int j = 0; j < this.f2Count; j++) {
        weight = (int) (inputPattern.getData(i) * outputPattern
            .getData(j));
        this.weightsF1toF2.add(i, j, weight);
        this.weightsF2toF1.add(j, i, weight);
      }
    }

  }

  /**
   * Clear any connection weights.
   */
  public final void clear() {
    this.weightsF1toF2.clear();
    this.weightsF2toF1.clear();
  }

  /**
   * Setup the network logic, read parameters from the network. NOT USED, call
   * compute(NeuralInputData).
   *
   * @param input
   *            NOT USED
   * @return NOT USED
   */
  public final MLData compute(final MLData input) {
    throw new NeuralNetworkError(
        "Compute on BasicNetwork cannot be used, rather call"
            + " the compute(NeuralData) method on the BAMLogic.");

  }

  /**
   * Compute the network for the specified input.
   *
   * @param input
   *            The input to the network.
   * @return The output from the network.
   */
  public final NeuralDataMapping compute(final NeuralDataMapping input) {

    boolean stable1 = true, stable2 = true;

    do {

      stable1 = propagateLayer(this.weightsF1toF2, input.getFrom(),
          input.getTo());
      stable2 = propagateLayer(this.weightsF2toF1, input.getTo(),
          input.getFrom());

    } while (!stable1 && !stable2);
    return null;
  }

  /**
   * @return the f1Count
   */
  public final int getF1Count() {
    return this.f1Count;
  }

  /**
   * @return the f2Count
   */
  public final int getF2Count() {
    return this.f2Count;
  }

  /**
   * Get the specified weight.
   *
   * @param matrix The matrix to use.
   * @param input
   *            The input, to obtain the size from.
   * @param x
   *            The x matrix value. (could be row or column, depending on
   *            input)
   * @param y
   *            The y matrix value. (could be row or column, depending on
   *            input)
   * @return The value from the matrix.
   */
  private double getWeight(final Matrix matrix, final MLData input,
      final int x, final int y) {
    if (matrix.getRows() != input.size()) {
      return matrix.get(x, y);
    } else {
      return matrix.get(y, x);
    }
  }

  /**
   * @return the weightsF1toF2
   */
  public final Matrix getWeightsF1toF2() {
    return this.weightsF1toF2;
  }

  /**
   * @return the weightsF2toF1
   */
  public final Matrix getWeightsF2toF1() {
    return this.weightsF2toF1;
  }

  /**
   * Propagate the layer.
   *
   * @param matrix
   *            The matrix for this layer.
   * @param input
   *            The input pattern.
   * @param output
   *            The output pattern.
   * @return True if the network has become stable.
   */
  private boolean propagateLayer(final Matrix matrix, final MLData input,
      final MLData output) {
    int i, j;
    int sum, out = 0;
    boolean stable;

    stable = true;

    for (i = 0; i < output.size(); i++) {
      sum = 0;
      for (j = 0; j < input.size(); j++) {
        sum += getWeight(matrix, input, i, j) * input.getData(j);
      }
      if (sum != 0) {
        if (sum < 0) {
          out = -1;
        } else {
          out = 1;
        }
        if (out != (int) output.getData(i)) {
          stable = false;
          output.setData(i, out);
        }
      }
    }
    return stable;
  }

  /**
   * Set the F1 neuron count.
   * @param i The count.
   */
  public final void setF1Count(final int i) {
    this.f1Count = i;
  }

  /**
   * Set the F2 neuron count.
   * @param i The count.
   */
  public final void setF2Count(final int i) {
    this.f2Count = i;
  }

  /**
   * Set the weights for F1 to F2.
   * @param matrix The weight matrix.
   */
  public final void setWeightsF1toF2(final Matrix matrix) {
    this.weightsF1toF2 = matrix;
  }

  /**
   * Set the weights for F2 to F1.
   * @param matrix The weight matrix.
   */
  public final void setWeightsF2toF1(final Matrix matrix) {
    this.weightsF2toF1 = matrix;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void updateProperties() {
    // TODO Auto-generated method stub
  }
}
TOP

Related Classes of org.encog.neural.bam.BAM

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.