Простейшая нейросеть на Delphi

В этой статье описывается программирование простейшей нейросети, состоящая только из одного нейрона. Для большей конкретики возьмем определенную задачу и решим ее с помощью нейросети. Пусть нам необходимо разработать приложение, которое определяет, является ли заданный цвет оттенком зеленого. Конечно, такую простую задачу проще решить с помощью условий. Но цель заключается не в решении этой задачи, а в разборе нейросети. О том, что же такое нейросеть и где их применяют в Интернете написано немало. В этой же статье рассматривается программирование нейрона и его обучение на конкретном примере. В качестве нейрона, здесь определена функция, на который подается три числа, а результатом функции является значение типа boolean. То есть истина или ложь. Реализация функции довольно проста:

function uslovie(r,g,b:byte):boolean;
begin
  result:=r*k1+g*k2+b*k3>250;
end;

Здесь, k1, k2, k3 — так называемые веса для соответствующих входов. Процесс обучения нейрона как раз и заключается в подборе значений этих весов.

Для начала накинем необходимые компоненты на форму. Для отображения случайного цвета используется компонент Image1. Для отображения численных значений R,G,B сгенерированного цвета используются Edit1, Edit2 и Edit3. Кнопками «Правильно» и «Неправильно» производиться обучение нейросети. Label1 служит для отображения ответа нашего нейрона. А кнопка «Случайный цвет» генерирует новый случайный цвет.

Генерация случайного цвета реализована следующим образом:

procedure TForm1.Button3Click(Sender: TObject);
begin
  cvet:=Random(clWhite+1);//Генерация случайного цвета
  r:=cvet and 255;//Выделение RGB-каналов из 
    //сгенерированного цвета
  g:=(cvet div 256) and 255;
  b:=((cvet div 256) div 256) and 255;
  Image1.Canvas.Brush.Color:=cvet;//Прорисовка этого цвета
  Image1.Canvas.Rectangle(0,0,100,100);
  edit1.Text:=IntToStr(r);//Вывод численных значений R,G,B
  edit2.Text:=IntToStr(g);
  edit3.Text:=IntToStr(b);
  if uslovie(r,g,b) then begin//Вывод мнения нейрона 
    zc:=1;
    Label1.Caption:='Зеленый';
    Label1.Font.Color:=clGreen;
  end else begin
    zc:=0;
    Label1.Caption:='Не зеленый';
    Label1.Font.Color:=clRed;
  end;
end;

Если нейросеть правильно угадала цвет, и мы нажали на соответствующую кнопку, то происходит сохранение этого примера в список:

procedure TForm1.Button1Click(Sender: TObject);
var stv:String;
begin
  stv:=IntToStr(zc)+#9+IntToStr(r)+#9
   +IntToStr(g)+#9+IntToStr(b);
  tests.Add(stv);
end;

Если же сеть неправильно угадывает новый цвет, то необходимо подобрать коэффициенты так, чтоб она не только начала проходить последний тест правильно, но и все предыдущие сохраненные правильные варианты тоже продолжала правильно проходить:

procedure TForm1.Button2Click(Sender: TObject);
var f:boolean;
  i:integer;
  stv:string;
begin
  f:=false;
  repeat
    k1:=random(11)-5;//Берём случайные веса
    k2:=random(11)-5;
    k3:=random(11)-5;
    f:=true;
    for i:=0 to tests.Count-1 do
    Begin//Прогоняем случайные веса по всем тестам
      stv:=tests[i]+#9;
      zc:=StrToInt(copy(stv,1,pos(#9, stv)-1));
      delete(stv,1,pos(#9, stv));
      r:=StrToInt(copy(stv,1,pos(#9, stv)-1));
      delete(stv,1,pos(#9, stv));
      g:=StrToInt(copy(stv,1,pos(#9, stv)-1));
      delete(stv,1,pos(#9, stv));
      b:=StrToInt(copy(stv,1,pos(#9, stv)-1));
      if uslovie(r,g,b) xor (zc=1) then f:=false;
    end;
  until f;//Повторяем, пока все тесты не будут пройдены
end;

Для того чтобы после закрытия программы, наши труды по обучению нейросети не пропали, сохраняем их в текстовый файл:

procedure TForm1.FormClose(Sender: TObject; var Action:TCloseAction);
begin
  tests.SaveToFile('tests.txt');
end;

Ну и конечно же не забываем подгрузить прошлый опыт нейросети при повторном запуске программы:

procedure TForm1.FormCreate(Sender: TObject);
begin
  randomize;
  tests:=TStringList.Create;
  if FileExists('tests.txt') then tests.LoadFromFile('tests.txt');
end;

Ссылка на скачивание исходников