Новые форумы для: пользователей, администраторов, математиков и филологов.
3
1

Здравствуйте, товарищи!

Я решил поизучать да поэкспериментировать с нейронными сетями и столкнулся с проблемой. А дело вот в чем: пытаюсь сделать приложение, которое будет анализировать слова, пущенные на выход нейронной сети хопфилда, со словами, хранимыми в обучающей выборке. Как все происходит:

  1. Нейронная сеть Хопфилда обучается словам, которые хранятся в ini-файле (слова разбиваются на буквы, каждая буква представляется уникальной шестизначной последовательностью 1 и 0)
  2. Каждая буква слова, которое нужно распознать, разбивается на уникальную шестизначную последовательность 1 и 0
  3. Эти коды букв распознаваемого слова соединяются в кучу и подаются на выходы нейронной сети хопфилда
  4. дальше, в идеале, выходные данные должны анализироваться, после чего, нейро сеть должна выдать наиболее похожий результат из тех, что она "знает"
  5. Заранее обученная нейронная сеть обратного распространения просматривает, выданные нейро сетью хапфилда, коды символов и преобразует их в буквы

Однако что-то у меня с сетью хопфилда не так. Она выбирает одно, какое-то, слово из обучающей выборки и всегда подставляет его. Чувствую, что я где-то накосячил =/

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

собственно код

// Очистить сведения о примерах
NeuralNetHopf1.ResetPatterns;
// Устанавливаем размер вектора для Хопфилда
SetLength(zInputVector, 36);
// Создаем стринглист
Slova:= TStringList.Create;
// Создаем ини файл
IniFile1:= TIniFile.Create('G:\Neural\Project 1\HopfData.ini');
// Заносим слова в стринглист
IniFile1.ReadSection('слова', Slova);

// Пробегаем все слова
for i := 0 to Slova.Count - 1 do
 begin
  f:= 0; // обнуляем элемент вектора
  // Пробегаем каждую букву в слове
  for h := 1 to Length(Slova[i]) do //количество букв в слове
    begin
      // смотрим код буквы и заносим его в вектор
      for z := 0 to 5 do  // z - количество символов буквы. всего 6
        begin
          if Array1[ord(Slova[i][h]), z] = 1 then // в этом массиве хранятся коды букв. например: буква "а" с анси кодом 1072 имеет личный код 100000
            zInputVector[f]:= 1
          else
            zInputVector[f]:= -1;
          // Переходим на следущее поле вектора
          inc(f); // переходим на след. элемент вектора
        end;
    end;

  // Добавляем пример для выборки
  NeuralNetHopf1.AddPattern(zInputVector);

 end;

// Инициализируем веса
NeuralNetHopf1.InitWeights;

Memo.Lines.Clear;

// подаем сигналы на выходы сети хопфилда
z:= 0;
for I := 1 to Length(Edit1.Text) do
 for h := 0 to 5 do
  begin
    // в массиве коды символов
    if Array1[ord(Edit1.Text[i]), h] = 1 then
      NeuralNetHopf1.Layers[1].Neurons[z].Output := 1
    else
      NeuralNetHopf1.Layers[1].Neurons[z].Output := -1;
  end;

// Запуск процесса распознования
NeuralNetHopf1.Calc;

// получаем результат
for i := 0 to Length(zInputVector) - 1 do
 if NeuralNetHopf1.Layers[1].Neurons[i].Output = -1 then
   Memo.Lines.Add(FloatToStr(0))
 else
   Memo.Lines.Add(FloatToStr(1));

// устанавливаем размер вектора входа для сети обратного распространения
SetLength(xInputVector, NeuralNetExtended1.InputFieldCount);

// считаем, сколько у нас букв в слове (выпендрился)
simbols:= NeuralNetHopf1.Layers[1].NeuronCount / NeuralNetExtended1.InputNeuronCount;

// счетчик строк
h:= 0;
// Вывод результата
for z := 0 to StrToInt(FloatToStr(simbols)) - 1 do
  begin
    // заполняем вектор входа кодом буквы
    for I := 0 to 5 do
      begin
        xInputVector[i] := StrToInt(Memo.Lines[h]);
        inc(h);
      end;
    // Просчитываем
    NeuralNetExtended1.ComputeUnPrepData(xInputVector);
    // Выводим результат
    res:= FloatToStr(NeuralNetExtended1.Output[0]);

    // округляем полученный код буквы
    if (res[6] = '8') or (res[6] = '9') or (res[6] = '7') or (res[6] = '6')then
      res:= IntToStr(StrToInt(copy(res, 1, 4)) + 1)
    else
      res:= copy(res, 1, 4);

    // выводим букву в мемо
    Memo.Lines.Add(chr(strtoint(res)));
  end;

задан 10 Фев 9:59

tean%D0%AB%D0%A7's gravatar image

teanЫЧ
1.1k110
78% принятых

изменен 4 Апр 17:47

1

А какого типа у вас zInputVector? Если это класс или массив, то это является указателем, т.е. во время первого цикла, где добавляется пример для выборки при изменении значения zInputVector[f], меняются также значения тех, что уже добавлены.

Попробуйте после

  f:= 0; // обнуляем элемент вектора
  // Пробегаем каждую букву в слове

Выделить новую память для zInputVector. Если класс, то zInputVector:=Classname.Create, если другое то New, или getMem, смотря по ситуации.

Вроде так. Но не уверен, с нейро сетью Хопфилда не приходилось общяться.

ссылка

отвечен 10 Фев 10:47

Vahan%20Av's gravatar image

Vahan Av
6396

изменен 10 Фев 10:51

%D0%A5%D1%8D%D1%88%D0%9A%D0%BE%D0%B4's gravatar image

ХэшКод
5.4k427

TVectorInt = array of integer;

Но дело не в этом. Я даже пробовал делать массив из векторов и заполнять по отдельности каждый вектор.

В примерах, представленных вместе с библиотекой, структура такая же.

(10 Фев 11:07) teanЫЧ

Проблема точно в этом, обратите внимание на их пример Hopfield, где есть

// Инициализация сети значениями из таблицы
procedure TForm1.Init;
begin

end;

Там добавление идет отдельной функцией AddPattern(TableLETTERS.AsString); в которой только объявлен вектор xVector: TVectorInt; В этом случае для каждого вызова функции выделяется пямять для массива, а в вашем случае все в одном масиве происходит.

Кстати тоже самое с xInputVector[i];

(10 Фев 11:44) Vahan Av
  1. Сеть обратного распространения работает нормально, несмотря на то, что я использую один и тот же вектор.

  2. У меня в выборку поступает два слова (якуплю, продаю). Даже если я меняю порядок их занесения(якуплю, продаю / продаю, якуплю), все равно в итоге сеть возвращает в результате тоже самое слово (продаю). Значит - ввод нового кода слова в вектор не заменяет уже занесенный в выборку код.

  3. попробовал сделать так, как вы сказали - результат тот же.

Самое интересное, что даже, если я вообще не даю слово на распознание, то все равно сеть выкидывает мне слово "продаю".

(10 Фев 13:28) teanЫЧ

Сеть обратного распространения работает не так, как мне надо. Она выдает только результат, который точно совпадает с примером из выборки. А Хопфилдская сеть смотрит примерные совпадения и восстанавливает "картину".

Поэтому если использовать Хопфилдскую сеть, мне достаточно указать в выборке правильное написание слова. А есть использовать БП, то нужно будет указывать в выборке все слова, и все варианты неправильного написания слов + делать дополнительные обработки...

БП у меня используется, но только для того, чтобы определить буквы, а буквы я все забью в выборку.

(10 Фев 15:36) teanЫЧ

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

(10 Фев 15:40) teanЫЧ

На сайте basegroup.ru есть аналогичная программа, но, к сожалению, без исходников. Но я как понял, в этом случае надо несколько слоев сделать.

(13 Фев 8:58) Vahan Av
показано 5 из 6 показать еще 1
Ваш ответ

Если вы не нашли ответ, задайте вопрос.

Здравствуйте

ХэшКод - это совместно редактируемый форум вопросов и ответов для начинающих и опытных программистов.

Присоединяйтесь!

отмечен:

×814
×1
×1

задан
10 Фев 9:59

показан
449 раз

обновлен
4 Апр 17:47

Отслеживать вопрос

по почте:

Зарегистрировавшись, вы сможете подписаться на любые обновления

по RSS:

Ответы

Ответы и Комментарии