Posts Tagged ‘NL UI’

Закон нейрокода

Четверг, Сентябрь 2nd, 2010

(По аналогии с законом Мура)
Каждые полтора года, скорость написания нейрокода нейрокодом увеличивается вдвое. Закон наблюдается с 2003го года. Ускорение было с связи:
* с лучшим изучением С++
* углублением опыта в MFC – основной библиотеке GUI под виндовс со времен 90х годов
* (трехкратное ускорение) переходом с MFC на Qt и повышением опыта в Qt – лучшей библиотеке GUI для виндовс 2000х годов
* постоянным развитием интерфейса Нейролаборатории, из-за чего отладка нейросетей постоянно ускорялась
* развитием архитектуры Нейролаборатории: переходу к шаблонным классам, использования метаданных о полях нейронов и связей, указателей на функции обработки нейронов и т. д.
* развитием теории ИНС: универсализация нейронных цепочек, переход к раздельно тактируемым нейроконтурам, усовершенствование архитектуры и более четкая специализация нейронов в нейрокластерах
* постоянное повышение уровня абстракции
* метанейросети: я начал добавлять в Нейролабораторию то поведение, которое наблюдаю у себя.
Подробнее о последнем. В этой статье затронут первый аспект – тестирование.
Началось все с системы тестирования. Бывало, что после минимальных изменений в коде ИНС, она начинала работать совсем не так. Ошибка оставалась незамеченной, а потом вылазила после долгой отладки. Скажем, в некоторых условиях нужная связь между нейронами не прорастала. Беглый взгляд на нейросеть давал результат «вроде все как раньше». Для более быстрого обнаружения таких неполадок и нужна была система тестирования. Первая система тестирования была основана на таблицах данных о нейронах. В каждом нейроне проверялась информация: идентификатор (такой нейрон должен существовать, по нему в происходит сверка остальных полей), идентификатор кластера, тип нейрона, порог и количество связей. Вначале, такие таблицы я прописывал в коде на С++. (Скопировать таблицу нейронов в Excel, выделить нужную колонку данных, вставить ее в Visual Studio, вызвать макрос «дописать в конец каждой строки некоторую строку» – типа запятых для разделения разных полей). Выходило что-то типа

  1. namespace B2Test
  2. {
  3. NeuronTestData g_arrTestData[]={
  4.         NeuronTestData(102, 809,  BrainB2::NTypeIn, 1, 1),
  5.         NeuronTestData(103, 817,  BrainB2::NTypeIn, 1, 1),
  6.         NeuronTestData(104, 825,  BrainB2::NTypeIn, 1, 1),
  7.         NeuronTestData(105, 833,  BrainB2::NTypeIn, 1, 1),
  8.         NeuronTestData(106, 841,  BrainB2::NTypeIn, 1, 1),
  9.         NeuronTestData(107, 849,  BrainB2::NTypeIn, 1, 1),
  10.         NeuronTestData(108, 857,  BrainB2::NTypeIn, 1, 0),
  11.         NeuronTestData(109, 865,  BrainB2::NTypeIn, 1, 1),
  12.         NeuronTestData(110, 873,  BrainB2::NTypeIn, 1, 0),
  13.         NeuronTestData(111, 881,  BrainB2::NTypeIn, 2, 2),
  14.         NeuronTestData(112, 889,  BrainB2::NTypeIn, 1, 1),
  15.         NeuronTestData(113, 897,  BrainB2::NTypeIn, 1, 1),
  16.         NeuronTestData(114, 905,  BrainB2::NTypeIn, 1, 0),

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

Сначала пришлось написать обслуживающий код. Выбор данных для тестирования берется в зависимости от того, какие данные поступали на вход нейросети. А именно, какая конкретно строка текста будет скормлена ИНС. И естественно, учитывается еще и тип ИНС – потому что в Нейролаборатории их несколько. (Именно этот момент и запечатлен тут – применяется еще тестирование по таблицам «NL UI: тестирование ИНС» ( http://neurocod.net/blog/tag/2010/06/nl-ui-тестирование-инс )). Как получить подсеть нейросети для формирования теста? Большая часть уже была готова, включая интерфейс: см. «Понимание структуры ИНС-2» ( http://neurocod.net/blog/tag/2010/01/понимание-структуры-инс-2 )


Выделенную подсеть можно использовать для создания тестирующей

.
Код сериализации такой вспомогательной нейросети тоже был готов (тестовая нейросеть имеет один и тот же тип независимо от того, ИНС какого типа она тестирует) – потому что код сериализации нейросетей универсальный, на основе шаблонов. Осталось подумать, как находить произвольный подграф в заново отработавшей исходной нейросети, которую надо протестировать. Задача ресурсоемкая и не простая для реализации. Легче всего с сенсорами: сначала получить сенсорные нейроны, узнать их идентификатора, прописать это соответствие, и затем искать оставшиеся. Но тут подумал: я ведь легко справляюсь с подобной задачей поиска подсети? Да. Почему? Нужно перенести эти эвристики и в Нейролабораторию. Полезли мысли типа таких:
* очередность (порядок) идентификаторов в тестирующей и тестируемой ИНС должны совпадать.
* (я не прокручиваю таблицу далеко) проверять не все нейроны, а только с идентификаторами в небольшой «округе» от исходного идентификатора – например, +-100 нейронов. Это даст защиту от незначительных изменений нейросети. Для каждого теста должны быть настройки гибкости: величина окрестности для поиска нейронов от первоначального идентификатора. Для начала можно реализовать единственный вариант: окрестность 0 – то есть, брать те же идентификаторы, что и раньше, и проверять связи. Было сделано.
* относительное расстояние между идентификаторами может отличаться на некоторую небольшую дельту от того, которое было в исходной ИНС. А если относительное расстояние не меняется… были нейроны 3, 5, 10, а стали 13, 15, 20… Эврика! Для многих случаев подойдет и такой простой способ поиска соответствия нейронов в тестируемой и тестирующей НС: перебирать только самый первый нейрон в подграфе, а остальные брать от него на прежнем смещении. И каждую полученную комбинацию проверять. Было сделано. Старую схему, которая ищет только идентификаторы с точным совпадением, решил не удалять. Старый режим проверки принят по умолчанию для вновь создаваемых тестов. Он удобен для проверок после рефакторинга – точно так ли ведет себя ИНС. Если же разработчик хочет ослабить ограничение поиска, то меняет в таблице значение всего одного поля, и поиск будет вестись уже более широко. Такое ослабление нужно санкционировать.

Грядущая Раса: Hypocrisy – A Coming Race

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Why all this searching?
The answer’s always been near
It is our destiny

Away from a screeching people
Waiting to destroy ourselves
They can’t interfere with history

Nuclear creation
For eternity they can’t be strained

All I wish they would land here!
But It’s too late now
Time is dying a soldier
With all them to around decay

In the other dimension
Time will no longer exist
No one never grow old
Something mankind will never resist
The destroying of soldiers

NL UI: тестирование ИНС

Среда, Июнь 30th, 2010

Метрические пространства и ИНС

Среда, Февраль 10th, 2010

Читал в википедии новый стандарт С++, и по ссылкам плавно перешел к определению метрического пространства. В целях креативного продуктивного развлечения, решил скрестить образы метрического пространства и ИНС.
Сначала возникло: «Элементы множества – нейроны, расстояние между нейронами определяется как сила некоторого коэффициента в межнейронной связи… ». Но это в каком году надо было такое писать? Явно не в 2010. Поэтому вторая попытка:
Элементам метрического пространства ставятся в соответствие отдельные кластеры нейросети. Можно ставить не отдельные кластеры, а отдельные нейронные цепочки – так как последний кластер такой цепочки будет соответствовать все тому же «один кластер».
Расстояние между элементами пространства задается при помощи нейронных цепочек из одного или более кластеров
Архитектура цепочки, которая хранит информацию о расстоянии между объектами, может быть различной. Пусть А и Б – нейронные кластеры, соответствующие некоторым элементам множества, на котором определено метрическое пространство. Тогда расстояние может сохраняться (см. рисунок, нейроны на рисунке обозначают кластеры):


Варианты хранения информации о расстоянии между А и Б


Вариант 1. Есть кластер с тремя связями: от А, Б и от кластера с информацией о расстоянии. Для того, чтобы оперировать с информацией о расстоянии, могут применяться различные механизмы. Но для начала, кластер, обозначенный как «d=1.7», нужно активировать. В схеме 1 – активировать А и Б, далее служебный кластер частично активируется (нечеткое распознавание), на нем концентрируется внимание, он распознается полностью, и активирует кластер «d=1.7». Чтобы убрать нечеткое распознавание, можно пойти другим путем – снизить порог срабатывания.
Вариант 2. Чтобы убрать стадию нечеткого распознавания, добавлен отдельный кластер. Связь «вперед» должна также полностью активировать следующий кластер. Как видно, во всех этих вариантах соблюдается условие симметрии А и Б – так как они должны активироваться одновременно.
Вариант 3. В многозадачной ИНС кластеры, объединяющие А и Б, могут хранить не только информацию о расстоянии. Чтобы не путать такие кластеры, в данном случае добавлен кластер вопроса «d?». Для того, чтобы узнать расстояние, нужно активировать кластеры обоих объектов и кластер вопроса о расстоянии. Нечеткое распознавание не нужно.
Вариант 4. То же, что и в пункте 3, но расстояние хранится не в одном кластере, а в цепочке – в данном случае, цепочке знаков, которые можно преобразовать в число.

В вариантах 1-2-3 кластер «d=1.7» мог соответствовать последнему кластеру цепочки, похожей на вариант 4, которая кодировала расстояние побуквенно. Для обработки такой цепоки нужно умение счета, умение сравнивать числа на величину и т. д. А можно добавить такую возможность в ИНС на базовом уровне, где за операции с числами будет отвечать интерфейс к калькулятору. Тогда нужно меньше нейронов (один кластер вместо цепочки), и вариант 4 не нужен.

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

Сериализация ИНС

Вторник, Январь 26th, 2010

Стандартный для НЛ родительский шаблонный класс ИНС обеспечивает универсальный гибкий механизм сериализации ИНС.
Для того, чтобы данный тип ИНС можно было сохранить или загрузить через пользовательский интерфейс, ее класс должен быть зарегистрирован как поддерживающий сериализацию. Для этого создается глобальный объект SerializableBrainClassRegistrator с данными о ИНС – с именем класса ИНС и другими. При выборе операции открытия ИНС из файла, сначала считывается имя класса ИНС, затем, если класс с таким именем зарегистрирован как поддерживающий загрузку, происходит создание экземпляра данного класса, и вызывается метод загрузки. Аналогично и с сохранением. Механизм разрешения нужен для того, чтобы не вводить в заблуждение пользователей – так как в научно-любительской программе далеко не все ИНС могут поддерживать сериализацию, из-за неактуальности операции для ее программирования.
При необходимости сериализации, в классах нейронов и связей пользовательской ИНС нужно переопределить функции сохранения и загрузки:

  1. virtual void save(QDataStream & s)const;
  2. virtual bool load(QDataStream & s);

В этих функциях, основываясь на примере реализации в других ИНС, провести сериализацию данных нейрона и связи, специфических для данного класса, и вызвать родительскую версию.
Универсальный алгоритм в упрошенном описании действует так. Проводит сериализацию описания формата и в случае загрузки проверяет, что формат поддерживается.
Сериализует количество нейронов, которое надо загрузить или сохранить. Далее, если нейронов более одного, происходит сериализация тела нейрона. После этого идет код подстраховки – сериализуется проверка на размер данных сериализованного нейрона. Если проверка пройдена, сериализуются и остальные нейроны.
Аналогично происходит сериализация связей. Так как все нейроны уже созданы, то связи можно создавать напрямую. После сериализации первой связи идет код проверки размера связи в сериализованном состоянии.
Также сериализуются: комментарии, точки останова, нейронные группы, и т. д. После данных каждого типа вставляется код проверки. Для сериализации данных, специфических для конкретной ИНС, вместо переопределения функции всей сериализации, удобнее переопределить лишь функцию serializeBrainSpecificData. Если нужно, то можно переопределять и другие функции.

История навигации

Пятница, Январь 22nd, 2010

Чтобы не сохранять (в другой программе типа текстового редактора) идентификаторы нейронов и кластеров, к которым нужно будет еще раз вернуться при отладке, в Нейролабораторию добавлено ведение истории навигации. Идея – та же, что и в Visual Studio, когда ведется история перехода курсором по файлам и строкам внутри файла.
Следующие события сохраняются:
* Выделение и снятие выделения с нейронов
* Выделение текущей связи
* Подсветка циклов
* Копирование текста
Для всех из списка возможна отмена и повтор действия. Для того, чтобы отмена приводила к как можно более похожему состоянию, введены такие дополнения. Информация о выделении нейронов содержит два списка – с выделенными и погашенными нейронами. При отмене, списки меняются местами – исходно выделенные нейроны гасятся, погашенные – выделяются.
Некоторое действие (например, выделение цикла) может привести к множеству действий (например – к выделению нейронов, созданных в том цикле). Спровоцированное действие также попадет в историю навигации. Но отменять и повторять их по одиночке неправильно, нужно обрабатывать их вместе. Для автоматизации группировки используется создание объекта NLUndoLock. При создании, этот объект регистрируется. (Соответственно, и при уничтожении этого объекта, он также оповещает свое хранилище). Если других аналогичных живых объектов нету, то начинается новый блок действий, иначе используется старый. В таблице истории навигации, группировка в блоки показывается стандартными скобками. Красным маркером показывается текущая позиция курсора отмены/повторения, а по совместительству – и курсора занесения истории новых команд.


Окно навигационных действий

Понимание структуры ИНС-2

Четверг, Январь 21st, 2010

Продолжение.
С ростом сложности ИНС, рассмотренных способов ориентирования в структуре ИНС становится недостаточно. Желательно визуально отображать структуру. Визуальное отображение на двухмерной карте ИНС мало помогает. Решение:
1) Применять дополнительную карту для отображения структуры
2) На этой дополнительной карте отображать не все нейроны, а только выбранного кластера и всех его признаков – рекурсивно. (Если не повезет, то из-за рекурсии на карту может попасть слишком много нейронов).
3) Вместо отображения каждого нейрона кластера, отображать кластеры высокоуровнево – одним квазинейроном на кластер. Для ИНС Б2 экономия в площади – девятикратная.
4) Вместо отображения кластеров в порядке создания, использовать двухмерную сортировку – по уровню иерархии и очередности срабатывания


Сравнение нового и старого способа просмотра цепочек


Чтобы было понятнее, зачем все это городить, можно взглянуть на фрагмент ИНС чуть посложнее:


Пример двухмерной сортировки – синие линии отделяют уровни иерархии


Детали устройства со стороны разработчика ИНС:
1) Если ИНС сообщает, что в ней есть кластеры, то при загрузке окон окружения ИНС создается и окно для отображения структуры нейронных цепочек
2) Каждый нейрон может переопределить функцию INeuroCluster* cluster()
3) В своей реализации INeuroCluster, зависящем от ИНС, можно возвращать список кластеров-признаков и кластера, предыдущего в цепочке памяти. Для ИНС Б2 используются кластеры нейронов всех связей с nEn и nIn.

Детали устройства со стороны разработчика интерфейса Нейролаборатории:
1) Для двухмерной сортировки и отображения структуры используется служебная ИНС. ИНС этого типа нельзя создать через интерфейс в качестве самостоятельной ИНС для исследований в НЛ.
2) Каждый нейрон этой ИНС соответствует кластеру главной ИНС.
3) Команду отображения цепочки можно вызвать несколькими способами: выбором кластера в таблице кластеров, двойным щелчком по идентификатору кластера в таблице нейронов, связей или нейронных цепочек, путем ввода идентификатора кластера в окне для отображения цепочек
4) После получения команды отображения цепочки по кластеру, у заданного кластера рекурсивно получаются все признаки и все кластеры, предшествующие в цепочках. Для них создаются соответствующие нейроны и связи между ними. Связи строятся двух типов – «признак обобщения» и «следствие».
5) Производится двухмерная сортировка. Все квазинейроны вначале имеют один и тот же уровень иерархии и время срабатывания. Начиная с кластера-инициатора, рекурсивно распространяется информация о том, что кластер-признак – ниже по иерархии. У заданного кластера, кластеры-признаки вместе с кластерами, предыдущими в цепочке, получают также информацию о том, что они должны сработать как минимум на цикл раньше, чем заданный кластер. В смысле реализации, вычисления производятся итеративно, а не рекурсивно – чтобы не переполнить стек. Если за всю итерацию ни один квазинейрон не получил инфорамцию о том, что его уровень иерархии надо еще более понизить, а максимальное время срабатывания – еще более отсрочить, то вычисления прекращаются. Если количество итераций превысило количество нейронов, это значит, что в данном фрагменте ИНС наблюдается зацикливание, и вычисления прекращаются.
6) Полученные относительные числа нормализуются: уровни иерархии и время срабатывания индексируются от нуля и выше, последовательно. По этим индексам строится отображение. В каждом столбце заносятся квазинейроны с одним и тем же интервалом максимального первого срабатывания. Уровни иерархии заносятся как отдельные строки и выделяются синими линиями. Выделение линий важно, так как в одном столбце могут быть несколько квазинейронов и несколько уровней, как на втором рисунке.

Понимание структуры ИНС в Нейролаборатории

Четверг, Январь 21st, 2010

В Нейролаборатории, перед вами нейрон цепочки памяти. Как понять, что именно он запоминал? Вариантов много.
Можно сделать двойной щелчок в строке этого нейрона по ячейке с циклом создания нейрона. Тогда по всем окнам пройдет сообщение «подсветить цикл №Х». В окне истории ввода/вывода будет подсвечена та строка с вводом/выводом, цикл создания которой наиболее близок к подсвечиваемому. Наиболее вероятно – что будет подсвечен тот ввод/вывод, который и был связан с данным нейроном и кластером. Можно будет сориентироваться, что за текст обрабатывался системой в момент создания кластера.


Двойной щелчок по циклу создания нейронов


Можно иначе. В кластере этого нейрона, выбрать нейрон контура nIn, и в окне с таблицей связей посмотреть на все его признаки и, таким образом, увидеть, что именно запоминал данный кластер (или что он распознает). Можно перейти на запомненные признаки по двойному щелчку их идентификатора в таблице связей – но если нужно только узнать, что за буквы были запомнены, то достаточно посмотреть комментарий нейрона, на который указывает связь, в той же таблице связей, в столбце правее.
Обычно достаточно выделить нейрон контура nIn в таблице связей. Если уже выбран нейрон другого контура, и нужно выбрать nIn, то, чтобы не переключать внимание на таблицу нейронов, не открывать ее, не искать визуально границ кластера и nIn в нем, можно в окне с таблицей связей выбрать из выпадающего списка нейрон нужного типа – там все нейроны кластера того нейрона, связи которого уже отображаются.
Вариант с подсветкой цикла проще. Однако, он не подходит, если нейрон был создан во время обобщения других нейронных цепочек – так как никакого ввода/вывода и обмена с внешней средой в тот момент не было, а если и был – то не относится к обобщению. Не проблема. В ИНС обычно есть окно с логированием. В информацию каждой строки лога входит и цикл логирования. Хороший тон – заносить в лог информацию о том, что за цепочки выбраны для обобщения. В ответ на глобальное сообщение о подсветке цикла, таблица логов также подсвечивает строку с циклом, наиболее близком к циклу сообщения. Там будет текст типа «сон 2ВЦ обобщение: выбраны н-ы 901 и 869». Можно ввести идентификатор одного из нейронов в поле ввода идентификатора в таблице связей, и далее применять просмотр связей. Но вводить вручную долго. Вместо этого можно сделать щелчек средней кнопкой мыши в любой ячейке таблицы. Из текста в ячейке таблицы будут выделены числа, и показано окно с выбором, что сделать с любым из чисел – подсветить нейрон с таким идентификатором или цикл с таким номером. После нажатия на кнопку действия, окно само закроется.


Выделить цикл -> окно логов -> выделить нейрон


Но что, если запомнены высокоуровневые признаки, у которых нет комментария? Если бы вы отлаживали чужую ИНС подобно коду на ассемблере в чужой программе, то можно было бы самому задавать комментарии.
Для частичного решения проблемы применяется автоматическое назначение комментариев. Алгоритм следующий.
1) У сенсорных нейронов комментарии не меняются и соответствуют воспринимаемым буквам
2) У кластеров цепочек памяти, если была изменена – добавлена или удалена – хотя бы одна связь, выставляется флаг «пересчитать комментарий»
3) Один раз на каждую высокоуровневую итерацию происходит перерасчет комментариев.
4) Всем нейронам кластера дается одинаковый для всех комментарий. Поэтому можно говорить «комментарий кластера» вместо «комментарий нейрона».
5) Комментарий у кластера берется так: в скобках перечисляются комментарии всех признаков, которые входят в nIn, а разделяются они через вертикальную черту или иной разделитель. Например, сенсорный нейрон «а» запомнен кластером, кластер принимает комментарий «(а)».
6) Каждый признак, который запомнен кластером, рассматривается как цепочка. Вся такая цепочка заносится в комментарий. Например, некоторая цепочка запомнила слог «об», двумя кластерами – которые имеют комментарии «(о)» и «(б)». Если второй кластер это цепочки будет распознан и станет признаком некоторой другой цепочки, то он войдет в нее как «((о)|(б))»
7) После того, как комментарий кластера поменялся, информация о том, что нужно обновить комментарий, выставляется для всех зависимых от него кластеров – для кластера, следующего в цепочке, и для более высокоуровневых кластеров. Их комментарии будут обновлены в следующей итерации.

Показ границ линий расположения в 2d

Воскресенье, Январь 17th, 2010

В дополнение к «№93 NL UI: Выбор координат нейронов для карты нейронов» ( http://neurocod.net/blog/tag/2009/04/№93-nl-ui-выбор-координат-нейронов-для-карт ). Чтобы было легче определять границы кластеров и нейронных цепочек, при «переводе строки» (расположения новых нейронов) в память заносится верхняя граница строки, и затем всегда отображается.


Синие линии – границы строк

Группировка истории нейроконтуров по итерациям

Пятница, Январь 15th, 2010

Переход на высокоуровневые итерации сделал простой визуальную группировку строк операций нейроконтуров в таблице истории.


Группировка в стандартном стиле - красными линиями

Оптимизация отображения нейронов в 2d

Четверг, Январь 14th, 2010

Речь об оптимизации не производительности, а полноты информирования пользователя.

Для того, чтобы справиться с отображением большого количества нейронов, ранее уже описывался вариант отображения – «отображать связи только выделенных нейронов». Но выделять нейроны ради одного только отображения утомительно. Решение: в этом режиме, кроме выделенных нейронов, отображать связи также и у тех нейронов, на которые указывает курсор. А курсор как раз итак обрабатывается при движении – так как нужно обновлять информацию для подсказки (tooltip). Также, в этом режиме, в этот список нейронов попадают и нейроны той связи, которая выделена в окне таблицы связей.

Другая оптимизация – независимо от режима, связи нейрона под курсором рисовать в последнюю очередь – чтобы они оказались на самом верху и не заслонялись другими.

Еще одна оптимизация – независимо от режима, связи нейронов ранее описанного списка рисовать более широкими линиями.

Чтобы подсказка не мешала смотреть связи нейрона под курсором, нужно нажать и удерживать колесико мыши.