Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Отчет№1.doc
Скачиваний:
4
Добавлен:
11.07.2019
Размер:
194.56 Кб
Скачать

Федеральное агентство рф по образованию Государственное образовательное учреждение Высшего профессионального образования «Владимирский государственный университет»

Кафедра физики и прикладной математики

Лабораторная работа №1

«Модель однонейронной сети»

Выполнил: ст. гр. ПМИ-104 Андреев Д. В.

Принял: Горлов В.Н.

Владимир 2008

Цель работы:

Построить модель биологического нейрона, провести его обучение на основе дельта-правил для распознавания простого графического изображения, вводимого при работе с программой.

Постановка задачи:

Программа моделирует сеть, состоящую из одного слоя: входного, - который состоит из одного нейрона. Входы нейрона непосредственно связаны с точками изображения. Максимальный размер изображения – 100*100 точек (если задать число входов нейрона меньше 1000, то не все пиксели будут задействованы в качестве рецепторов).

Исходные данные для процесса обучения:

  • Число входов нейрона.

  • Значение порога.

  • Значение шага обучения.

  • Количество итераций.

Интерфейс: помимо окон, в которых можно изменять параметры, должны быть кнопки для выполнения следующих действий:

  • Сформировать нейронную сеть;

  • Выполнить заданное количество итераций обучения (“обучить”);

  • Запустить процесс распознавания изображения (“тестировать”);

  • Открыть форму для просмотра состояний скрытого слоя сети;

  • Стереть введенное изображение;

  • Получить информацию о программе.

Краткая теория:

Нейронные сети реализуют биологические процессы обработки информации и принятия человеком решений.

Из биологии: Нервная система человека состоит из нейронов, соединенных между собой нервными волокнами. Передача раздражений от кожи, ушей и глаз к мозгу, и процессы мышления происходят через передачу электрических импульсов между нейронами. Типы нервных волокон – дендриты (в большом количестве) для приема сигнала, и единственный аксон для передачи импульса.

Аксон контактирует с дендритами других нейронов через синапсы, которые влияют на силу импульса. Т.е., каждый синапс характеризуется определенным весом. Импульсы, поступившие к нейрону, суммируются. Если суммарный импульс превышает некоторый порог, нейрон формирует собственный импульс и передает его по аксону.

Математическая модель:

Текущее состояние нейрона определяется, как взвешенная сумма его входов: .

Выход нейрона есть функция его состояния: y = f(s).Часто это пороговая функция: ,

где p – параметр, называемый порогом.

Обучение НС:

    Обучить НС, в сущности, это процесс настройки весов связей нейрона. Пусть есть некоторая база данных с примерами. Предъявляя образы на вход нейронной сети, мы получаем некоторый ответ. Вычисляя разность между желаемым (целевым) ответом и реальным ответом сети, мы получаем ошибку сети. Если ошибка достаточно мало процесс обучения останавливают, если нет, то изменяют веса ряда нейронов. Существует множество алгоритмов обучения, например, алгоритм дельта-правил.

Алгоритм «дельта-правила»

  1. Задаем начальные малые значения весов.

  2. Рассчитываем текущий выход сети Y.

  3. Вычисляем d=T-Y, где T- целевое значение сети.

  4. Если d=0, то веса не меняем, иначе w(t)[i]=w(t-1)[i]+d*x[i]*h, где h- шаг обучения.

Тестирование НС:

После того, как нейронная сеть обучена, мы можем применять ее для решения задачи. Важнейшая особенность человеческого мозга состоит в том, что, однажды обучившись определенному процессу, он может верно действовать и в тех ситуациях, в которых он не бывал в процессе обучения. Веса обученной нейронной сети хранят достаточно много информации, поэтому можно рассчитывать на правильный ответ и для нового варианта изображения.

Выполнение работы:

Работа начинается с запуска формы. Появляется следующее окно:

Она включает следующие элементы:

  • Область отображения bmp-файла;

  • Список bmp-файлов. Затем необходимо выбрать в списке один из bmp-файлов

  • Нажав кнопку “Результат” появляется окно, которое отображает четность/нечетность цифры, представленной на экране;

  • Кнопки “Добавить” и “Очистить” управляют изображением на экране.

  • Кнопка “Выход” закрывает форму приложения.

Листинг программы:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace lab1

{

public partial class mainForm : Form

{

void BmpReadData(List<string> files, List<List<int>> all_x)

{

foreach (string file_name in files)

{

Bitmap bmp = new Bitmap(file_name);

List<int> x = new List<int>();

for (int i = 0; i < 100; i++)

for (int j = 0; j < 100; j++)

{

if (bmp.GetPixel(i, j).ToArgb() == Color.Black.ToArgb())

x.Add(1);

else

x.Add(0);

}

all_x.Add(x);

}

}

public mainForm()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

string[] files = { "0.bmp", "1.bmp", "2.bmp", "3.bmp", "4.bmp" };

res = new List<int>();

int i = 0;

foreach (string file_name in files)

{

listBoxPic.Items.Add(file_name);

res.Add(i % 2);

i++;

}

picBox.Image = Image.FromFile("no_image.bmp");

StatusBar.Text = "Для обучения нажмите \"обучить\"";

}

private void btnClear_Click(object sender, EventArgs e)

{

listBoxPic.Items.Clear();

res.Clear();

picBox.Image = Image.FromFile("no_image.bmp");

cmbBoxRes.SelectedIndex = -1;

}

//при выборе файлы отоборажаем картинку

private void listBoxPic_SelectedIndexChanged(object sender, EventArgs e)

{

toolStripProgressBar1.Value = 0;

if (listBoxPic.SelectedIndex == -1)

return;

picBox.Image = Image.FromFile(listBoxPic.Items[listBoxPic.SelectedIndex].ToString());

cmbBoxRes.SelectedIndex = res[listBoxPic.SelectedIndex];

}

private void cmbBoxRes_SelectedIndexChanged(object sender, EventArgs e)

{

if (listBoxPic.SelectedIndex == -1)

return;

res[listBoxPic.SelectedIndex] = cmbBoxRes.SelectedIndex;

}

//добавление файла в список

private void btnAdd_Click(object sender, EventArgs e)

{

openFileDialog.Filter = "bmp files (*.bmp)|*.bmp|All files (*.*)|*.*";

if (openFileDialog.ShowDialog() == DialogResult.OK)

{

string file_name = openFileDialog.FileName;

file_name = file_name.Substring(file_name.LastIndexOf("\\") + 1);

//проверяем расширение файла (необходимо чтобы было *.bmp)

if (!file_name.EndsWith("bmp"))

{

MessageBox.Show(

"Файл не является файлом *.bmp",

"Внимание",

MessageBoxButtons.OK,

MessageBoxIcon.Warning,

MessageBoxDefaultButton.Button2);

return;

}

//проверяем размеры изображения (необходимо 100*100)

Bitmap bmp = new Bitmap(file_name);

if (bmp.Width != 100 || bmp.Height != 100)

{

MessageBox.Show(

"Изображение должно быть размером 100х100",

"Внимание",

MessageBoxButtons.OK,

MessageBoxIcon.Warning,

MessageBoxDefaultButton.Button2);

return;

}

//проверяем, есть ли такой файл в списке

if (!listBoxPic.Items.Contains(file_name))

{

listBoxPic.Items.Add(file_name);

//по умолчанию новая цифра является четной

res.Add(0);

}

else

MessageBox.Show(

"Такой файл уже есть в списке",

"Внимание",

MessageBoxButtons.OK,

MessageBoxIcon.Warning,

MessageBoxDefaultButton.Button2);

}

}

//обучение нейронной сети

private void btnTraining_Click(object sender, EventArgs e)

{

toolStripProgressBar1.Value = 0;

//если ListBox пуст

if (listBoxPic.Items.Count == 0)

{

MessageBox.Show(

"Список файлов пуст",

"Внимание",

MessageBoxButtons.OK,

MessageBoxIcon.Warning,

MessageBoxDefaultButton.Button2);

return;

}

StatusBar.Text = "Обучение!";

Application.DoEvents();

//здесь храняться имена файлов

List<string> files = new List<string>();

for (int i = 0; i < listBoxPic.Items.Count; i++)

files.Add(listBoxPic.Items[i].ToString());

//здесь храняться все точки из изображений files

List<List<int>> all_x = new List<List<int>>();

BmpReadData(files, all_x);

//создаем нейрон

SingleNeiro n = new SingleNeiro(all_x[0].Count);

//проводим обучение

n.training(all_x, res, this);

//записываем весы в файл

n.WeightsToFile("w");

StatusBar.Text = "Обучение завершено!";

}

//определение четности цифры

private void btnRes_Click(object sender, EventArgs e)

{

//не выбран файл из списка

if (listBoxPic.SelectedIndex == -1)

{

MessageBox.Show(

"Не выбран файл для определения четности",

"Внимание",

MessageBoxButtons.OK,

MessageBoxIcon.Warning,

MessageBoxDefaultButton.Button2);

return;

}

SingleNeiro neuro = new SingleNeiro();

//проверка существования файла весов w или является ли он пустым

try

{

neuro.ReadWeigthsfromFile("w");

}

catch

{

MessageBox.Show(

"Файл весов w - не существует либо пуст\n Нужно обучить нейронную сеть",

"Внимание",

MessageBoxButtons.OK,

MessageBoxIcon.Warning,

MessageBoxDefaultButton.Button2);

return;

}

//читаем входы из изображения

neuro.ReadInputsFromBmpFile(listBoxPic.Items[listBoxPic.SelectedIndex].ToString());

txtRes.Text = "Цифра " + (neuro.Calculate() == 0 ? "четная" : "нечетная");

}

private void btnExit_Click(object sender, EventArgs e)

{

Application.Exit();

}

private void mnuItemDel_Click(object sender, EventArgs e)

{

listBoxPic.Items.Remove(listBoxPic.SelectedItem);

}

}

class SingleNeiro

{

private const double step = 0.8; //шаг обучения

private List<int> Inputs; //входы

private List<double> Weights; //веса

private double p = 3; //порог

public SingleNeiro()

{

Inputs = new List<int>();

Weights = new List<double>();

}

public SingleNeiro(int size)

{

Inputs = new List<int>();

Weights = new List<double>();

for (int i = 0; i < size; i++)

Weights.Add(0.5);

}

/// <summary>

/// рассчет четности цифры

/// </summary>

/// <returns></returns>

public int Calculate()

{

double sum = 0;

int idx = 0;

foreach (int bit in Inputs)

{

sum += bit * Weights[idx++];

}

return sum < p ? 0 : 1;

}

/// <summary>

/// изменяем весы пересчет весов

/// </summary>

/// <param name="popravka"></param>

public void ChangeWeight(int popravka)

{

for (int i = 0; i < Weights.Count; i++)

Weights[i] = Weights[i] + popravka * Inputs[i] * step;

}

/// <summary>

/// запись весов в файл

/// </summary>

/// <param name="name"></param>

public void WeightsToFile(string name)

{

StreamWriter fout = new StreamWriter(name);

foreach (double weight in Weights)

{

fout.WriteLine(weight);

}

fout.Close();

}

/// <summary>

/// функция для считывания весов из файла

/// </summary>

/// <param name="file_name"></param>

public void ReadWeigthsfromFile(string file_name)

{

StreamReader fin_w = new StreamReader(file_name);

string str = "";

while ((str = fin_w.ReadLine()) != null)

{

Weights.Add(double.Parse(str));

}

fin_w.Close();

}

/// <summary>

/// функция для считывания входов из графического изображения

/// </summary>

/// <param name="file_name"></param>

public void ReadInputsFromBmpFile(string file_name)

{

Bitmap bmp = new Bitmap(file_name);

for (int i = 0; i < 100; i++)

for (int j = 0; j < 100; j++)

{

if (bmp.GetPixel(i, j).ToArgb() == Color.Black.ToArgb())

Inputs.Add(1);

else

Inputs.Add(0);

}

}

/// <summary>

/// обучаем нейрон определять четность цифры

/// </summary>

/// <param name="all_x">образы цифр</param>

/// <param name="res">результаты четности для каждого из образов</param>

/// <param name="f1"></param>

public void training(List<List<int>> all_x, List<int> res,mainForm f1)

{

do

{

int idx = 0;

foreach (List<int> x in all_x)

{

//считываем входы

this.Inputs = x;

//определяем поправку, на которую изменяем весы

int offset = res[idx] - Calculate();

//до тех пор, пока не получим правильный результат

while (offset != 0)

{

if (f1.toolStripProgressBar1.Value + 5 > f1.toolStripProgressBar1.Maximum)

f1.toolStripProgressBar1.Maximum += 5;

f1.toolStripProgressBar1.Value += 5;

ChangeWeight(offset);

offset = res[idx] - Calculate();

}

idx++;

}

}

while (!TestTeaching(all_x, res));

f1.toolStripProgressBar1.Value = f1.toolStripProgressBar1.Maximum;

}

/// <summary>

/// проверка правильности четности цифры, выдаваемого нейронной сетью

/// </summary>

/// <param name="all_x"></param>

/// <param name="res"></param>

/// <returns></returns>

bool TestTeaching(List<List<int>> all_x, List<int> res)

{

int idx = 0;

foreach (List<int> x in all_x)

{

this.Inputs = x;

if (Calculate() != res[idx++])

return false;

}

return true;

}

}

}