public float[] NNRun(float[] inputs) { Outputs = NN.Run(inputs); return(Outputs); }
static void Main(string[] args) { FeedForwardNN nn = new FeedForwardNN(new FeedForwardNNDescriptor()); nn.ReadWeights("mnist.xml"); float[][] testData = new float[10000][]; float[][] testAnswers = new float[10000][]; int index = 0; using (StreamReader sr = new StreamReader(@"C:\Users\Dima\source\repos\NeuralNet1\NeuralNetRun\bin\Debug\mnist_test.csv", System.Text.Encoding.Default)) { string line; while ((line = sr.ReadLine()) != null) { string[] array = line.Split(','); float[] data = new float[784]; int label = Convert.ToInt32(array[0]); for (int i = 0; i < 784; i++) { data[i] = Normalize.Minimax(Convert.ToInt32(array[i + 1]), 0, 255); } float[] answer = new float[10]; answer[label] = 1; testData[index] = data; testAnswers[index] = answer; index++; } } Trainer trainer = new Trainer(ref nn); trainer.TrainBackPropogation(1, 1, 0.0001f, 0.3f, testData, new float[][] { }, testAnswers, new float[][] { }); float[][] o = new float[3][]; o[0] = nn.Run(testData[0]); o[1] = nn.Run(testData[1]); o[2] = nn.Run(testData[2]); int answer0; int answer1; int answer2; float max = 0; for (int i = 0; i < o[0].Length; i++) { if (o[0][i] > max) { answer0 = i; max = o[0][i]; } } max = 0; for (int i = 0; i < o[0].Length; i++) { if (o[1][i] > max) { answer1 = i; max = o[1][i]; } } max = 0; for (int i = 0; i < o[0].Length; i++) { if (o[2][i] > max) { answer2 = i; max = o[2][i]; } } }
public int TrainBackPropogation(int epochs, int iterCount, float learningRate, float moment, float[][] learnData, float[][] testData, float[][] learnAnswers, float[][] testAnswers, float[] DOScheme = null, float accuracyChangeLimit = -1, bool logging = true, string logFileName = "Train log.txt") //берем кол-во эпох, итераций в эпохе, данные для обучения, ответы { bool DOSchemeIsCorrect = NeuralNet.CheckDOScheme(DOScheme); if (DOScheme != null) { if (DOScheme.Length + 2 != NeuralNet.Outputs.Count) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Incorrect dropout scheme"); Console.ForegroundColor = ConsoleColor.White; } } List <List <float> > deltas = new List <List <float> >(); // создаем листы для хранения дельт for (int i = 0; i < NeuralNet.Outputs.Count; i++) { deltas.Add(new List <float>()); // добавляем ячейки для вычислений, так же как в листы output for (int k = 0; k < NeuralNet.Outputs[i].Count; k++) { deltas[i].Add(0f); } } StreamWriter logger = new StreamWriter(logFileName, false); float prevTestMSE = 0; for (int epoch = 0; epoch < epochs; epoch++) { for (int iter = 0; iter < iterCount; iter++) { for (int learnDataCounter = 0; learnDataCounter < learnData.Length; learnDataCounter++) { float[] NNOut; if (DOScheme != null && DOSchemeIsCorrect == true) { NNOut = NeuralNet.RunDropOut(learnData[learnDataCounter], DOScheme); // получаем выходы нс } else { NNOut = NeuralNet.Run(learnData[learnDataCounter]); // получаем выходы нс } for (int i = 0; i < NNOut.Length; i++) { deltas[deltas.Count - 1][i] = (learnAnswers[learnDataCounter][i] - NNOut[i]) * NeuralNet.Descriptor.GetDerivedActivation()(NNOut[i]);//параллельно считаем дельты выходных нейронов } for (int layer = NeuralNet.Weights.Count - 1; layer >= 0; layer--) { for (int neuron = 0; neuron < NeuralNet.Outputs[layer].Count; neuron++) { for (int synapse = 0; synapse < NeuralNet.Outputs[layer + 1].Count; synapse++) { deltas[layer][neuron] = deltas[layer + 1][synapse] * NeuralNet.Weights[layer][synapse][neuron]; // суммируем } deltas[layer][neuron] *= NeuralNet.Descriptor.GetDerivedActivation()(NeuralNet.Outputs[layer][neuron]); // домножаем на производную } } for (int layer = NeuralNet.Weights.Count - 1; layer >= 0; layer--) { for (int neuron = 0; neuron < NeuralNet.Outputs[layer].Count; neuron++) { for (int synapse = 0; synapse < NeuralNet.Outputs[layer + 1].Count; synapse++) { float deltaW = NeuralNet.Outputs[layer][neuron] * deltas[layer + 1][synapse]; deltaW = learningRate * deltaW + moment * NeuralNet.WeightsDeltas[layer][synapse][neuron]; // тут сложно см ниже NeuralNet.Weights[layer][synapse][neuron] += deltaW; NeuralNet.WeightsDeltas[layer][synapse][neuron] = deltaW; } } } Console.WriteLine($"DataCounter = {learnDataCounter}"); /* * суть подсчета дельт такая: * т.к. у нас слоев весов 2(см. 1.jpg), а выходов и дельт всегда на 1 слой больше, так еще и веса у нас на вход, то * получается не очень удобно считать дельты. Поэтому я в перебираю не синапсы от нейрона, а нейроны, а нейроны от нейрона(2.jpg) * Как хранятся веса: Слой, нейрон, входы в этот нейрон */ } if (iter % 10 == 0) { float TotalMse = 0; for (int testDataCounter = 0; testDataCounter < testData.Length; testDataCounter++) { float[] NNOut = NeuralNet.Run(testData[testDataCounter]); // получаем выходы нс float MSE = 0; for (int i = 0; i < NNOut.Length; i++) { MSE += (float)Math.Pow(testAnswers[testDataCounter][i] - NNOut[i], 2); //подсчитываем сумму ошибок } MSE = MSE / NNOut.Length; // делим TotalMse += MSE; } TotalMse /= testData.Length; if (logging) { logger.WriteLine(TotalMse.ToString()); Console.WriteLine($"Epoch: {epoch + 1}\t Iteration: {iter}\t Avg test error: {TotalMse}"); } if (Math.Abs(prevTestMSE - TotalMse) < accuracyChangeLimit) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Accuracy limit!"); Console.ForegroundColor = ConsoleColor.White; return(2); } prevTestMSE = TotalMse; } } } logger.Close(); return(1); }