public void RandomizeWeights()
        {
            var random = new Random();

            RandomizeLayer(InputLayer, (HiddenLayers.FirstOrDefault() ?? OutputLayer).Count(), random);
            for (int i = 0; i < HiddenLayers.Count; i++)
            {
                RandomizeLayer(HiddenLayers[i], (HiddenLayers.ElementAtOrDefault(i + 1) ?? OutputLayer).Count, random);
            }
        }
        public List <double> FeedForward(double[] input)
        {
            if (input.Length != InputLayer.Count)
            {
                throw new ArgumentException("input length has to be the same as the InputLayer length");
            }

            // calculate input activations
            for (int i = 0; i < input.Length; i++)
            {
                InputLayer[i].ActivationValue = input[i];
            }

            // calculate hidden layer activations
            // i : LayerIndex in HiddenLayers
            // j : NeuronIndex in HiddenLayers[i]
            for (int i = 0; i < HiddenLayers.Count; i++)
            {
                var previousLayer = HiddenLayers.ElementAtOrDefault(i - 1) ?? InputLayer;
                for (int j = 0; j < HiddenLayers[i].Count; j++)
                {
                    HiddenLayers[i][j].ActivationValue = CalculateWeightedSum(previousLayer, j);
                }
            }

            // calculate output activations
            // i : NeuronIndex in OutputLayer
            var lastLayer = HiddenLayers.LastOrDefault() ?? InputLayer;

            for (int i = 0; i < OutputLayer.Count; i++)
            {
                var currentNeuron = OutputLayer[i];
                OutputLayer[i].ActivationValue = CalculateWeightedSum(lastLayer, i);
            }

            // return only values of output layer
            return(OutputLayer.Select(x => x.ActivationValue).ToList());
        }