public void SGD(ref MnistData data, int epochs, int batchSize, float learningRate, bool output)
        {
            MathNet.Numerics.Control.UseSingleThread(); // Single thread is optimal over multithreading.

            Console.WriteLine("Training...");

            for (int l = 0; l < vSizes.Count; l++)
            {
                mSumW[l].Clear();
                mSumB[l].Clear();
            }

            RandomizeParameters();

            for (int i = 0; i < epochs; i++)
            {
                for (int j = 0; j < data.TrainImages.ColumnCount; j++)
                {
                    SetInputLayer(data.TrainImages.Column(j));
                    FeedForward();
                    SetOutputLayer((int)(data.TrainLabels[j]));
                    OutputError();
                    Backprop();

                    // Perform summation calculations over the training images.
                    for (int l = lastLayerIndex; l > 0; l--)
                    {
                        mSumW[l] += mError[l].ToColumnMatrix() * mNeurons[l - 1].ToRowMatrix();
                        mSumB[l] += mError[l];
                    }

                    // Update the weights and biases after the mini-batch has been processed.
                    if (j % batchSize == 0 && j > 0)
                    {
                        for (int l = 0; l < vSizes.Count; l++)
                        {
                            mWeights[l] += mSumW[l].Multiply(-learningRate / batchSize);
                            mBiases[l]  += mSumB[l].Multiply(-learningRate / batchSize);
                            mSumW[l].Clear();
                            mSumB[l].Clear();
                        }
                    }
                }
                if (output == true)
                {
                    Console.WriteLine("Epoch {0}: {1} / {2}", i, MnistTest(ref data), data.TestLabels.Count);
                }
            }
            Console.WriteLine("Training Complete.");
        }
        public int MnistTest(ref MnistData data)
        {
            int correct = 0;
            int total   = data.TestLabels.Count;

            for (int i = 0; i < total; i++)
            {
                SetInputLayer(data.TestImages.Column(i));
                FeedForward();
                if ((mNeurons[lastLayerIndex].MaximumIndex()) == data.TestLabels[i])
                {
                    correct++;
                }
            }
            Console.WriteLine(correct / total);
            this.Accuracy = (double)correct / (double)total;
            return(correct);
        }