Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторна робота 1 ШІ.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
421.9 Кб
Скачать

Приклад 1.

Для прикладу напишемо невелику програму, яка буде розпізнавати прості зображення, скажімо, букви російської мови на растрових зображеннях. Домовимося, що в початковому стані наша система буде мати «порожню» пам'ять, тобто отакий новонароджений мозок, готовий до бою. Для того щоб змусити її коректно працювати, нам потрібно буде витратити час на навчання.

Отже, виходячи з поставленого завдання – кількість варіантів виходу дорівнює кількості букв в алфавіті -> 33. Далі, визначимося зі вхідними даними - будемо подавати на вхід бітовий масив 30х30 у вигляді растрового зображення:

У підсумку - потрібно створити 33 нейрона, у кожного з яких буде 30х30 = 900 входів.

Створимо клас для нашого нейрона:

type

  Neuron = class

name: string; / / Тут назву нейрона - буква, з якою він асоціюється

Input: array [0 .. 29,0 .. 29] of integer; / / Тут вхідний масив 30х30

output: integer; / / Сюди результат

memory: array [0 .. 29,0 .. 29] of integer; // Тут будемо зберігати досвід про попередній досвід

end;

Створимо масив нейронів, по кількості букв:

For i: = 0 to 32 do begin

neuro_web [i]: = Neuron.Create;

neuro_web [i]. output: = 0;

neuro_web [i]. name: = chr (Ord ('A') + i); / / Букви від А до Я

end;

«Пам'ять» нейромережі будемо зберігати їх у растрових зображеннях 30х30.

Ось наприклад, пам'ять нейрона «К» після прогону програми за різними шрифтами:

Як видно, самі насичені області відповідають пік селям, що найбільш часто зустрічаються.

Будемо завантажувати «пам'ять» у кожен нейрон при його створенні:

p: = TBitmap.Create;

p.LoadFromFile (ExtractFilePath (Application.ExeName) + '\ res\' + neuro_web [i]. name + '. bmp')

На початку роботи ненавченої програми, пам'ять кожного нейрона буде білою плямою 30х30.

Розпізнавати нейрон буде наступним чином:

- Беремо 1-й піксель

- Порівнюємо його з 1- м пікселем в пам'яті (там лежить значення 0 .. 255)

- Порівнюємо різницю з якимсь порогом

- Якщо різниця менше порога - вважаємо, що в даній точці буква схожа на лежачу в пам'яті, додаємо +1 до ваги нейрона.

І так по всіх пікселям.

В кінці розпізнавання у нас буде набір нейронів, кожен з яких вважає, що він прав на скількись відсотків. Ці відсотки - і є вага нейрона. Чим більше вага, тим імовірніше, що саме цей нейрон прав.

Тепер будемо згодовувати програмі довільне зображення і пробігати кожним нейроном по ньому:

for x: = 0 to 29 do

              for y: = 0 to 29 do begin

                  n: = neuro_web [i]. memory [x, y];

                  m: = neuro_web [i]. input [x, y];

                  if ((abs (m-n) <120)) then / / Поріг різниці кольору

                 if m <250 then neuro_web [i]. weight: = neuro_web [i]. weight +1; / / Крім того, не будемо враховувати білі пікселі, щоб не отримувати зайвих балів в терезах

                 if m <> 0 then begin

                   if m <250 then n: = round ((n + (n + m) / 2) / 2);

                       neuro_web [i]. memory [x, y]: = n; end

                 else if n <> 0 then

                   if m <250 then n: = round ((n + (n + m) / 2) / 2);

                neuro_web [i]. memory [x, y]: = n;

              end;

якого вага більша:

if neuro_web [i]. weight> max then begin

         max: = neuro_web [i]. weight;

         max_n: = i;

         end;

Саме по ось цьому значенню max_n, програма і скаже нам, що, на її думку, ми їй підсунули.

По початку це буде не завжди вірно, тому потрібно зробити алгоритм навчання.

s: = InputBox ('Enter the letter', 'програма вважає, що це буква' + neuro_web [max_n]. name, neuro_web [max_n]. name);

     for i: = 0 to 32 do begin / / Пробігаємо по нейронам

     if neuro_web [i]. name = s then begin / / В потрібному нейроні оновлюємо пам'ять

for x: = 0 to 29 do begin

    for y: = 0 to 29 do begin

     p.Canvas.Pixels [x, y]: = RGB (neuro_web [i]. memory [x, y], neuro_web [i]. memory [x, y], neuro_web [i]. memory [x, y]) ; / / Записуємо нове значення пікселя пам'яті

     end;

      end;

       p.SaveToFile (ExtractFilePath (Application.ExeName) + '\ res \' + neuro_web [i]. name + '. bmp');

Саме оновлення пам'яті будемо робити так: n: = round (n + (n + m) / 2);

Тобто якщо дана точка в пам'яті нейрона відсутня, але вчитель говорить, що вона є в цій букві - ми її запам'ятовуємо, але не повністю, а тільки наполовину. З подальшим навчанням, ступінь впливу даного уроку буде збільшуватися.

Ось декілька ітерацій для літери Г:

Почнемо навчання.

Відкриваємо зображення букв і терпляче вказуємо програмі на її помилки:

Через деякий час програма почне стабільно визначати навіть не знайомі їй раніше літери.

unit neuro;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ExtCtrls, StdCtrls, ExtDlgs, XPMan;

type

Neuron = class

name: string;

input: array[0..29,0..29] of integer;

output:integer;

weight:integer;

memory:array[0..29,0..29] of integer;

end;

type

TForm1 = class(TForm)

Image1: TImage;

ListBox1: TListBox;

Button1: TButton;

ListBox2: TListBox;

Button2: TButton;

Panel1: TPanel;

Panel2: TPanel;

Button3: TButton;

OpenPictureDialog1: TOpenPictureDialog;

XPManifest1: TXPManifest;

procedure FormCreate(Sender: TObject);

procedure ListBox1Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure Button1Click(Sender: TObject);

procedure ListBox1DblClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

neuro_web:array[0..32] of Neuron;

img:array[0..29,0..29] of integer;

implementation

{$R *.dfm}

procedure GetAllFiles( Path: string; Lb: TListBox );

var

sRec: TSearchRec;

isFound: boolean;

begin

isFound := FindFirst( Path + '\*.bmp', faAnyFile, sRec ) = 0;

while isFound do

begin

if ( sRec.Name <> '.' ) and ( sRec.Name <> '..' ) then

begin

if ( sRec.Attr and faDirectory ) = faDirectory then

GetAllFiles( Path + '\' + sRec.Name, Lb );

Lb.Items.Add( sRec.Name );

end;

Application.ProcessMessages;

isFound := FindNext( sRec ) = 0;

end;

FindClose( sRec );

end;

procedure start();

var x,y,i,l:integer;

p:TBitmap;

c:TColor;

begin

for i:=0 to 32 do begin

neuro_web[i].weight:=0;

neuro_web[i].output:=50;

neuro_web[i].name:=chr(Ord('А')+i);

p:=TBitmap.Create;

p.LoadFromFile(ExtractFilePath(Application.ExeName)+'\res\'+neuro_web[i].name+'.bmp');

for x:=0 to 29 do

for y:=0 to 29 do begin

c:=p.Canvas.Pixels[x,y];

l:=round((GetRValue(c)+GetGValue(c)+GetBValue(c))/3);

neuro_web[i].memory[x,y]:=l;

end;

end;

p.Free;

end;

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

procedure recognize();

var x,y,i,n,m,max,max_n:integer;

c:TColor;

p:TBitmap;

s:string;

r:Trect ;

begin

Form1.ListBox2.Clear;

max:=0;

max_n:=0;

r.Left:=0;

r.Right:=30;

r.Top:=0;

r.Bottom:=30;

for x:=0 to 29 do

for y:=0 to 29 do begin

c:=Form1.Image1.Canvas.Pixels[x,y];

i:=round((GetRValue(c)+GetGValue(c)+GetBValue(c))/3);

if i<100 then i:=0 else i:=255;

img[x,y]:=i ;

end;

for i:=0 to 32 do

for x:=0 to 29 do

for y:=0 to 29 do

neuro_web[i].input[x,y]:=img[x,y];

for i:=0 to 32 do begin

p:=TBitmap.Create;

p.Width:=30;

p.Height:=30;

for x:=0 to 29 do

for y:=0 to 29 do begin

n:=neuro_web[i].memory[x,y];

m:=neuro_web[i].input[x,y];

if ((abs(m-n)<120)) then

if m<250 then neuro_web[i].weight:=neuro_web[i].weight+1;

if m<>0 then begin

if m<250 then n:=round((n+(n+m)/2)/2);

neuro_web[i].memory[x,y]:=n; end

else if n<>0 then

if m<250 then n:=round((n+(n+m)/2)/2);

neuro_web[i].memory[x,y]:=n;

end;

Form1.ListBox2.Items.Add(chr(Ord('А')+i)+' = '+IntToStr(neuro_web[i].weight));

if neuro_web[i].weight>max then begin

max:=neuro_web[i].weight;

max_n:=i;

end;

end;

s:=InputBox('Enter the letter', 'Программа считает, что найдена буква '+neuro_web[max_n].name, neuro_web[max_n].name);

for i:=0 to 32 do begin

if neuro_web[i].name=s then begin

p.Canvas.TextOut(10,10,'asa');

p.Canvas.Brush.Color:=clWhite;

p.Canvas.Pen.Color:=clWhite;

p.Canvas.FillRect(r);

p.Canvas.Brush.Color:=clBlack;

p.Canvas.Pen.Color:=clBlack;

p.SaveToFile('aa.bmp');

for x:=0 to 29 do begin

for y:=0 to 29 do begin

p.Canvas.Pixels[x,y]:=RGB(neuro_web[i].memory[x,y],neuro_web[i].memory[x,y],neuro_web[i].memory[x,y]);

end;

end;

p.SaveToFile(ExtractFilePath(Application.ExeName)+'\res\'+neuro_web[i].name+'.bmp');

end;

end;

max:=0;

start();

end;

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

procedure TForm1.FormCreate(Sender: TObject);

var i:integer;

begin

GetAllFiles( ExtractFilePath(Application.ExeName)+'\img', listbox1 );

for i:=0 to 32 do

neuro_web[i]:=Neuron.Create;

start();

end;

procedure TForm1.ListBox1Click(Sender: TObject);

begin

Image1.Picture.LoadFromFile( ExtractFilePath(Application.ExeName)+'\res\'+ListBox1.Items.Strings[Listbox1.ItemIndex]);

end;

procedure TForm1.Button3Click(Sender: TObject);

begin

recognize();

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

If OpenPictureDialog1.Execute then

Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);

recognize();

end;

procedure TForm1.ListBox1DblClick(Sender: TObject);

begin

Button1.Click;

end;

end.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace WindowsFormsApplication1

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

public int[,] input = new int[3, 5];

Web NW1;

private void button1_Click(object sender, EventArgs e)

{

listBox1.Items.Clear();

button2.Enabled = true;

openFileDialog1.Title = "Укажите тестируемый файл";

openFileDialog1.ShowDialog();

pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);

Bitmap im = pictureBox1.Image as Bitmap;

for (var i = 0; i <= 5; i++) listBox1.Items.Add(" ");

for (var x = 0; x <= 2; x++)

{

for (var y = 0; y <= 4; y++)

{

// listBox1.Items.Add(Convert.ToString(im.GetPixel(x, y).R));

int n = (im.GetPixel(x, y).R);

if (n >= 250) n = 0;

else n = 1;

listBox1.Items[y] = listBox1.Items[y] + " " + Convert.ToString(n);

input[x, y] = n;

//if (n == 0) input[x, y] = 1;

}

}

recognize();

}

public void recognize()

{

NW1.mul_w();

NW1.Sum();

if (NW1.Rez()) listBox1.Items.Add(" - True, Sum = "+Convert.ToString(NW1.sum));

else listBox1.Items.Add( " - False, Sum = "+Convert.ToString(NW1.sum));

}

class Web

{

public int[,] mul;

public int[,] weight;

public int[,] input;

public int limit = 9;

public int sum ;

public Web(int sizex, int sizey,int[,] inP)

{

weight = new int[sizex, sizey];

mul = new int[sizex, sizey];

input = new int[sizex, sizey];

input = inP;

}

public void mul_w()

{

for (int x = 0; x <= 2; x++)

{

for (int y = 0; y <= 4; y++)

{

mul[x, y] = input[x,y]*weight[x,y];

}

}

}

public void Sum()

{

sum = 0;

for (int x = 0; x <= 2; x++)

{

for (int y = 0; y <= 4; y++)

{

sum += mul[x, y];

}

}

}

public bool Rez()

{

if (sum >= limit)

return true;

else return false;

}

public void incW(int[,] inP)

{

for (int x = 0; x <= 2; x++)

{

for (int y = 0; y <= 4; y++)

{

weight[x, y] += inP[x, y];

}

}

}

public void decW(int[,] inP)

{

for (int x = 0; x <= 2; x++)

{

for (int y = 0; y <= 4; y++)

{

weight[x, y] -= inP[x, y];

}

}

}

}

private void Form1_Load(object sender, EventArgs e)

{

NW1 = new Web(3, 5,input);

openFileDialog1.Title = "Укажите файл весов";

openFileDialog1.ShowDialog();

string s = openFileDialog1.FileName;

StreamReader sr = File.OpenText(s);

string line;

string[] s1;

int k = 0;

while ((line = sr.ReadLine()) != null)

{

s1 = line.Split(' ');

for (int i = 0; i < s1.Length; i++)

{

listBox1.Items.Add("");

if (k < 5)

{

NW1.weight[i, k] = Convert.ToInt32(s1[i]);

listBox1.Items[k] += Convert.ToString(NW1.weight[i, k]);

}

}

k++;

}

sr.Close();

}

private void button2_Click(object sender, EventArgs e)

{

button2.Enabled = false;

if (NW1.Rez() == false)

NW1.incW(input);

else NW1.decW(input);

//Запись

string s="";

string[] s1 = new string[5];

System.IO.File.Delete("w.txt");

FileStream FS = new FileStream("w.txt", FileMode.OpenOrCreate);

StreamWriter SW = new StreamWriter(FS);

for (int y = 0; y <= 4; y++)

{

s = Convert.ToString(NW1.weight[0, y]) + " " + Convert.ToString(NW1.weight[1, y]) + " " + Convert.ToString(NW1.weight[2, y]) ;

s1[y] = s;

SW.WriteLine(s);

}

SW.Close();

}

}

}