/**
* Copyright 2014 Neuroph Project http://neuroph.sourceforge.net
*
* 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.
*/
package org.neuroph.core;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ForkJoinPool;
import org.neuroph.core.events.NeuralNetworkEvent;
import org.neuroph.util.NeuronFactory;
import org.neuroph.util.NeuronProperties;
/**
*
* Layer of neurons in a neural network. The Layer is basic neuron container (a collection of neurons),
* and it provides methods for manipulating neurons (add, remove, get, set, calculate, ...).
*
*
* @see Neuron
* @author Zoran Sevarac
*/
public class Layer implements Iterable, Serializable {
/**
* The class fingerprint that is set to indicate serialization compatibility
* with a previous version of the class
*/
private static final long serialVersionUID = 4L;
/**
* Parent neural network - to which this layer belongs
*/
private NeuralNetwork parentNetwork;
/**
* Collection of neurons in this layer
*/
protected List neurons;
/**
* Label for this layer
*/
private String label;
/**
* Creates an instance of empty Layer
*/
public Layer() {
neurons = new ArrayList<>();
}
/**
* Creates an instance of empty Layer for specified number of neurons
* @param neuronsCount number of neurons in this layer
*/
public Layer(int neuronsCount) {
neurons = new ArrayList<>(neuronsCount);
}
/**
* Creates an instance of Layer with the specified number of neurons with
* specified neuron properties
*
* @param neuronsCount number of neurons in layer
* @param neuronProperties properties of neurons in layer
*/
public Layer(int neuronsCount, NeuronProperties neuronProperties) {
this(neuronsCount);
for (int i = 0; i < neuronsCount; i++) {
Neuron neuron = NeuronFactory.createNeuron(neuronProperties);
this.addNeuron(neuron);
}
}
/**
* Sets reference on parent network
*
* @param parent parent network
*/
public final void setParentNetwork(NeuralNetwork parent) {
this.parentNetwork = parent;
}
/**
* Returns reference to parent network
*
* @return reference on parent neural network
*/
public final NeuralNetwork getParentNetwork() {
return this.parentNetwork;
}
/**
* Returns array neurons in this layer as array
*
* @return array of neurons in this layer
*/
public final List getNeurons() {
return Collections.unmodifiableList(neurons);
}
/**
* Adds specified neuron to this layer
*
* @param neuron neuron to add
*/
public final void addNeuron(Neuron neuron) {
// prevent adding null neurons
Objects.requireNonNull(neuron, "Neuron cant be null!");
// if (neuron == null) {
// throw new IllegalArgumentException("Neuron cant be null!");
// }
// set neuron's parent layer to this layer
neuron.setParentLayer(this);
// add new neuron at the end of the array
neurons.add(neuron);
// notify network listeners that neuron has been added
if (parentNetwork != null)
parentNetwork.fireNetworkEvent(new NeuralNetworkEvent(neuron, NeuralNetworkEvent.Type.NEURON_ADDED));
}
/**
* Adds specified neuron to this layer,at specified index position
*
* Throws IllegalArgumentException if neuron is null, or index is
* illegal value (index<0 or index>neuronsCount)
*
* @param neuron neuron to add
* @param index index position at which neuron should be added
*/
public final void addNeuron(int index, Neuron neuron) {
// prevent adding null neurons
if (neuron == null) {
throw new IllegalArgumentException("Neuron cant be null!");
}
// add neuron to this layer
neurons.add(index, neuron);
// set neuron's parent layer to this layer
neuron.setParentLayer(this);
// notify network listeners that neuron has been added
if (parentNetwork != null)
parentNetwork.fireNetworkEvent(new NeuralNetworkEvent(neuron, NeuralNetworkEvent.Type.NEURON_ADDED));
}
/**
* Sets (replace) the neuron at specified position in layer
*
* @param index index position to set/replace
* @param neuron new Neuron object to set
*/
public final void setNeuron(int index, Neuron neuron) {
// make sure that neuron is not null
if (neuron == null) {
throw new IllegalArgumentException("Neuron cant be null!");
}
// new neuron at specified index position
neurons.set(index, neuron);
// set neuron's parent layer to this layer
neuron.setParentLayer(this);
// notify network listeners that neuron has been added
if (parentNetwork != null)
parentNetwork.fireNetworkEvent(new NeuralNetworkEvent(neuron, NeuralNetworkEvent.Type.NEURON_ADDED));
}
/**
* Removes neuron from layer
*
* @param neuron neuron to remove
*/
public final void removeNeuron(Neuron neuron) {
int index = indexOf(neuron);
removeNeuronAt(index);
}
/**
* Removes neuron at specified index position in this layer
*
* @param index index position of neuron to remove
*/
public final void removeNeuronAt(int index) {
Neuron neuron = neurons.get(index);
neuron.setParentLayer(null);
neuron.removeAllConnections(); // why we're doing this here? maybe we shouldnt
neurons.remove(index);
// notify listeners that neuron has been removed
if (parentNetwork != null)
parentNetwork.fireNetworkEvent(new NeuralNetworkEvent(this, NeuralNetworkEvent.Type.NEURON_REMOVED));
}
public final void removeAllNeurons() {
neurons.clear();
// notify listeners that neurons has been removed
if (parentNetwork != null)
parentNetwork.fireNetworkEvent(new NeuralNetworkEvent(this, NeuralNetworkEvent.Type.NEURON_REMOVED));
}
/**
* Returns neuron at specified index position in this layer
*
* @param index neuron index position
* @return neuron at specified index position
*/
public Neuron getNeuronAt(int index) {
return neurons.get(index);
}
/**
* Returns the index position in layer for the specified neuron
*
* @param neuron neuron object
* @return index position of specified neuron
*/
public int indexOf(Neuron neuron) {
return neurons.indexOf(neuron);
}
/**
* Returns number of neurons in this layer
*
* @return number of neurons in this layer
*/
public int getNeuronsCount() {
return neurons.size();
}
//static final ForkJoinPool mainPool = ForkJoinPool.commonPool();
/**
* Performs calculaton for all neurons in this layer
*/
public void calculate() {
for (Neuron neuron : neurons) {
neuron.calculate();
}
// neurons.forEach(Neuron::calculate);
// neurons.parallelStream().forEach( n -> n.calculate());
// mainPool.invokeAll(Arrays.asList(neurons.asArray()));
}
/**
* Resets the activation and input levels for all neurons in this layer
*/
public void reset() {
for (Neuron neuron : this.neurons) {
neuron.reset();
}
}
/**
* Initialize connection weights for the whole layer to to specified value
*
* @param value the weight value
*/
public void initializeWeights(double value) {
for (Neuron neuron : this.neurons) {
neuron.initializeWeights(value);
}
}
/**
* Get layer label
*
* @return layer label
*/
public String getLabel() {
return label;
}
/**
* Set layer label
*
* @param label layer label to set
*/
public void setLabel(String label) {
this.label = label;
}
public boolean isEmpty() {
return neurons.isEmpty();
}
@Override
public Iterator iterator() {
return neurons.iterator();
}
}
Ads help maintain this website.