<commit_before>package org.encog.neural.networks.training.propagation;

import org.encog.neural.data.NeuralData;
import org.encog.neural.data.NeuralDataPair;
import org.encog.neural.data.NeuralDataSet;
import org.encog.neural.networks.BasicNetwork;
import org.encog.neural.networks.NeuralOutputHolder;
import org.encog.neural.networks.layers.Layer;
import org.encog.neural.networks.synapse.Synapse;
import org.encog.util.ErrorCalculation;

import java.util.HashMap;
import java.util.Map;

public class PropagateErrors {

	private BasicNetwork network;
	private Map<Layer, Object> layerDeltas = new HashMap<Layer, Object>();
	private double[] errors;
	private double[] weights;
	private NeuralOutputHolder holder;
	private ErrorCalculation error = new ErrorCalculation();

	public PropagateErrors(BasicNetwork network) {
		this.network = network;
		int size = network.getStructure().calculateSize();
		this.errors = new double[size];
		this.holder = new NeuralOutputHolder();
	}

	public double[] getErrors() {
		return this.errors;
	}

	private double[] getLayerDeltas(Layer layer) {
		if (this.layerDeltas.containsKey(layer)) {
			return (double[]) this.layerDeltas.get(layer);
		}

		double[] result = new double[layer.getNeuronCount()];
		this.layerDeltas.put(layer, result);
		return result;
	}
	
	private void clearDeltas()
	{
		for(Object obj: this.layerDeltas.values())
		{
			double[] d = (double[])obj;
			for(int i=0;i<d.length;i++) {
				d[i] = 0;
			}
		}
	}
	
	public void calculate(NeuralDataSet training, double[] weights) {
		reset(weights);
		for(NeuralDataPair pair: training) {
			calculate(pair.getInput(), pair.getIdeal());
		}				
	}

	public void calculate(NeuralData input, NeuralData ideal) {
		clearDeltas();
		
		this.holder = new NeuralOutputHolder();
		Layer output = this.network.getLayer(BasicNetwork.TAG_OUTPUT);
		NeuralData actual = this.network.compute(input, this.holder);
		
		this.error.updateError(actual.getData(), ideal.getData());
		
		double deltas[] = getLayerDeltas(output);

		for (int i = 0; i < deltas.length; i++) {
			deltas[i] = actual.getData(i);
		}

		// take the derivative of these outputs
		output.getActivationFunction().derivativeFunction(deltas);

		// multiply by the difference between the actual and idea
		for (int i = 0; i < output.getNeuronCount(); i++) {
			deltas[i] = deltas[i] * (ideal.getData(i) - actual.getData(i));
		}

		int index = 0;
		for(Layer layer: this.network.getStructure().getLayers()) {
			double layerDeltas[] = getLayerDeltas(layer);
			
			if( layer.hasThreshold() ) {
				for(int i=0;i<layerDeltas.length;i++) {
					this.errors[index++] += layerDeltas[i]; 
				}	
			}
			
			for(Synapse synapse: this.network.getStructure().getPreviousSynapses(layer)) {
				index = calculate(synapse,index);
			}			
		}		
	}

	private int calculate(Synapse synapse, int index) {
		
		double toDeltas[] = getLayerDeltas(synapse.getToLayer());
		double fromDeltas[] = getLayerDeltas(synapse.getFromLayer());
		
		NeuralData actual = this.holder.getResult().get(synapse);
		
		for (int x = 0; x < synapse.getToNeuronCount(); x++) {
			for (int y = 0; y < synapse.getFromNeuronCount(); y++) {
				double value = actual.getData(y)*toDeltas[x];
				errors[index] += value;
				fromDeltas[y] +=  this.weights[index]*toDeltas[x];
				index++;
			}
		}
		
		double[] temp = new double[fromDeltas.length];

		for (int i = 0; i < fromDeltas.length; i++) {
			temp[i] = actual.getData(i);
		}

		// get an activation function to use
		synapse.getToLayer().getActivationFunction().derivativeFunction(temp);

		for (int i = 0; i < temp.length; i++) {
			fromDeltas[i] *= temp[i];
		}
				
		return index;
	}

	public void reset(double[] weights) {
		this.error.reset();
		this.weights = weights;
		this.layerDeltas.clear();
		
		for (int i = 0; i < this.errors.length; i++)
			this.errors[i] = 0;
	}

	public double getError() {
		return this.error.calculateRMS();
	}<commit_msg>allow linear layer on output<commit_after>package org.encog.neural.networks.training.propagation;

import org.encog.neural.activation.ActivationLinear;
import org.encog.neural.data.NeuralData;
import org.encog.neural.data.NeuralDataPair;
import org.encog.neural.data.NeuralDataSet;
import org.encog.neural.networks.BasicNetwork;
import org.encog.neural.networks.NeuralOutputHolder;
import org.encog.neural.networks.layers.Layer;
import org.encog.neural.networks.synapse.Synapse;
import org.encog.util.ErrorCalculation;

import java.util.HashMap;
import java.util.Map;

public class PropagateErrors {

	private BasicNetwork network;
	private Map<Layer, Object> layerDeltas = new HashMap<Layer, Object>();
	private double[] errors;
	private double[] weights;
	private NeuralOutputHolder holder;
	private ErrorCalculation error = new ErrorCalculation();

	public PropagateErrors(BasicNetwork network) {
		this.network = network;
		int size = network.getStructure().calculateSize();
		this.errors = new double[size];
		this.holder = new NeuralOutputHolder();
	}

	public double[] getErrors() {
		return this.errors;
	}

	private double[] getLayerDeltas(Layer layer) {
		if (this.layerDeltas.containsKey(layer)) {
			return (double[]) this.layerDeltas.get(layer);
		}

		double[] result = new double[layer.getNeuronCount()];
		this.layerDeltas.put(layer, result);
		return result;
	}
	
	private void clearDeltas()
	{
		for(Object obj: this.layerDeltas.values())
		{
			double[] d = (double[])obj;
			for(int i=0;i<d.length;i++) {
				d[i] = 0;
			}
		}
	}
	
	public void calculate(NeuralDataSet training, double[] weights) {
		reset(weights);
		for(NeuralDataPair pair: training) {
			calculate(pair.getInput(), pair.getIdeal());
		}				
	}

	public void calculate(NeuralData input, NeuralData ideal) {
		clearDeltas();
		
		this.holder = new NeuralOutputHolder();
		Layer output = this.network.getLayer(BasicNetwork.TAG_OUTPUT);
		NeuralData actual = this.network.compute(input, this.holder);
		
		this.error.updateError(actual.getData(), ideal.getData());
		
		double deltas[] = getLayerDeltas(output);

		if ( output.getActivationFunction().hasDerivative() ) {
			for (int i = 0; i < deltas.length; i++) {
				deltas[i] = actual.getData(i);
			}

			// take the derivative of these outputs
			output.getActivationFunction().derivativeFunction(deltas);

			// multiply by the difference between the actual and idea
			for (int i = 0; i < output.getNeuronCount(); i++) {
				deltas[i] = deltas[i] * (ideal.getData(i) - actual.getData(i));
			}
		}
		else
		{
			for (int i = 0; i < output.getNeuronCount(); i++) 
				deltas[i] = (ideal.getData(i) - actual.getData(i));
		}

		int index = 0;
		for(Layer layer: this.network.getStructure().getLayers()) {
			double layerDeltas[] = getLayerDeltas(layer);
			
			if( layer.hasThreshold() ) {
				for(int i=0;i<layerDeltas.length;i++) {
					this.errors[index++] += layerDeltas[i]; 
				}	
			}
			
			for(Synapse synapse: this.network.getStructure().getPreviousSynapses(layer)) {
				index = calculate(synapse,index);
			}			
		}		
	}

	private int calculate(Synapse synapse, int index) {
		
		double toDeltas[] = getLayerDeltas(synapse.getToLayer());
		double fromDeltas[] = getLayerDeltas(synapse.getFromLayer());
		
		NeuralData actual = this.holder.getResult().get(synapse);
		
		for (int x = 0; x < synapse.getToNeuronCount(); x++) {
			for (int y = 0; y < synapse.getFromNeuronCount(); y++) {
				double value = actual.getData(y)*toDeltas[x];
				errors[index] += value;
				fromDeltas[y] +=  this.weights[index]*toDeltas[x];
				index++;
			}
		}
		
		double[] temp = new double[fromDeltas.length];

		for (int i = 0; i < fromDeltas.length; i++) {
			temp[i] = actual.getData(i);
		}

		// get an activation function to use
		synapse.getFromLayer().getActivationFunction().derivativeFunction(temp);

		for (int i = 0; i < temp.length; i++) {
			fromDeltas[i] *= temp[i];
		}
				
		return index;
	}

	public void reset(double[] weights) {
		this.error.reset();
		this.weights = weights;
		this.layerDeltas.clear();
		
		for (int i = 0; i < this.errors.length; i++)
			this.errors[i] = 0;
	}

	public double getError() {
		return this.error.calculateRMS();
	}
{'fraction_non_alphanumeric': 0.14371624938635247, 'fraction_numerical': 0.0030682376043200785, 'mean_word_length': 4.014769230769231, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6542663', 'n_tokens_mistral': 3208, 'n_tokens_neox': 2797, 'n_words': 575}