示例#1
0
        public float[] NNRun(float[] inputs)
        {
            Outputs = NN.Run(inputs);

            return(Outputs);
        }
示例#2
0
        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];
                }
            }
        }
示例#3
0
        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);
        }