-
Notifications
You must be signed in to change notification settings - Fork 1
/
Form1.cs
137 lines (104 loc) · 8.08 KB
/
Form1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using MNIST.IO;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace NeuralNetwork
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void learnButton_Click(object sender, EventArgs e)
{
string myDocumentFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string trainingImagesPath = Path.Combine(myDocumentFolder, "train-images-idx3-ubyte");
string trainingLabelsPath = Path.Combine(myDocumentFolder, "train-labels-idx1-ubyte");
string testImagesPath = Path.Combine(myDocumentFolder, "t10k-images-idx3-ubyte");
string testLabelsPath = 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 Блок для инициализация нейросети рандомными значениями и ее обучение
// Инициализируем нейросеть с помощью заданных параметров
int hiddenLayersCount = 1; // Задаем количество скрытых слоев
int[] hiddenLayersDimensions = new int[hiddenLayersCount]; // Массив для хранения количества нейронов на каждом скрытом слое
Func<double, double>[] hiddenActivationFunctions = new Func<double, double>[hiddenLayersCount]; // Массив для хранения функций активации на каждом скрытом слое
hiddenLayersDimensions[0] = 80; // У нас один скрытый слой на котором 80 нейронов
hiddenActivationFunctions[0] = ActivationFunctions.SigmoidFunction; // И для всех нейронов этого скрытого слоя используется сигмоидальная функция активации
// 784 входа - это размер массива полученного из изображения (28 * 28 пикселей)
Network network = new Network(784, 10, ActivationFunctions.SigmoidFunction, hiddenLayersDimensions, hiddenActivationFunctions);
network.Train(trainingImagesPath, trainingLabelsPath, 0.2, 16); // Запускаем обучение
#endregion
#region Тестируем нейросеть на тестовой выборке в 10 000 изображений
// Получаем тестовые изображения
IEnumerable<TestCase> testCases = FileReaderMNIST.LoadImagesAndLables(testLabelsPath, testImagesPath);
int incorrectPredictionsCount = 0; // счетчик неверно предсказанных результатов
foreach (TestCase test in testCases)
{
List<double> functionSignal = ImageHelper.ConvertImageToFunctionSignal(test.Image); // Преобразуем изображение в вектор размерности 784 состоящий из нулей и единичек
List<double> outputSignal = network.MakePropagateForward(functionSignal); // Получаем сигнал от нейросети
int predictedDigit = outputSignal.IndexOf(outputSignal.Max()); // Предсказанную цифру находим как индекс максимального элемента массива
// Если нейросеть выдала некорректный ответ
if (test.Label != predictedDigit)
{
incorrectPredictionsCount++;
// Получим это изображение
Bitmap bitmap = ImageHelper.CreateBitmapFromMnistImage(test.Image);
// И сохраним в папку IncorrectPredictions
bitmap.Save(Path.Combine(myDocumentFolder, "IncorrectPredictions", $"{incorrectPredictionsCount}_{test.Label}_{predictedDigit}.png"));
}
}
double accuracy = 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"));
}
/// <summary>
/// Формирует выходной слой и инициализирует его весовые коэффициенты из CSV-файла
/// </summary>
/// <param name="fileName">путь к файлу с весовыми коэффициентами для выходного слоя</param>
/// <returns>Выходной слой</returns>
private Layer InitializeOutputLayerWeightsFromCSVFile(string fileName)
{
List<List<double>> outputLayerWeights = WeightsReader.ReadOutputLayerWeightsFromCSVFile(fileName);
// Формируем выходной слой
List<Neuron> outputNeurons = new List<Neuron>();
for (int i = 0; i < outputLayerWeights.Count; i++)
outputNeurons.Add(new Neuron(ActivationFunctions.SigmoidFunction, Weights: outputLayerWeights[i].Skip(1).ToList(), Bias: outputLayerWeights[i][0]));
return new Layer(outputNeurons);
}
/// <summary>
/// Формирует скрытые слои и инициализирует их весовые коэффициенты из CSV-файла
/// </summary>
/// <param name="fileName">путь к файлу с весовыми коэффициентами для скрытых слоев</param>
/// <returns>Список скрытых слоев</returns>
private List<Layer> InitializeHiddenLayersWeightsFromCSVFile(string fileName)
{
// Читаем весовые коэффициенты из файла
List<List<List<double>>> hiddenLayersWeights = WeightsReader.ReadHiddenLayersWeightsFromCSVFile(fileName);
// Формируем скрытые слои
List<Layer> hiddenLayers = new List<Layer>();
foreach (var layer in hiddenLayersWeights)
{
List<Neuron> neurons = new List<Neuron>();
foreach (var weights in layer)
neurons.Add(new Neuron(ActivationFunctions.SigmoidFunction, Weights: weights.Skip(1).ToList(), Bias: weights[0]));
hiddenLayers.Add(new Layer(neurons));
}
return hiddenLayers;
}
}
}