Логика мышления — spin-off

от автора

Представляю вашему вниманию цикл статей по нейросетям, концептуально близкий к серии статей Алексея Редозубова. Для понимания материала рекомендуется ознакомится со всем циклом его статей. По ссылке указана лишь одна статья из цикла, полезная для данного текста.

КДПВ
Описываемые модели нейросетей (далее НС) будут чуть более высокого уровня, чем у Алексея. Это позволяет упростить изложение и понимание процессов, происходящих в НС, что затем позволит переходить к более тонкой настройке более низкоуровневых НС. Также, работа над такими НС быстрее дает возможность их практического использования. В частности, я их применял для парсинга текстов, моделирования ходьбы мыши по лабиринту и интерпретации lisp-подобного языка, могут быть и множество других применений. К такому сложному поведению мы подойдем плавно к концу цикла.
Начнем с иллюстрации такого более высокоуровневого подхода. В статье Алексея про гиппокамп есть предложение: «гиппокамп формирует уникальные идентификаторы для воспоминаний». Начнем с простого кода, который будет производить эти действия — создавать уникальный идентификатор и подключать его к описываемым событиям. Код на С++. Исходники пока не выкладываю — без подготовительных объяснений в них все равно мало проку.

 NC & hippocampNewId = newNC(); 

Вместо отдельных нейронов, основная программная единица — нейронный кластер/колонка. Имя класса — NC (сокращение от NeuroCluster). Так как в НС создается большое количество нейрокластеров (в моих экспериментах — сотни тысяч), то operator new для выделения новых нейрокластеров использовать нежелательно — он работает медленно и имеет большие накладные расходы по памяти. Поэтому применяется функция newNC, которая использует пул нейрокластеров, и выделяет их оттуда. Вместо указателя, эта функция возвращает ссылку на NC, что делает код более удобным и безопасным.
Концептуально, этот код соответствует примерно такому подходу: в НС существует множество нейронных колонок, надо выделить очередную слабо используемую колонку, и она будет отвечать за новый идентификатор. Детализация способа, которым будет происходить такое выделение — более низкоуровневая задача к специалистам по гиппокампу. Она тоже интересна, у меня есть мысли, как её решать, но такая задача — слишком низкоуровневая, поэтому мы будем двигаться дальше.
Напишем цикл прохода по всем нейрокластерам:

 for(NC& nc: _listNC) { 	if(nc.isActive()) 		//тут надо как-то связать этот нейрокластер с hippocampNewId } 

Активный нейрокластер — это например любое текущее ощущение, признак с сенсорной коры, текущее действие, и так далее.
В модели Алексея, такая связь будет создана через настройку — кластер научится распознавать новую идентификационную волну. Для создания такой опосредованной связи нужно много вычислительных ресурсов — нужно много нейронов и связей (сотня-две нейронов на каждый нейрокластер), много вычислений, нужно моделировать прохождение идентификационной волны через всю кору, это прохождение займет много времени. Мы поступим проще — создадим программную связь напрямую:

 for(NC& nc: _listNC) { 	if(nc.isActive()) 		hippocampNewId.createLinkTo(nc); } 

После этого, новую метку гиппокампа надо увязать во времени с прошлыми воспоминаниями:

	hippocampNewId.createTimeLinkTo(_prevHippocampId);

И наконец для следующего цикла, проведем замену:

	_prevHippocampId = hippocampNewId;

Конечно, это пока псевдокод. Подразумевается, что это код в классе ИНС. Поэтому функция newNC — это функция-член класса НС. Если переменная начинается со знака подчеркивания, эта переменная — член класса (примерно как префикс m_, только не надо проговаривать букву m, что делает программирование более удобным).
Заслуга Алексея в том, что его открытие позволяет писать код типа createLinkTo. До его статей, можно было лишь догадываться, как быстро связать два воспоминания вместе. Ведь мозг не может мгновенно прорастить связь от аксона одного нейрона в другое полушарие, и так сотню раз каждую секунду. Технология Алексея же превращает весь мозг с гиппокампом в коммутатор, который может очень быстро создавать произвольные ассоциации. Лет 15 назад я принял существование такого механизма как данность, и работал дальше, надеясь, что его когда-нибудь откроют. Оставалось лишь писать код с некоторыми сомнениями — а насколько это все биологически правдоподобно? На существование такого механизма указывали разные факты, и вот наконец открылись подробности.
Хорошо, мы каким-то образом подсоединили самые активные текущие воспоминания и новую метку гиппокампа. Что нам это дает? Давайте сделаем так, чтобы при поступлении серии событий, похожей на ту, что была запомнена ранее, запомненные метки времени могли распознавать эти новые серии как нечто уже встречавшееся. Тогда можно будет делать разные вещи — например, запустить прогнозирование на основе опыта.
Для этого временно перейдем к другой задаче. Пусть сенсорная кора ИНС (искусственной НС) воспринимает буквы. Например, читает их из файла. Задача — создать нейронные цепочки, которые будут распознавать слово — например, слово «распознал». Причем распознавание это должно быть из нескольких компонент — из трех отдельных цепочек «рас», «поз», «нал».
Общий принцип решения в общем очевиден, и описан, например, в Hierarchical Temporal Memory Хокинса. А вот для картинки ниже нужно дать объяснения (картинку можно вытаскивать мышей в строку вкладок для открытия в новой вкладке):

1) в более старых моделях ИНС использовались не нейрокластеры, а нейроны (как здесь), но сейчас поднимать те старые исходники Нейронной Лаборатории 3 и заставлять их собираться слишком утомительно, поэтому буду иллюстрировать картинками, сгенерированными в последней версии Нейролаборатории 4. Поэтому хотя будут отображаться и абстракции нейрокластеров, я их буду называть нейронами — по контексту должно быть ясно, о чем речь.
2) Данное окно — вкладка «цепочки 2d» — создает удобную визуализацию части нейросети. Смотреть на нейросеть, как она выглядит на самой первой картинке в статье, неудобно. А это окно позволяет указать отдельный нейрокластер, проанализирует его связи, и показывает только те кластеры, которые достижимы по связям с выбранного. Оно выстраивает кластеры в ряд, дочерние признаки показывает ниже, временнЫе связи располагает по горизонтали. Теперь легче увидеть, что данная цепочка анализирует слово «распознал».
3) Видно, что разные кластеры имеют разные типы, разные типы окрашены в разный цвет. На картинке видны обычные (if) и сенсорные (sensor) нейрокластеры — они соответствуют сенсорной коре. Связи с сенсорного кластера на настоящий сенсор не моделируются за отсутствием необходимости. В данном случае отдельный тип кластера нужен лишь для того, чтобы облегчить отладку — например чтобы не думать, «а почему этот кластер не распознает никакие признаки, он что, бесполезен?». Нет, не бесполезен, он распознает ту букву, которая указана в комментарии.
4) Во всплывающей зеленой подсказке (по наведению мыши) показаны разные поля. В самом низу подсказки показана схема визуализации кластера. Разные модели ИНС могут визуализировать кластеры по разному, так как могут иметь очень разное наполнение (всякие численные переменные, количество внутренних нейронов и т. д.), и чтобы было ясно, что это за числа, картинку решил дать вместе с подсказкой.
5) Проанализируем распознавание первого слога «рас». В него входят сенсорные нейроны 6, 7 и 9, они распознаются в нужной последовательности благодаря нейронам 8 и 10. Если они сработают в другом порядке, или хотя бы с задержкой в один такт, то сигнал не достигнет нейрона 10.
6) По приведенной схеме можно подумать, что после того, как нейрон номер 10 с буквой «с» пошлет сигнал на нейрон номер 20 с другого слога, то сигнал придет слишком рано и успеет погаснуть прежде, чем будет распознан второй слог. Раньше для решения этой задачи я применял «нейроны задержки», которые пересылали сигнал, чтобы он пришел ровно в то время, как он понадобится другому нейрону. Сейчас я научился использовать правильную настройку связей, о чем будет описано в отдельной статье, поэтому нейроны задержки не нужны. Поэтому на картинке их нету.
7) Данная схема с нейронами, чтобы правильно распознать слово, шлет сигналы «вправо» и «вверх». Это соответствует течению времени и повышению уровня признака в иерархии. Но по всплывающей подсказке видно, что количество входящих и исходящих связей таковы, что связи скорее ведут «вниз». Это особенности работы нейрокластеров, не обращайте внимание, для схемы с нейронами связи идут вправо и вверх.
8) Для удобства, данное окно рисует по краям экрана номера строк и столбцов, а также смещения по времени, относительно срабатывания главного выделенного кластера — то есть того, чей идентификатор введен в поле для ввода и который подсвечен толстой рамкой справа вверху
9) Сложный формат времени (время создания нейрона типа 0:0.0-0) будет описан позже. Так как эта НС сгенерирована для иллюстрации, то время создания всех нейронов здесь одинаковое. В реальных схемах, это время будет показывать такт, в котором данная нейронная колонка настроилась на распознавание некоторого конкретного признака. Это время вызова функции newNC. Эту информацию затем можно использовать для отладки и прочего.
10) Такие цепочки, конечно же, могут в каждый такт времени запоминать более одного признака (у нейронов может быть сколько угодно связей). В данном случае у нейронов по одной связи на каждый такт времени, так как распознаются буквы. Были бы тут зрительные цепочки, картина была бы совсем другой, с очень большим количеством связей. В учебных целях проще работать с буквами. Даже при распознавании букв, в одну метку времени могут быть запомнены связи на множество кластеров — на букву, на окончание распознанного слога, на окончание распознанного слова, на параллельные мысли, сопутствующие обдумыванию текста. В этом значительное отличие нейрокластеров от lisp, где car/cdr содержат только по одному указателю. Такая семантика связей у lisp менее удобна для ИИ — так как отдельный cell нельзя рассматривать как полноценную ассоциацию, для этого нужно вытягивать из cell отдельный список признаков, который можно соединять очень разными способами. Поэтому попытки работы с ИИ на лиспе сразу дают очевидное решение — отдельный символ = отдельный cell, а это слишком низкий уровень для работы, ИИ на lisp создавать неудобно.
В следующей части будут рассмотрены некоторые алгоритмы для выделения условных рефлексов.

ссылка на оригинал статьи http://geektimes.ru/post/268652/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *