- •Реализация персептрона:
- •2.1. Точка входа в программу Program.Cs
- •2.2. Входные данные InputData.Cs
- •2.3. Реализация персептрона по методу Хебба Perceptron.Cs
- •2.4 Вывод информации OutputInformation.Cs
- •Описание
- •1. Точка входа – Program.Cs
- •2. Входные данные – InputData.Cs
- •3. Реализация персептрона – Perceptron.Cs
- •4. Вывод информации – OutputInformation.Cs
- •Взаимосвязь скриптов
- •Реализация генетического алгоритма:
- •1) Скрипт Program.Cs
- •2) Скрипт Population.Cs
- •3) Скрипт Individual.Cs
- •4) Скрипт Gen.Cs
- •5) Скрипт EvolutionManager.Cs
- •6) Скрипт Chromosome.Cs
- •Описание
- •Взаимосвязь между скриптами
- •Нейроэволюционный алгоритм:
- •1) Скрипт Program.Cs
- •2) Скрипт gaEvolutionManager
- •3) Скрипт TrainingSample.Cs
- •4) Скрипт OutputInformation.Cs
- •5) Скрипт InputData.Cs
- •6) Скрипт gaPerceptronIndividual.Cs
- •Описание
- •Общая схема работы и взаимосвязь модулей
- •Тестирование и демонстрация:
Реализация персептрона:
2.1. Точка входа в программу Program.Cs
using System;
using System.Collections.Generic;
namespace PerceptronSymbols
{
class Program
{
static void Main(string[] args)
{
// Массив чисел тренировок (эпох)
int[] trainingEpochsArray = new int[] { 5, 10, 50, 100, 1000, 10000, 100000 };
var researchResults = new List<(int trainingEpochs, double idealError, double noiseError, double mixedError)>();
Console.WriteLine("=== Исследование работы персептрона ===");
// Для каждого количества эпох обучения запускаем эксперимент 10 раз и усредняем результаты
foreach (int epochs in trainingEpochsArray)
{
double sumIdeal = 0, sumNoise = 0, sumMixed = 0;
int runs = 10;
for (int i = 0; i < runs; i++)
{
var result = RunExperiment(epochs);
sumIdeal += result.idealError;
sumNoise += result.noiseError;
sumMixed += result.mixedError;
}
double avgIdeal = sumIdeal / runs;
double avgNoise = sumNoise / runs;
double avgMixed = sumMixed / runs;
researchResults.Add((epochs, avgIdeal, avgNoise, avgMixed));
Console.WriteLine($"Результаты для {epochs} тренировок (среднее по {runs} запусков):");
Console.WriteLine($" Идеальные изображения: {avgIdeal:F6}% ложных срабатываний");
Console.WriteLine($" Два зашумленных изображения: {avgNoise:F6}% ложных срабатываний");
Console.WriteLine($" Идеальное + два зашумленных: {avgMixed:F6}% ложных срабатываний");
Console.WriteLine("Нажмите Enter для продолжения исследования...");
Console.ReadLine();
}
PrintResearchTable(researchResults);
// Обучение итоговой модели для демонстрации распознавания символов
Console.WriteLine("\n=== Демонстрация распознавания символов ===");
List<TrainingSample> idealSamples = InputData.GetSymbolSamples();
List<TrainingSample> trainingSet = new List<TrainingSample>();
trainingSet.AddRange(idealSamples);
// Добавляем по два шумовых примера на каждый символ
for (int i = 0; i < idealSamples.Count * 2; i++)
{
trainingSet.Add(InputData.GenerateNoiseSample());
}
List<Perceptron> perceptrons = new List<Perceptron>();
foreach (var sample in idealSamples)
{
if (!perceptrons.Exists(p => p.Symbol == sample.Label))
perceptrons.Add(new Perceptron(sample.Label, 25));
}
int finalTrainingEpochs = 10000;
for (int iter = 0; iter < finalTrainingEpochs; iter++)
{
foreach (var sample in trainingSet)
{
foreach (var p in perceptrons)
{
int target = (sample.Label == p.Symbol) ? 1 : 0;
p.Train(sample.Input, target);
}
}
}
Console.WriteLine("Итоговые весовые матрицы после обучения итоговой модели:");
foreach (var p in perceptrons)
{
OutputInformation.PrintWeights(p);
}
// Демонстрация: для каждого символа проводится тест с идеальным и двумя зашумленными изображениями
foreach (var ideal in idealSamples)
{
Console.WriteLine($"\n--- Тест для символа {ideal.Label} ---");
// Идеальное изображение
Console.WriteLine("Введите ИДЕАЛЬНОЕ изображение (5 строк по 5 чисел, разделённых пробелами или запятыми):");
int[] userIdeal = InputData.ReadUserInput();
string recognizedIdeal = RecognizeSymbol(userIdeal, perceptrons);
OutputInformation.PrintTestResult(userIdeal, GetPerceptronBySymbol(recognizedIdeal, perceptrons), recognizedIdeal);
// Два зашумлённых варианта
for (int i = 1; i <= 2; i++)
{
Console.WriteLine($"Введите ЗАШУМЛЁННОЕ изображение вариант {i} (5 строк по 5 чисел):");
int[] userNoisy = InputData.ReadUserInput();
string recognizedNoisy = RecognizeSymbol(userNoisy, perceptrons);
OutputInformation.PrintTestResult(userNoisy, GetPerceptronBySymbol(recognizedNoisy, perceptrons), recognizedNoisy);
}
}
Console.WriteLine("Нажмите любую клавишу для завершения...");
Console.ReadKey();
}
// Метод для проведения эксперимента с заданным числом эпох обучения.
// Возвращает процент ошибок (ложноположительных срабатываний) для трёх тестовых наборов.
static (double idealError, double noiseError, double mixedError) RunExperiment(int trainingEpochs)
{
List<TrainingSample> idealSamples = InputData.GetSymbolSamples();
List<TrainingSample> trainingSet = new List<TrainingSample>();
trainingSet.AddRange(idealSamples);
// Добавляем по два шумовых примера на каждый символ
for (int i = 0; i < idealSamples.Count * 2; i++)
{
trainingSet.Add(InputData.GenerateNoiseSample());
}
// Инициализируем персептроны для каждого символа
List<Perceptron> perceptrons = new List<Perceptron>();
foreach (var sample in idealSamples)
{
if (!perceptrons.Exists(p => p.Symbol == sample.Label))
perceptrons.Add(new Perceptron(sample.Label, 25));
}
// Обучение
for (int iter = 0; iter < trainingEpochs; iter++)
{
foreach (var sample in trainingSet)
{
foreach (var p in perceptrons)
{
int target = (sample.Label == p.Symbol) ? 1 : 0;
p.Train(sample.Input, target);
}
}
}
// Тест 1: Идеальные изображения
double idealError = TestPerceptrons(idealSamples, perceptrons);
// Тест 2: Два шумовых изображения на каждый символ
List<TrainingSample> noiseSamples = new List<TrainingSample>();
for (int i = 0; i < idealSamples.Count * 2; i++)
{
noiseSamples.Add(InputData.GenerateNoiseSample());
}
double noiseError = TestPerceptrons(noiseSamples, perceptrons);
// Тест 3: Для каждого символа одно идеальное + два шумовых
List<TrainingSample> mixedSamples = new List<TrainingSample>();
foreach (var sample in idealSamples)
{
mixedSamples.Add(sample);
mixedSamples.Add(InputData.GenerateNoiseSample());
mixedSamples.Add(InputData.GenerateNoiseSample());
}
double mixedError = TestPerceptrons(mixedSamples, perceptrons);
// Вывод весовых матриц и результатов тестирования
Console.WriteLine($"\nВесовые матрицы после обучения (эпох: {trainingEpochs}):");
foreach (var p in perceptrons)
{
OutputInformation.PrintWeights(p);
}
Console.WriteLine($"Результаты тестирования при {trainingEpochs} тренировках:");
Console.WriteLine($" Идеальные изображения: {idealError:F6}% ложных срабатываний");
Console.WriteLine($" Два зашумленных изображения: {noiseError:F6}% ложных срабатываний");
Console.WriteLine($" Идеальное + два зашумленных: {mixedError:F6}% ложных срабатываний");
return (idealError, noiseError, mixedError);
}
/* Метод тестирования персептронов:
для каждого образца проверяется, соответствует ли результат ожиданиям.
Если образец – идеальный, ожидается, что сработает ровно один персептрон с соответствующим символом.
Если образец шумовой (Label == "None"), ожидается, что ни один персептрон не сработает.*/
static double TestPerceptrons(List<TrainingSample> testSamples, List<Perceptron> perceptrons)
{
int errorCount = 0;
foreach (var sample in testSamples)
{
List<string> firedSymbols = new List<string>();
foreach (var p in perceptrons)
{
if (p.Predict(sample.Input) == 1)
firedSymbols.Add(p.Symbol);
}
if (sample.Label == "None")
{
if (firedSymbols.Count > 0)
errorCount++;
}
else
{
if (firedSymbols.Count != 1 || firedSymbols[0] != sample.Label)
errorCount++;
}
}
return (double)errorCount / testSamples.Count * 100.0;
}
// Вывод таблицы результатов исследования.
static void PrintResearchTable(List<(int trainingEpochs, double idealError, double noiseError, double mixedError)> results)
{
Console.WriteLine("\n---------------------------------------------------------");
Console.WriteLine("Число тренировок | Идеальные (%) | 2 зашумленных (%) | Идеальное + 2 зашумленных (%)");
foreach (var r in results)
{
Console.WriteLine($"{r.trainingEpochs,16} | {r.idealError,13:F6} | {r.noiseError,16:F6} | {r.mixedError,27:F6}");
}
Console.WriteLine("---------------------------------------------------------\n");
}
/* Распознавание символа по введённой матрице с использованием всех персептронов.
Если срабатывает ровно один персептрон, возвращается его символ, иначе – "None".*/
static string RecognizeSymbol(int[] input, List<Perceptron> perceptrons)
{
List<string> firedSymbols = new List<string>();
foreach (var p in perceptrons)
{
if (p.Predict(input) == 1)
firedSymbols.Add(p.Symbol);
}
return (firedSymbols.Count == 1) ? firedSymbols[0] : "None";
}
// Поиск персептрона по символу (если распознано "None" – возвращается null).
static Perceptron GetPerceptronBySymbol(string symbol, List<Perceptron> perceptrons)
{
foreach (var p in perceptrons)
{
if (p.Symbol == symbol)
return p;
}
return null;
}
}
}
