ЧАСТЬ ПЕРВАЯ. САМОЗАРОЖДАЮЩИЕСЯ И РАЗРУШАЮЩИЕСЯ СТРУКТУРЫ
Глава 3. Алгоритмы самозарождения знания (опыт построения практической системы)
На лоскуте пергамента;
Я брошен в огонь и корчусь!
3.1. Жизненная сила элемента
Ненавидя, кляня и любя:
За мученья, за гибель я знаю -
Все равно: принимаю тебя!
Для того чтобы придать рассуждениям вес и плоть, опустимся на землю, т.е. приведем конкретные примеры, которые легко могут быть реализованы с помощью ЭВМ, и посмотрим, каким образом система способна обучаться используя принцип самовозрождения.
Предположим, что наши нейроны способны к следующим элементарным действиям (ЭД): сложить ('+'), вычесть по модулю ("-"), умножить ("х"), разделить ("/"), ничего не делать (" "). Можно допустить и операции логарифмирования и возведения в степень это позволит расширить возможности системы по обучению. Нас же сейчас интересует сам подход, поэтому мы ограничимся только пятью названными операциями. Далее, выделим участок "пустого" пространства, на который будет оказываться воздействие по двум входам и одному выходу.
Предположим, что возникшее напряжение должно компенсироваться образованием нейронов в этом "пустом" пространстве.
Предположим, что элементов должно появиться ровно столько (не меньше и не больше), сколько достаточно для компенсации напряжения.
Предположим, что при рождении нейронов выбирается нейрон с тем элементарным действием, которое максимально способствует минимизации напряжения.
Например, пусть на первый вход подан сигнал силой три условные единицы (х=3), на второй 5 (у=5), требуемый результат 20 (z=20).
Тогда, перейдя на язык линейного программирования, поставленные условия можно записать следующим образом:
х,у входные значения;
z выходное значение;
d элементарное действие из множества [+, *,-,/,'' "].
При этом, считаем, что "ничего не делать" является наиболее предпочтительным из всех ЭД. Это действие подразумевает отсутствие нейрона и введено исключительно для полноты картины. Образно говоря, оно полностью соответствует восточной мудрости "никогда не делай лишнего шага, если можешь оставаться на месте, ибо тебе не ведомо не окажется ли этот твой шаг последним".
Требуется подобрать такое d, которое минимизировало бы выражение
Отсюда следует, что на первом этапе должен возникнуть нейрон с ЭД "умножить". Обозначим его через А1. Возникший нейрон максимально сгладит существующие противоречия, но до полной идиллии будет еще далеко. Напряжение ослабнет, но останется. В том случае, если оставшегося напряжения система не в состоянии будет "долго терпеть", то ей придется опять решать ту же самую задачу, задачу по устранению возникшего напряжения, но уже в новых условиях. Целевую функцию (3.1) придется переписать в виде (с учетом нового элемента):
Здесь d1,d2,d3,d4,d5 принимают значения из множества ЭД.
В нашем случае решение (3.2) приведет к следующим результатам (напоминаем, что операция является более предпочтительной):
d1 " " d2 " " d3 "+" d4 " " d5 " " |
Таким образом, итоговая схема формирования системы по принципу самозарождения будет выглядеть:
Процесс самозарождения повторяется до тех пор, пока система не откажется от рождения новых элементов, считая оставшееся внешнее напряжение вполне терпимым. Кроме того, с каждым разом задача выбора ЭД будет становиться все более и более трудоемкой. С одной стороны, все возрастающая трудоемкость выбора нейрона, а с другой понижение внешнего напряжения приведут к тому, что система успокоится и будет работать с той погрешностью, на которую окажется способной.
На этом можно считать обучение по принципу самозарождения законченным. Но теперь уже появляется возможность дальнейшего обучения по принципу саморазрушения, который был рассмотрен ранее. Здесь его можно уточнить, введя такой параметр как "жизненная сила" нейрона. Под жизненной силой нейрона будем понимать величину внешнего напряжения для компенсации которого он был рожден. В приведенном примере жизненная сила нейронов А1 и A2 соответствует 15 и 5 соответственно. Будем считать, что нейрон может быть уничтожен только тогда, когда внешнее напряжение, действующее на него, превосходит его собственную жизненную силу. Это значит, что для уничтожения первого нейрона из приведенного примера потребуется напряжение не менее 15, а для второго не менее 5 условных единиц.
Покажем возможность этого.
Пусть на вход системы, приведенной на рис. 1.5, поданы сигналы со значением 5 и 1, а на выход 12, т.е. х=5, у=1, z=12. В этой ситуации внешнее напряжение элемента А2 превосходит его жизненную силу, и он гибнет. Процесс гибели распространяется вглубь системы, но останавливается на нейроне А1, жизненная сила которого больше внешней энергии разрушения Возникает ситуация, благоприятная для рождения нового элемента взамен погибшего.
Минимизация целевой функции (3.2) приведет к рождению нейрона с ЭД "вычитание по модулю", что отражено в итоговой схеме на рис. 1.6.
В том случае, если внешние условия вернутся к первоначальным (x=3,y=5,z=20), то рожденный элемент опять будет уничтожен.
В приведенном примере силой, ответственной за уничтожение элементов, является значение целевой функции на новой порции обучающих данных. Понятно, что это только один из возможных подходов. Существуют и другие пути. Например, в качестве внешнего напряжения можно использовать функцию от неких средних значений по всей обучающей выборке.
Подобный принцип самообучения достаточно просто реализовать в виде компьютерной программы, размер которой, как и ее знания, будет динамически изменяться в зависимости от успешности адаптации к внешним условиям.
В предложенной схеме самообучения исключается такая ситуация, как паралич системы, и гарантируется на каждом этапе обучения та или иная точность предсказания. Эта точность определяется ранее рожденными нейронами.
Подобный подход не исключает методов, в основе которых лежит изменение весовых коэффициентов для входных связей нейрона, наоборот, изменение весовых коэффициентов является единственным методом настройки системы в том случае, когда рождение или гибель нового нейрона становятся невозможными. Например, в случае примера на рис. 1.6, система не способна давать ответ с той точностью, которую хотелось бы пользователю; возникновение новых нейронов уже невозможно в силу недостаточности внешнего напряжения; входные/выходные данные, достаточные для уничтожения нейрона А2, отсутствуют. Единственный способ повышения точности в этой ситуации подстройка весовых коэффициентов.
В дальнейшем, системы, функционирующие на базе приведенных принципов самовозрождения и разрушения, для краткости назовем СР-сетями.
В рассмотренном примере в качестве ЭД фигурировали арифметические операции, и именно для удобства работы с ними была подобрана соответствующая функция цели. Однако многообразие существующих задач никак не позволяет свести все существующие процессы самообучения исключительно к набору арифметических ЭД. Поэтому возникает резонный вопрос: "Позволяет ли подобный подход решать задачи, связанные с переработкой графических или символьных образов, и можно ли данный подход использовать для решения обычных, будничных задач, присущих человеку, как объекту, притягивающемуся целью ?"
Пусть в качестве входных сообщений выступают строки символов, например, Х = "abc", Y = "def". На выходе должна быть строка вида Zp = "bcda".
В качестве целевой функции определим функцию вида:
где
n = max (strlen(Zp), strlen(Z));
Zp(i) i символ желаемого результата;
Z(i) i символ получаемого результата;
strlen() функция определения длины строки;
g( Zp(i) Z(i)) = 1, если Zp(i) = Z(i),
g( Zp(i) Z(i)) = 1/2, если Zp(i) или Z(i) отсутствуют,
g( Zp(i) Z(i)) = 0, если Zp(i) и Z(i) присутствуют, но Zp(i) ? Z(i).
В качестве ЭД определим следующие:
X+Y склеивание строк;
X-Y результатом является строка из символов, присутствующих в X, но отсутствующих в Y;
Di(X) удаление первого символа строки X;
Dn(X) удаление последнего символа строки X.
Тогда результатом применения изложенного подхода станет автоматически сгенерированная следующая СР-сеть:
При желании полученная схема всегда может быть автоматически отображена в текст компьютерной программы на любом заданном языке программирования. Например, если в качестве языка программирования задан язык Си, то будет получен следующий текст:
sr_sxema(x,y,z) char x[ ] y[ ] z[ ]; { char x[80] /* рабочая переменная */ strcpy(x1,x); /* подготовка к работе */ х1[0]=0; strcat(х1,&х1[1]); /* D1 */ strcat(xl,y); /*xl+y*/ l=strlen(xl);x1[l]=0; /*Dn */ l=strlen(xl);x1[l]=0; /*Dn */ strcat(x1,x); /* x1+x */ 1=strlen(xl);xl[l]=0; /*Dn */ 1=strlen(xl);xl[l]=0; /*Dn */ strcpy(z,x1); /* возвращение управления */ return; } |
При желании приведенную программу можно подвергнуть автоматической оптимизации, которая приведет к введению циклов за счет поглощения одинаковых строк, например:
sr_sxema(x,y,z) char x[ ] y[ ] z[ ]; { int j; /* рабочая переменная */ char xl [80]; /* рабочая переменная */ strcpy(xl,x); /* подготовка к работе */ xl[0]=0;strcat(xl,&xl[l]); /*D1 */ strcat(xl,y); /*xl+y*/ for(j=0;j<2;j++) { 1=strlen(xl); xl[I]=0;} /* Dn */ strcat(xl,x); /*xl+x*/ for(j=0;j<2;j++) { 1=strlen(xl); xl[I]=0;} /* Dn */ strcpy(xl); /* возвращение управления */ return; } |
Ничто не мешает предложить аналогичный подход для моделирования ситуаций в биологическом, социальном и компьютерном мирах.
Анализируя ситуации социальной жизни людей, можно ввести ЭД типа:"бежать", "идти", "сидеть", "ехать", "говорить", "рождаться", "умирать", "повеситься" и т.п. Можно даже ограничить это множество, скорректировав его действиями "не убий", "не возжелай".
Для компьютерной программы в качестве ЭД могут выступать операции:
"писать", "читать" и т.д.
Понятно, что подобные СР-сети не являются панацеей от всех бед и не предлагают универсальной эвристики, пригодной для всех случаев жизни. Они могут стать лишь еще одним инструментом в руках художника, рисующего собственную жизнь.
Серьезным недостатком изложенного подхода является его "непробиваемая" целеустремленность стремление на каждом шаге увеличивать значение целевой функции. В приведенных примерах подобный путь привел к успеху, но это не означает, что так будет всегда; хотя, с другой стороны, целевой функцией, как, впрочем, и множеством ЭД всегда можно варьировать.
Пути улучшения ситуации видятся в направлении распараллеливания процессов. Например, если, решая выше приведенную задачу по обработке символьных строк, допустить параллельность в формировании СР-сети, т.е. наращивать сеть не только по единственному пути максимального увеличения значения целевой функции, а по нескольким направлениям, при этом разрешая использовать на каждом этапе все имеющиеся на данный момент результаты по всем возможным направлениям, то шансы найти выход в лабиринте решения задачи могут быть значительно повышены, см. следующий рисунок:
Обобщить сказанное и подвести итог представляется возможным в виде следующей схемы:
1. Элемент системы является простейшей неделимой частицей формальным нейроном.
2. Каждый нейрон способен к одному элементарному действию из некоторого наперед заданного множества, куда входит действие "ничего не делать". В общем случае в множество ЭД могут быть включены как арифметические операции, так и специальные алгоритмы, мемо-функции. Наличие ЭД "ничего не делать" равносильно отсутствию нейрона;
3. На начальном этапе система представляет собой множество нейронов с ЭД "ничего не делать", на каждый из которых может оказываться воздействие со стороны нескольких входов и одного выхода. Разницу между получаемым выходным значением и требуемым выходным значением назовем напряжением;
4. Считаем, что возникшее напряжение должно компенсироваться изменением у нейронов присущих им ЭД. Изменение ЭД "ничего не делать" на любое другое приводит к рождению нейрона для системы. Предположим, что нейронов должно возникать ровно столько, сколько необходимо для компенсации напряжения;
5. Считаем, что при рождении нейронов выбирается нейрон с тем ЭД, которое максимально способствует минимизации напряжения. Значение напряжения, которое компенсируется рожденным нейроном, назовем жизненной силой нейрона; считаем, что если на нейрон действует напряжение, превосходящее его собственную жизненную силу, то нейрон гибнет.
Таким образом, было показано, что в основе моделей, предназначенных для исследования серьезных качественных изменений работы системы, с успехом можно использовать саморазрушающиеся и самовозрождающиеся нейросети. Были даны основные определения, предложен механизм и приведены необходимые примеры, достаточные, на мой взгляд, для самостоятельной практической реализации изложенного подхода к различной областям жизни.
Новизна и эффективность данного подхода построения самообучающихся систем определяется применением для корректировки имеющегося знания не только коэффициентов ряда. с помощью которого апроксимируется неизвестная функция, а в первую очередь, операций между компонентами числового ряда с последующей корректировкой коэффициентов. Подобный подход позволяет значительно упростить схему работы самообучающейся системы в том случае, когда эта система используется для выделения в потоке данных аналитических зависимостей, построенных на базе таких действий, как сложение, вычитание, умножение и деление. При необходимости перечень действий всегда может быть расширен и дополнен не только известными математическими операциями типа логарифмирования и возведения в степень, но и алгоритмами, включающими реализованные программно мемо-функции, а также сам алгоритм самообучения. В этом случае речь может идти уже не столько о классическом программировании, сколько о написании сценария или задании сюжета произведения.
В этой связи интересно посмотреть на аналогии, прослеживающиеся в современных технологиях проектирования программного обеспечения для ЭВМ, и, в частности, на объектно-ориентированное программирование в среде Windows, в котором объекты рождаются, наследуя свойства, и умирают, возвращая память.
Цитируется по книге Э.Телло "Объектно-ориентированное программирование в среде Windows (М.: "Наука-Уайли", 1993):
"Объектно-ориентированное программирование это способ программирования, обеспечивающий модульность программ за счет разделения памяти на области, содержащие данные и процедуры. Области могут использоваться в качестве образцов, с которых по требованию могут делаться копии.
Весьма удобно рассматривать объекты как попытку создания активных данных. Смысл, вкладываемый в слова "объект представляет собой активные данные", основан на объектно-ориентированной парадигме выполнения операций, состоящей в посылке сообщений.
В посылаемых объекту сообщениях указывается, что мы хотим, чтобы он выполнил. Так, например, если мы хотим вывести на экране строку, то мы посылаем строке сообщение, чтобы она изобразила себя. В этом случае строка это уже не пассивный кусок текста, это активная единица, знающая, как правильно производить над собой различные действия".
Цитируется по книге П.Эйткена и С.Джерола "Visual C++ для мультимедиа (К,: "КОМИЗДАТ", 1996):
"Любое приложение Windows все время активно взаимодействует с операционной системой. Приложение и система, как молодые влюбленные, с огромной. частотой обмениваются множеством сообщений. Каждый раз, когда в системе Windows что-нибудь происходит, она посылает сообщение, на которое ваше приложение может отреагировать тем или иным образом. Часто такое сообщение вызывает целую лавину изменений!
...Когда вы определяете новый объект, в большинстве случаев вы просто порождаете его из уже существующего объекта с необходимыми вам свойствами. Новый объект сразу после создания уже имеет ("наследует") все свойства и возможности старого объекта. Таким образом, вы не тратите время на изобретение велосипеда. После создания нового объекта вы только дополняете его код новыми функциями, которые вам необходимы, -все старые функции и свойства у него уже присутствуют.
Любое действие пользователя во время выполнения Windows-программы вызывает генерацию сообщения.
Любой объект в программе для Windows обладает способностью реагировать на сообщения".