/*
* Encog(tm) Core v2.5 - Java Version
* http://www.heatonresearch.com/encog/
* http://code.google.com/p/encog-java/
* Copyright 2008-2010 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.networks.layers;
import org.encog.engine.network.activation.ActivationFunction;
import org.encog.engine.network.activation.ActivationTANH;
import org.encog.neural.NeuralNetworkError;
import org.encog.neural.data.NeuralData;
import org.encog.neural.data.basic.BasicNeuralData;
import org.encog.neural.networks.ContextClearable;
import org.encog.persist.Persistor;
import org.encog.persist.persistors.ContextLayerPersistor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implements a context layer. A context layer is used to implement a simple
* recurrent neural network, such as an Elman or Jordan neural network. The
* context layer has a short-term memory. The context layer accept input, and
* provide the same data as output on the next cycle. This continues, and the
* context layer's output "one step" out of sync with the input.
*
* @author jheaton
*
*/
public class ContextLayer extends BasicLayer implements ContextClearable {
public static final String ERROR = "Bias is not suppoted for a contextlayer.";
/**
* The serial id.
*/
private static final long serialVersionUID = -5588659547177460637L;
/**
* The context data that this layer will store.
*/
private final NeuralData context;
/**
* The location in the flat network that the context is stored at.
*/
private int flatContextIndex = -1;
/**
* The logging object.
*/
private static final transient Logger LOGGER = LoggerFactory
.getLogger(ContextLayer.class);
/**
* Default constructor, mainly so the workbench can easily create a default
* layer.
*/
public ContextLayer() {
this(1);
}
/**
* Construct a context layer with the parameters specified.
*
* @param activationFunction
* The activation function to use.
* @param neuronCount
* The neuron count to use.
*/
public ContextLayer(final ActivationFunction activationFunction,
final int neuronCount) {
super(activationFunction, false, neuronCount);
this.context = new BasicNeuralData(neuronCount);
}
/**
* Construct a default context layer that has the TANH activation function
* and the specified number of neurons. Use bias values.
*
* @param neuronCount
* The number of neurons on this layer.
*/
public ContextLayer(final int neuronCount) {
this(new ActivationTANH(), neuronCount);
}
/**
* Create a persistor for this layer.
*
* @return The new persistor.
*/
@Override
public Persistor createPersistor() {
return new ContextLayerPersistor();
}
/**
* @return The context, or memory of this layer. These will be the values
* that were just output.
*/
public NeuralData getContext() {
return this.context;
}
/**
* Called to process input from the previous layer. Simply store the output
* in the context.
*
* @param pattern
* The pattern to store in the context.
*/
@Override
public void process(final NeuralData pattern) {
double[] s = pattern.getData();
double[] t = this.context.getData();
System.arraycopy(s, 0, t, 0, s.length);
if (ContextLayer.LOGGER.isDebugEnabled()) {
ContextLayer.LOGGER.debug("Updated ContextLayer to {}", pattern);
}
}
/**
* Called to get the output from this layer when called in a recurrent
* manor. Simply return the context that was kept from the last iteration.
*
* @return The recurrent output.
*/
@Override
public NeuralData recur() {
return this.context;
}
/**
* Reset the context values back to zero.
*/
public void clearContext() {
for (int i = 0; i < this.context.size(); i++) {
this.context.setData(i, 0);
}
}
/**
* @return The weight biases.
*/
public double[] getBiasWeights() {
throw new NeuralNetworkError(ERROR);
}
/**
* Get one weight bias value.
* @param index The index to get.
* @return The bias value.
*/
public double getBiasWeight(final int index) {
throw new NeuralNetworkError(ERROR);
}
/**
* Set the bias weights.
* @param d The bias weights.
*/
public void setBiasWeights(final double[] d) {
throw new NeuralNetworkError(ERROR);
}
/**
* Set a bias weight.
* @param index The index of the value to set.
* @param d The new value.
*/
public void setBiasWeight(final int index, final double d) {
throw new NeuralNetworkError(ERROR);
}
/**
* @return The index, in the flat network, where the context is stored.
*/
public int getFlatContextIndex() {
return flatContextIndex;
}
/**
* Set the flat context index.
* @param flatContextIndex The index, in the flat network, where the context is stored.
*/
public void setFlatContextIndex(int flatContextIndex) {
this.flatContextIndex = flatContextIndex;
}
}