protected void performGradientDescent(Pattern<?,?> pattern) throws NNException {
		try {
			network.process(pattern.getInputSignal());
			
			// Calculate derivatives for the final layer:
			for (int i = 0; i < network.numberOfOutputs(); i++) {
				Neuron neuron = network.outputLayer.get(i);
				Double correctValue = pattern.getOutputSignal().get(i);
				derivatives.put(neuron, (neuron.lastResult - correctValue)*2);
			}
			
			// Iterate through layers backwards and compute layer's derivatives
			// and weights from the next layer's ones.
			LayerIterator iter = new LayerIterator(network);
			// Must start from the next to last layer:
			List<? extends Neuron> curLayer = iter.previous();
			while (iter.hasPrevious()) {
				curLayer = iter.previous();
				// The gist of calculation:
				for (Neuron curNeuron : curLayer) {
					double derivative = 0;
					for (Neuron nextNeuron : curNeuron.outputs) {
						double weight = nextNeuron.getInputWeight(curNeuron);
						double nextObjDeriv = derivatives.get(nextNeuron);
						double nextActivFeriv = nextNeuron.getActivationFunction().derivative(nextNeuron.accumulatedInput);
						derivative += weight * nextObjDeriv * nextActivFeriv;
						//System.out.println("Gradient is " + nextObjDeriv * nextActivFeriv * curNeuron.lastResult);
						weight -= gradientStep * nextObjDeriv * nextActivFeriv * curNeuron.lastResult;
						nextNeuron.setInputWeight(curNeuron, weight);
					}
					derivatives.put(curNeuron, Double.valueOf(derivative));
				}
			}
		} catch (NNException e) {
			throw e;
		} catch (Exception e) {
			throw new NNException(e);
		}
	}