/// <summary> /// Stochastic gradient descent algorithm with lazy data loading. /// </summary> public static void SgdLazy(DeepNeuralNetwork nn, int trainingDataSetSize, GetNextDataDelegate getTrainingData, int batchSize, int epochs, double learningRate, UpdateTrainingStatusDelegate statusUpdate, int testDataSetSize = 0, GetNextDataDelegate getTestingData = null, CheckIfCorrectDelegate checkCorrect = null) { Random rng = new Random(); DateTime startingTime = DateTime.Now; int[] dataSetIndexes = new int[trainingDataSetSize]; for (int i = 0; i < dataSetIndexes.Length; ++i) { dataSetIndexes[i] = i; } int currentBatchOffset; int currentBatchSize; for (int epoch = 1; epoch <= epochs; ++epoch) { dataSetIndexes.Shuffle(rng); currentBatchOffset = 0; int currentBatch = 0; for (; currentBatchOffset < trainingDataSetSize; currentBatchOffset += batchSize, ++currentBatch) { int remainingDataSize = trainingDataSetSize - currentBatchOffset; currentBatchSize = remainingDataSize < batchSize ? remainingDataSize : batchSize; TrainWithBatchLazy(nn, currentBatchSize, getData, learningRate); } TrainingStatus status = new TrainingStatus { EpochsDone = epoch }; if (testDataSetSize != 0 && getTestingData != null && checkCorrect != null) { double errorRate = TestNetwork(nn, testDataSetSize, getTestingData, out int correctCount, checkCorrect); status.Error = errorRate; status.Correct = correctCount; } //status update TimeSpan elapsed = DateTime.Now - startingTime; TimeSpan remaining = TimeSpan.FromTicks((long)(elapsed.Ticks * ((epochs - epoch) / (double)epoch))); status.ElapsedTime = elapsed; status.TimeLeft = remaining; statusUpdate(status); } LabeledData getData(int indexInBatch) { int actualIndex = dataSetIndexes[currentBatchOffset + indexInBatch]; return(getTrainingData(actualIndex)); } }
public LazyBatchEnumerator(GetNextDataDelegate getNext, int size) { this.getNext = getNext; this.size = size; currentIndex = 0; }
public LazyBatch(GetNextDataDelegate getNext, int size) { this.getNext = getNext; this.size = size; }
/// <summary> /// Tests the network over a given test dataset. Returns the error ( sum(|a - y(x)|^2)/n ). The out param will count the data that was correctly categorized using a given function. /// </summary> private static double TestNetwork(DeepNeuralNetwork nn, int testingDataSetSize, GetNextDataDelegate getNextData, out int correctCount, CheckIfCorrectDelegate checkCorrect) { correctCount = 0; Vector <double> error = new DenseVector(nn.OutputLayer.GetNeuronCount()); for (int i = 0; i < testingDataSetSize; ++i) { LabeledData labeledData = getNextData(i); Vector <double> result = nn.ProcessInput(labeledData.InputValues); if (checkCorrect(result.AsArray(), labeledData.OutputValues.AsArray())) { ++correctCount; } Vector <double> diff = labeledData.OutputValues - result; error += diff.PointwiseMultiply(diff); } error = error.Divide(testingDataSetSize); return(error.Average()); }
/// <summary> /// Train the network using the given training set. The starting weights and biasses are the ones present in the network when the call to this function is made. /// This "lazy" version means that each training value pair will be read (using the function given as a parameter) only when it has to be processed. /// Recomended when the size of one training data is very large and loading the whole batch would need too much memory. /// Obs.: The lazy loading of the data should be ensured by the function given. /// </summary> public static void TrainWithBatchLazy(DeepNeuralNetwork nn, int batchSize, GetNextDataDelegate getNextData, double learningRate) { LazyBatch batch = new LazyBatch(getNextData, batchSize); TrainWithBatch(nn, batch, batchSize, learningRate); }