Скачиваний:
0
Добавлен:
26.10.2025
Размер:
66.59 Кб
Скачать

Реализация персептрона:

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;

}

}

}