Package org.encog.neural.thermal

Source Code of org.encog.neural.thermal.HopfieldNetwork

/*
* 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.thermal;

import org.encog.mathutil.matrices.BiPolarUtil;
import org.encog.mathutil.matrices.Matrix;
import org.encog.mathutil.matrices.MatrixMath;
import org.encog.ml.data.MLData;
import org.encog.ml.data.specific.BiPolarNeuralData;
import org.encog.neural.NeuralNetworkError;
import org.encog.util.EngineArray;

/**
* Implements a Hopfield network.
*
*/
public class HopfieldNetwork extends ThermalNetwork {

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

  /**
   * Default constructor.
   */
  public HopfieldNetwork() {

  }

  /**
   * Construct a Hopfield with the specified neuron count.
   * @param neuronCount The neuron count.
   */
  public HopfieldNetwork(final int neuronCount) {
    super(neuronCount);
  }

  /**
   * Train the neural network for the specified pattern. The neural network
   * can be trained for more than one pattern. To do this simply call the
   * train method more than once.
   *
   * @param pattern
   *            The pattern to train for.
   */
  public final void addPattern(final MLData pattern) {

    if (pattern.size() != getNeuronCount()) {
      throw new NeuralNetworkError("Network with " + getNeuronCount()
          + " neurons, cannot learn a pattern of size "
          + pattern.size());
    }

    // Create a row matrix from the input, convert boolean to bipolar
    final Matrix m2 = Matrix.createRowMatrix(pattern.getData());
    // Transpose the matrix and multiply by the original input matrix
    final Matrix m1 = MatrixMath.transpose(m2);
    final Matrix m3 = MatrixMath.multiply(m1, m2);

    // matrix 3 should be square by now, so create an identity
    // matrix of the same size.
    final Matrix identity = MatrixMath.identity(m3.getRows());

    // subtract the identity matrix
    final Matrix m4 = MatrixMath.subtract(m3, identity);

    // now add the calculated matrix, for this pattern, to the
    // existing weight matrix.
    convertHopfieldMatrix(m4);
  }

  /**
   * Note: for Hopfield networks, you will usually want to call the "run"
   * method to compute the output.
   *
   * This method can be used to copy the input data to the current state. A
   * single iteration is then run, and the new current state is returned.
   *
   * @param input
   *            The input pattern.
   * @return The new current state.
   */
  @Override
  public final MLData compute(final MLData input) {
    final BiPolarNeuralData result = new BiPolarNeuralData(input.size());
    EngineArray.arrayCopy(input.getData(), getCurrentState().getData());
    run();

    for (int i = 0; i < getCurrentState().size(); i++) {
      result.setData(i,
          BiPolarUtil.double2bipolar(getCurrentState().getData(i)));
    }
    EngineArray.arrayCopy(getCurrentState().getData(), result.getData());
    return result;
  }

  /**
   * Update the Hopfield weights after training.
   *
   * @param delta
   *            The amount to change the weights by.
   */
  private void convertHopfieldMatrix(final Matrix delta) {
    // add the new weight matrix to what is there already
    for (int row = 0; row < delta.getRows(); row++) {
      for (int col = 0; col < delta.getRows(); col++) {
        addWeight(row, col, delta.get(row, col));
      }
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public final int getInputCount() {
    return super.getNeuronCount();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public final int getOutputCount() {
    return super.getNeuronCount();
  }

  /**
   * Perform one Hopfield iteration.
   */
  public final void run() {

    for (int toNeuron = 0; toNeuron < getNeuronCount(); toNeuron++) {
      double sum = 0;
      for (int fromNeuron = 0; fromNeuron < getNeuronCount(); fromNeuron++) {
        sum += getCurrentState().getData(fromNeuron)
            * getWeight(fromNeuron, toNeuron);
      }
      getCurrentState().setData(toNeuron, sum);
    }
  }

  /**
   * Run the network until it becomes stable and does not change from more
   * runs.
   *
   * @param max
   *            The maximum number of cycles to run before giving up.
   * @return The number of cycles that were run.
   */
  public final int runUntilStable(final int max) {
    boolean done = false;
    String lastStateStr = getCurrentState().toString();
    String currentStateStr = getCurrentState().toString();

    int cycle = 0;
    do {
      run();
      cycle++;

      lastStateStr = getCurrentState().toString();

      if (!currentStateStr.equals(lastStateStr)) {
        if (cycle > max) {
          done = true;
        }
      } else {
        done = true;
      }

      currentStateStr = lastStateStr;

    } while (!done);

    return cycle;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void updateProperties() {
    // nothing needed here
  }

}
TOP

Related Classes of org.encog.neural.thermal.HopfieldNetwork

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.