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); }