Made a simple neural network in C #. Everything works fine with a small example, and if I create 10 input neurons and even hidden layers 2. Then I have 700 eras before the perfect answer. And each time a different meaning.

I tried to change the hyperparameters, but without success.

Please look at my code and tell me what I did wrong.

And if it's not difficult can anyone explain where I have an error in finding a neural network error. I kind of did everything on the article, but it does not work.

Ps in general, the idea was that 9 values ​​are fed to the input (this is 0 or 1 depending on whether the cell is painted or not). And if the field is 3 by 3 stick vertical, then the neural network says that the stick is vertical well or horizontal.

Here is the link to the article: https://m.habr.com/ru/en/post/312450/

But the code itself:

static Random r; static void Main(string[] args) { //Входные данные double[,] inputData = new double[,] { {1,0,0,1,0,0,1,0,0}, {1,1,1,0,0,0,0,0,0}, {0,1,0,0,1,0,0,1,0}, {0,0,0,1,1,1,0,0,0}, {0,0,1,0,0,1,0,0,1}, {0,0,0,0,0,0,1,1,1} }; /*inputData = new double[,] { {0,1,1}, {0,0,1},{1,0,1},{0,0,0},{1,0,0},{0,1,0},{1,1,0},{1,1,1} };*/ //Идеальные значения double[] outputData = new double[] { 1, 0, 1, 0, 1, 0 }; //outputData = new double[] { 1, 1, 0, 0, 0, 0, 0, 1 }; //Значение момента double a = 0.8; //Скорость обучения double E = 0.8; //Все нейроны double[][,] allNeurons = new double[][,] { new double[10,1], new double[6,2], new double[4,2], new double[1,2] //new double[4, 1], new double[1, 2] }; //Все веса double[][,,] allWeights = new double[][,,] { new double[10,5,2], new double[6,3,2], new double[4,1,2] //new double[4,1,2] }; r = new Random(); //Инициализация весов в промежутке от -0.5 до 0.5 случайным образом for (int i = 0; i < allWeights.GetLength(0); i++) for (int j = 0; j < allWeights[i].GetLength(0); j++) for (int k = 0; k < allWeights[i].GetLength(1); k++) allWeights[i][j, k, 0] = r.NextDouble() - 0.5; double error = 0; for (int epoch = 0; epoch < 1000; epoch++) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(epoch); Console.ResetColor(); for (int stepTrain = 0; stepTrain < inputData.GetLength(0); stepTrain++) { //Инициализация входных нейронов for (int i = 0; i < allNeurons[0].GetLength(0) - 1; i++) allNeurons[0][i, 0] = inputData[stepTrain, i]; //Инициализация нейронов смещения for (int i = 0; i < allNeurons.GetLength(0) - 1; i++) allNeurons[i][allNeurons[i].GetLength(0) - 1, 0] = 1; //Прямое прохождение по всем слоям for (int i = 1; i < allNeurons.GetLength(0); i++) { int lastLayer = 1; if (i == allNeurons.GetLength(0) - 1) lastLayer = 0; for (int k = 0; k < allNeurons[i].GetLength(0) - lastLayer; k++) { for (int j = 0; j < allNeurons[i - 1].GetLength(0); j++) allNeurons[i][k, 0] += allWeights[i - 1][j, k, 0] * allNeurons[i - 1][j, 0]; allNeurons[i][k, 0] = Sigmoid(allNeurons[i][k, 0]); } } //Нахождение ошибки у выходных нейронов int index = allNeurons.GetLength(0) - 1; for (int i = 0; i < allNeurons[index].GetLength(0); i++) allNeurons[index][i, 1] = FixOutError(outputData, allNeurons[index][i, 0], stepTrain); //Нахождение ошибок для скрытых нейронов for (int i = allNeurons.GetLength(0) - 2; i >= 1; i--) { int lastLayer = 1; if (i + 1 == allNeurons.GetLength(0) - 1) lastLayer = 0; for (int j = 0; j < allNeurons[i].GetLength(0); j++) { for (int k = 0; k < allNeurons[i + 1].GetLength(0) - lastLayer; k++) allNeurons[i][j, 1] += allWeights[i][j, k, 0] * allNeurons[i + 1][k, 1]; allNeurons[i][j, 1] = allNeurons[i][j, 1] * (1 - allNeurons[i][j, 0]) * allNeurons[i][j, 0]; } } //Корректировка весов for (int i = 1; i < allNeurons.GetLength(0); i++) { int lastLayer = 1; if (i == allNeurons.GetLength(0) - 1) lastLayer = 0; for (int k = 0; k < allNeurons[i - 1].GetLength(0); k++) for (int j = 0; j < allNeurons[i].GetLength(0) - lastLayer; j++) { allWeights[i - 1][k, j, 1] = E * allNeurons[i - 1][k, 0] * allNeurons[i][j, 1] + a * allWeights[i - 1][k, j, 1]; allWeights[i - 1][k, j, 0] += allWeights[i - 1][k, j, 1]; } } error += Math.Pow(Math.Atan(outputData[stepTrain] - allNeurons[3][0, 1]), 2); Console.WriteLine(allNeurons[3][0, 0]); } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(error / outputData.Length); error = 0; Console.ResetColor(); //Thread.Sleep(300); } Console.ReadKey(); } static double FixOutError(double[] outputData, double outputValue, int index) => (outputData[index] - outputValue) * (1 - outputValue) * outputValue; static double Sigmoid(double outputData) => 1 / (1 + Math.Exp(-(outputData))); 

Addition:

I changed the search error to the string

 error += Math.Pow(Math.Atan(outputData[stepTrain] - allNeurons[3][0, 1]), 2); 

on line

 error += Math.Abs(outputData[stepTrain] - allNeurons[3][0, 0]); 

And at the end of an era, I simply divide error by the number of elements in an array of ideal values.

And I noticed that the first 200 eras, the error value is about 0.6 and almost does not change. After 200 epochs, the error begins to fall to 0.04 and then slowly decreases.

How to fix this error when 200 epoch error almost does not change.

Addition:

I changed the random generation of scales from -0.5 to 0.5 on s -1 to 0 and the neural network began to study for 100 epochs and not for 700 or 1400 as it was.

But I do not know if I did it right

  • @AK; ​​but it’s definitely not the code itself. And not in the size of the network. Because I followed the changes in the output values ​​of each epoch and the difference between the ideal response and the response of the neural network first increased and then at some point begins to produce the necessary values. - Pavel Erikov

1 answer 1

In general, after sitting and playing with the neural network.

1) Changed the number of hidden layers to 1 layer in which there are 5 neurons (1 displacement neuron)

2) Left the generation of weights -0.5 to 0.5. It did not play a special role. Only at the beginning, epoch 8-10 neuron a little tupit. (At least not 200 epochs as before)

3) If you stop learning at error <= 0.05, then it will take eras 80 (the minimum I received) if you need more precise answers (although they are already quite accurate) then at error <= 0.02 the neuron will learn 400 eras. Because approximately by 0.3-0.4 error decreases very slowly.

4) Hyper parameters changed as follows:

Moment value (a) = 0.9

The learning rate (E) was set to 1, but decided to set to 0.9 just somewhere I heard that it is better not to set hyper parameters to 1 (especially the moment value).

As a result, from 800-1400 epochs of training, I reduced to 80-400 (depending on the clarity of the answer you need).

Please correct if I made a mistake somewhere.

Just by neural networks I occupy a week of everything.