Skip to content

Repository files navigation

NeuralNetwork

Реализация классического алгоритма обратного распространения ошибки с помощью последовательного (стохастического) режима обучения для тренировки многослойного персептрона распознаванию рукописных цифр

Digit Recognition Canvas (песочница)

Digit Recognition Canvas (исходники)

Описание алгоритма (Хабр)

Form1.cs

privatevoidlearnButton_Click(objectsender,EventArgse){stringmyDocumentFolder=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);stringtrainingImagesPath=Path.Combine(myDocumentFolder,"train-images-idx3-ubyte");stringtrainingLabelsPath=Path.Combine(myDocumentFolder,"train-labels-idx1-ubyte");stringtestImagesPath=Path.Combine(myDocumentFolder,"t10k-images-idx3-ubyte");stringtestLabelsPath=Path.Combine(myDocumentFolder,"t10k-labels-idx1-ubyte");
#region Блок для инициализации нейросети с помощью весовых коэффициентов из файлов csv
//// Считываем весовые коэффициенты из файлов// List<Layer> hiddenLayers = InitializeHiddenLayersWeightsFromCSVFile(Path.Combine(myDocumentFolder, "adjustedHiddenLayerWeights_acc9572_16.csv"));// Layer outputLayer = InitializeOutputLayerWeightsFromCSVFile(Path.Combine(myDocumentFolder, "adjustedOutputLayerWeights_acc9572_16.csv"));////Инициализируем нейросеть//Network network = new Network(hiddenLayers, outputLayer);
#endregion
#region Блок для инициализация нейросети рандомными значениями и ее обучение
// Инициализируем нейросеть с помощью заданных параметровinthiddenLayersCount=1;// Задаем количество скрытых слоевint[]hiddenLayersDimensions=newint[hiddenLayersCount];// Массив для хранения количества нейронов на каждом скрытом слоеFunc<double,double>[]hiddenActivationFunctions=newFunc<double,double>[hiddenLayersCount];// Массив для хранения функций активации на каждом скрытом слоеhiddenLayersDimensions[0]=80;// У нас один скрытый слой на котором 80 нейроновhiddenActivationFunctions[0]=ActivationFunctions.SigmoidFunction;// И для всех нейронов этого скрытого слоя используется сигмоидальная функция активации// 784 входа - это размер массива полученного из изображения (28 * 28 пикселей)Networknetwork=newNetwork(784,10,ActivationFunctions.SigmoidFunction,hiddenLayersDimensions,hiddenActivationFunctions);network.Train(trainingImagesPath,trainingLabelsPath,0.2,16);// Запускаем обучение
#endregion
#region Тестируем нейросеть на тестовой выборке в 10 000 изображений
// Получаем тестовые изображенияIEnumerable<TestCase>testCases=FileReaderMNIST.LoadImagesAndLables(testLabelsPath,testImagesPath);intincorrectPredictionsCount=0;// счетчик неверно предсказанных результатовforeach(TestCasetestintestCases){List<double>functionSignal=ImageHelper.ConvertImageToFunctionSignal(test.Image);// Преобразуем изображение в вектор размерности 784 состоящий из нулей и единичекList<double>outputSignal=network.MakePropagateForward(functionSignal);// Получаем сигнал от нейросетиintpredictedDigit=outputSignal.IndexOf(outputSignal.Max());// Предсказанную цифру находим как индекс максимального элемента массива// Если нейросеть выдала некорректный ответif(test.Label!=predictedDigit){incorrectPredictionsCount++;// Получим это изображениеBitmapbitmap=ImageHelper.CreateBitmapFromMnistImage(test.Image);// И сохраним в папку IncorrectPredictionsbitmap.Save(Path.Combine(myDocumentFolder,"IncorrectPredictions",$"{incorrectPredictionsCount}_{test.Label}_{predictedDigit}.png"));}}doubleaccuracy=100.0-(incorrectPredictionsCount/100.0);// Вычисляем точность (%)
#endregion
// Записываем скорректированные весовые коэффициенты в файлыnetwork.WriteHiddenWeightsToCSVFile(Path.Combine(myDocumentFolder,$"adjustedHiddenLayerWeights_acc{accuracy.ToString().Replace(",",string.Empty)}.csv"));network.WriteOutputWeightsToCSVFile(Path.Combine(myDocumentFolder,$"adjustedOutputLayerWeights_acc{accuracy.ToString().Replace(",",string.Empty)}.csv"));// и в JSON файлыnetwork.WriteHiddenWeightsToJsonFile(Path.Combine(myDocumentFolder,$"adjustedHiddenLayerWeights_acc{accuracy.ToString().Replace(",",string.Empty)}.json"));network.WriteOutputWeightsToJsonFile(Path.Combine(myDocumentFolder,$"adjustedOutputLayerWeights_acc{accuracy.ToString().Replace(",",string.Empty)}.json"));}