public static DoubleVectorList Load(BinaryReader r)
        {
            DoubleVectorList nnvl = new DoubleVectorList();
            int count             = r.ReadInt32();

            for (int i = 0; i < count; i++)
            {
                nnvl.Add(DoubleVector.Load(r));
            }
            return(nnvl);
        }
        /// <summary>
        /// Train the network on a single input vector. Returns the sum of the mean square error of the sets.
        /// </summary>
        /// <param name="inputs">The input vectors to train on</param>
        /// <param name="targets">The target output vectors</param>
        /// <param name="iterations">The number of iterations to train on these inputs</param>
        public double Train(DoubleVectorList inputs, DoubleVectorList targets, int iterations)
        {
            // Make sure all input vectors have a matching output vector
            if (inputs.Count != targets.Count)
            {
                throw new Exception("You must provide a desired output vector for each input vector!");
            }

            double error = 0.0;
            int    progress;

            Random r = new Random();

            for (int i = 0; i < iterations; i++)
            {
                // The error for this iteration
                error = 0.0;

                // Create a list of indexes and mix it up so that we don't train on the sets sequentially
                List <int> indices = new List <int>();
                for (int n = 0; n < inputs.Count; n++)
                {
                    indices.Insert(r.Next(n), n);
                }

                // Train for one iteration on this set
                for (int s = 0; s < inputs.Count; s++)
                {
                    error += Train(inputs[indices[s]], targets[indices[s]], 1);

                    // Report Progress
                    progress = (int)(((double)i * 100 / (double)iterations) + (((double)s * 100) / (double)inputs.Count) / (double)iterations);
                    if (OnTrainingProgressChange != null)
                    {
                        OnTrainingProgressChange(this, new OnTrainingProgressChangeEventArgs(progress, (error / (double)s) * (double)inputs.Count));
                    }
                }

                // Lower the learning rate
                learningRate *= _learningRateDescent;
            }

            // Return error of most recent iteration
            return(error);
        }