/// <summary> /// This method implements weights update procedure for the single neuron for /// the back propagation with momentum factor /// </summary> /// <param name="neuron"> neuron to update weights </param> public override void updateNeuronWeights(Neuron neuron) { foreach (Connection connection in neuron.InputConnections) { double input = connection.Input; if (input == 0) { continue; } // get the error for specified neuron, double neuronError = neuron.Error; // tanh can be used to minimise the impact of big error values, which can cause network instability // suggested at https://sourceforge.net/tracker/?func=detail&atid=1107579&aid=3130561&group_id=238532 // double neuronError = Math.tanh(neuron.getError()); Weight weight = connection.Weight; MomentumWeightTrainingData weightTrainingData = (MomentumWeightTrainingData)weight.TrainingData; //double currentWeightValue = weight.getValue(); double previousWeightValue = weightTrainingData.previousValue; double weightChange = this.learningRate * neuronError * input + momentum * (weight.value - previousWeightValue); // save previous weight value //weight.getTrainingData().set(TrainingData.PREVIOUS_WEIGHT, currentWeightValue); weightTrainingData.previousValue = weight.value; // if the learning is in batch mode apply the weight change immediately if (this.InBatchMode == false) { weight.weightChange = weightChange; weight.value += weightChange; } // otherwise, sum the weight changes and apply them after at the end of epoch else { weight.weightChange += weightChange; } } }
/// <summary> /// Creates connections with shared weights between two feature maps /// Assumes that toMap is from Pooling layer. /// <p/> /// In this implementation, there is no overlapping between kernel positions. /// </summary> /// <param name="fromMap"> source feature map </param> /// <param name="toMap"> destination feature map </param> public override void connectMaps(FeatureMapLayer fromMap, FeatureMapLayer toMap) { int kernelWidth = kernel.Width; int kernelHeight = kernel.Height; Weight weight = new Weight(1); for (int x = 0; x < fromMap.Width - kernelWidth + 1; x += kernelWidth) // < da li step treba da je kernel { for (int y = 0; y < fromMap.Height - kernelHeight + 1; y += kernelHeight) { Neuron toNeuron = toMap.getNeuronAt(x / kernelWidth, y / kernelHeight); for (int dy = 0; dy < kernelHeight; dy++) { for (int dx = 0; dx < kernelWidth; dx++) { int fromX = x + dx; int fromY = y + dy; Neuron fromNeuron = fromMap.getNeuronAt(fromX, fromY); ConnectionFactory.createConnection(fromNeuron, toNeuron, weight); } } } } }
/// <summary> /// Creates connection between two specified neurons /// </summary> /// <param name="fromNeuron"> /// neuron to connect (connection source) </param> /// <param name="toNeuron"> /// neuron to connect to (connection target) </param> /// <param name="weight"> /// connection weight </param> public static void createConnection(Neuron fromNeuron, Neuron toNeuron, Weight weight) { Connection connection = new Connection(fromNeuron, toNeuron, weight); toNeuron.addInputConnection(connection); }