1.2 Разработка схем алгоритмов
Для дальнейшей работы необходимо построить следующие алгоритмы: алгоритм работы программы в целом, и алгоритм обучения нейросети. Обобщенная схема алгоритма программы, распознающей 2 класса букв с помощью двухслойной нейросети, представлена на рисунке 2.
Распознавание
букв
Рисунок 2 – Обобщенная схема алгоритма программы, распознающей 2 класса букв с помощью двухслойной нейросети
Алгоритм обучения нейросети представлен на рисунке 3.
Рисунок 3 – Схема алгоритма обучения нейросети
2 Разработка программы
Текст программы, распознающей букву Е с помощью двухслойной нейросети, представлен на рисунке 4.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
namespace курсовой_титп_2
{
public partial class Form1 : Form
{
Random number = new Random();
Neyro nr;
public bool flag = false, flagp = false; //флаг создания нейросети
public Thread pp;
public Form1()
{
InitializeComponent();
}
// ///////////////////////////////////////////
// кнопка создать сеть
private void button1_Click(object sender, EventArgs e)
{
int neyr1, neyr2;
double k;
double skor;
flag = true;
if (textBox1.TextLength != 0)
{
neyr1 = Convert.ToInt32(textBox1.Text); //количество нейронов первого слоя
}
else
{
MessageBox.Show("Введите количество нейронов первого слоя");
return;
}
if (textBox2.TextLength != 0)
{
neyr2 = Convert.ToInt32(textBox2.Text); //количество нейронов второго слоя
}
else
{
MessageBox.Show("Введите количество нейронов второго слоя");
return; }
Рисунок 4 – Текст программы, распознающей букву Е с помощью двухслойной нейросети
if (textBox9.TextLength != 0)
{
k = Convert.ToDouble(textBox9.Text); //коэффицент сигмоида k
}
else
{
MessageBox.Show("Введите k");
return;
}
if (textBox11.TextLength != 0)
{
skor = Convert.ToDouble(textBox11.Text); //коэффицент скорости обучения
}
else
{
MessageBox.Show("Введите skor");
return;
}
nr = new Neyro(neyr1, neyr2, k, skor); //вызываем конструктор класса
nr.CreateNS();
//выводим резульат нейросети
textBox3.Clear();
for (int i = 0; i < neyr2; i++)
{
textBox3.AppendText(Convert.ToString(Math.Round(nr.rez[i], 3)) + " ");
}
}
////////////////////////////////////////////////////////////
//кнопка сброс
private void button2_Click(object sender, EventArgs e)
{
textBox1.Clear();
textBox2.Clear();
textBox3.Clear();
textBox9.Clear();
textBox11.Clear();
comboBox1.Text = "";
comboBox3.Text = "";
}
// //////////////////////////////////////
// кнопка обучение
private void button3_Click(object sender, EventArgs e)
{
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
pp = new Thread(Potok);
flagp = true;
pp.Start();
Рисунок 4 – Продожение
///////////////////////////////////////////////
//выводим результат
textBox3.Clear();
for (int i = 0; i < nr.neyr2; i++)
{
textBox3.AppendText(Convert.ToString(Math.Round(nr.rez[i], 3)) + " ");
}
}
private void Potok()
{
string file;
if (flag == false)
{
MessageBox.Show("Создайте сеть");
return;
}
if (comboBox1.Text != "")
{
file = "bmp/" + comboBox1.Text; //выбранный файл для обучения
}
else
{
MessageBox.Show("Выберите файл");
return;
}
nr.Obuchenie(file);
//коректировка весовых коэфицентов
int ii = 0;
while (true)
{
nr.Korekt(); //коректируем веса
nr.Rez(); //еще раз пересчитываем результат
//считаем ошибку
nr.err = 0;
for (int i = 0; i < nr.neyr2; i++)
{
nr.err = nr.err + (nr.rez[i] - nr.ogid[i]) * (nr.rez[i] - nr.ogid[i]);
}
nr.err = nr.err / 2;
//выводим ошибку
textBox4.Clear();
textBox4.AppendText(Convert.ToString(Math.Round(nr.err, 5)));
if (ii > 50 && nr.err < 0.0001)
break;
ii++;
}
flagp = false;
}
// ////////////////////////////////////////////////
//кнопка результат
private void button4_Click(object sender, EventArgs e)
{
string file;
Рисунок 4 – Продожение
int[] znach = new int[nr.neyr2];
int kl = 0;
int aa;
if (flag == false)
{
MessageBox.Show("Создайте сеть");
return;
}
for (int i = 0; i < nr.neyr2; i++)
{
znach[i] = 0;
}
if (comboBox3.Text != "")
{
file = "bmp/" + comboBox3.Text;
}
else
{
MessageBox.Show("Выберите файл тестовой выборки");
return;
}
byte[] b = File.ReadAllBytes(file); //читаем содержимое файла в переменную text
for (int i = 62; i < 190; i++)
{
aa = b[i];
for (int j = 0; j < 8; j++)
{
nr.vvod[((i - 62) * 8) + j] = (aa & 1); //создаем массив входных значений
aa = aa >> 1;
}
}
//считаем результат
nr.Rez();
//выводим резульат нейросети
textBox3.Clear();
for (int i = 0; i < nr.neyr2; i++)
{
textBox3.AppendText(Convert.ToString(Math.Round(nr.rez[i], 3)) + " ");
}
for (int i = 0; i < nr.neyr2; i++)
{
if (nr.rez[i] < 0.05)
znach[i] = 0;
if (nr.rez[i] > 0.95)
znach[i] = 1;
if (nr.rez[i] < 0.95 && nr.rez[i] > 0.05)
znach[i] = 2;
}
for (int i = 0; i < nr.neyr2; i++)
{
if (znach[i] == nr.ogid[i])
{ }
Рисунок 4 – Продожение
else goto m;
}
kl = 1;
m:
textBox3.Clear();
for (int i = 0; i < nr.neyr2; i++)
{
textBox3.AppendText(Convert.ToString(Math.Round(nr.rez[i], 3)) + " ");
}
//считаем ошибку
nr.err = 0;
for (int i = 0; i < nr.neyr2; i++)
{
nr.err = nr.err + (nr.rez[i] - nr.ogid[i]) * (nr.rez[i] - nr.ogid[i]);
}
nr.err = nr.err / 2;
//выводим ошибку
textBox4.Clear();
textBox4.AppendText(Convert.ToString(Math.Round(nr.err, 3)));
if (kl == 0)
{
textBox5.Clear();
textBox5.AppendText("Это не E");
}
if (kl == 1)
{
textBox5.Clear();
textBox5.AppendText("Это E");
}
}
////////////////////////////////////////
//кнопка выход
private void button8_Click(object sender, EventArgs e)
{
if (flagp && pp.IsAlive)
{
pp.Abort();
}
Application.Exit();
}
//рисование картинки выбраной в первом списке
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string file = "bmp/" + comboBox1.Text;
Bitmap bm = new Bitmap(file);
pictureBox1.Image=bm;
}
//рисование картинки выбраной во втором списке
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
string file = "bmp/" + comboBox3.Text;
Рисунок 4 – Продожение
Bitmap bm = new Bitmap(file);
pictureBox2.Image = bm;
}
//создание списка фалов из папки bmp при создании окна
private void Form1_Load(object sender, EventArgs e)
{
DirectoryInfo di = new DirectoryInfo("bmp");
FileInfo[] a = di.GetFiles();
for (int i = 0; i < a.Length; i++)
{
comboBox3.Items.Add(a[i].Name);
}
for (int i = 0; i < a.Length; i++)
{
comboBox1.Items.Add(a[i].Name);
}
}
}
//класс, который работает с нейросетью
public class Neyro : Form1
{
public double[] prom;
public double[] vvod;
public double[,] w1, w2;
public double[] rez;
public int count1=0, count2=0;
public int neyr1, neyr2;
public int[] ogid;
public double err = 0;
public double k, skor;
public int kol_vvod = 1024;
//конструктор. при создании объекта класса задаем параметры матриц
public Neyro(int neyr1, int neyr2, double k, double skor)
{
this.neyr1 = neyr1;
this.neyr2 = neyr2;
this.k = k;
this.skor = skor;
this.ogid = new int[neyr2];
this.w1 = new double[kol_vvod, neyr1];
this.w2 = new double[neyr1, neyr2];
this.prom = new double[neyr1];
this.vvod = new double[kol_vvod];
this.rez = new double[neyr2];
Random number = new Random();
//Заполнение матрицы весовых коэффицентов w1
for (int q = 0; q < kol_vvod; q++)
{
for (int p = 0; p < neyr1; p++)
{
w1[q, p] = number.NextDouble()-0.5;
}
}
Рисунок 4 – Продожение
//Заполнение матрицы весовых коэффицентов w2
for (int q = 0; q < neyr1; q++)
{
for (int p = 0; p < neyr2; p++)
{
w2[q, p] = number.NextDouble()-0.5;
}
}
ogid[0] = 0;
for (int i = 1; i < neyr2; i++)
{
if (ogid[i - 1] == 0)
ogid[i] = 1;
else ogid[i] = 0;
}
}
//код, который будет выполняться в потоке
public void Potok1(object _Data)
{
double sum1 = 0;
for (int n = 0; n < (neyr1 / 2); n++)
{
for (int i = 0; i < kol_vvod; i++)
{
sum1 = sum1 + (vvod[i] * w1[i, n]);
}
prom[n] = Math.Round(1 / (1 + Math.Exp(-sum1*k)), 3);
}
count1++;
}
public void Potok2(object _Data)
{
double sum2 = 0;
for (int n = (neyr1 / 2); n < neyr1; n++)
{
for (int i = 0; i < kol_vvod; i++)
{
sum2 = sum2 + (vvod[i] * w1[i, n]);
}
prom[n] = 1 / (1 + Math.Exp(-sum2*k));
}
count1++;
}
public void Potok3(object _Data)
{
double sum1 = 0;
for (int n = 0; n < (neyr2 / 2); n++)
{
for (int i = 0; i < neyr1; i++)
{
sum1 = sum1 + (prom[i] * w2[i, n]);
}
Рисунок 4 – Продожение
rez[n] = 1 / (1 + Math.Exp(-sum1*k));
}
count2++;
}
public void Potok4(object _Data)
{
double sum2 = 0;
for (int n = (neyr2 / 2); n < neyr2; n++)
{
for (int i = 0; i < neyr1; i++)
{
sum2 = sum2 + (prom[i] * w2[i, n]);
}
rez[n] = 1 / (1 + Math.Exp(-sum2*k));
}
count2++;
}
public void Korekt() //коректировка весов матриц
{
double[] beta2 = new double[neyr2];
double[] beta1 = new double[neyr1];
double summa = 0;
//ощибка выходного слоя
for (int q = 0; q < neyr2; q++)
{
beta2[q] = (ogid[q] - rez[q]) * (1 - rez[q]) * rez[q];
}
//коректировка весов матрицы w2
for (int p = 0; p < neyr1; p++)
{
for (int q = 0; q < neyr2; q++)
{
w2[p, q] = (w2[p, q] + skor * beta2[q] * prom[p]);
}
}
//ошибка промежуточного слоя
summa = 0;
for (int q = 0; q < neyr1; q++)
{
for (int k = 0; k < neyr2; k++)
{
summa = summa + beta2[k] * w2[q, k];
}
beta1[q] = (1 - prom[q]) * prom[q] * summa;
summa = 0;
}
//коректировка весов матрицы w1
for (int p = 0; p < kol_vvod; p++)
{
for (int q = 0; q < neyr1; q++)
{
w1[p, q] = (w1[p, q] + skor * beta1[q] * vvod[p]);
}
Рисунок 4 – Продожение
}
}
public void Rez()
{
//пересчитываем результат
Thread th_11 = new Thread(Potok1);
Thread th_22 = new Thread(Potok2);
th_11.Start("11");
th_22.Start("22");
while (count1 != 2) { }
count1 = 0;
Thread th_33 = new Thread(Potok3);
Thread th_44 = new Thread(Potok4);
th_33.Start("33");
th_44.Start("44");
while (count2 != 2) { }
count2 = 0;
}
public void CreateNS()
{
int aa;
byte[] b = File.ReadAllBytes("bmp/1.bmp"); //читаем содержимое файла в переменную text
for (int i = 62; i < 190; i++)
{
aa = b[i];
for (int j = 0; j < 8; j++)
{
vvod[((i - 62) * 8) + j] = (aa & 1); //создаем массив входных значений
aa = aa >> 1;
}
}
//считаем результат
Rez();
}
public void Obuchenie(string file)
{
int aa;
byte[] b = File.ReadAllBytes(file); //читаем содержимое файла в переменную text
for (int i = 62; i < 190; i++)
{
aa = b[i];
for (int j = 0; j < 8; j++)
{
vvod[((i - 62) * 8) + j] = (aa & 1);
aa = aa >> 1;
Рисунок 4 – Продожение
}
}
Rez(); //пересчитываем результат
/*//коректировка весовых коэфицентов
int ii = 0;
while (true)
{
Korekt(); //коректируем веса
Rez(); //еще раз пересчитываем результат
//считаем ошибку
err = 0;
for (int i = 0; i < neyr2; i++)
{
err = err + (rez[i] - ogid[i]) * (rez[i] - ogid[i]);
}
err = err / 2;
if (ii > 50 && err < 0.001)
break;
ii++;
}*/
}
}
}
Рисунок 4 – Продожение