Постановка задачи:
Сделать максимально упрощённую, но при этом функциональную модель LIF (Leaky Integrate-and-Fire) нейрона. Арифметика-линейность-бинарность. Никаких дифуров, непрерывных функций (экспонент) и прочего подобного.
Сделать на тех же принципах максимально упрощённую модель STDP (Spike-Time Dependent Plasticity) синапса.
Обогатить получившуюся систему механизмом R-STDP (Reward-Modulated STDP).
Собрать из этих нейронов и синапсов небольшой мозг. Снабдить этим мозгом виртуального "чудика". Сделать ему простой (одномерный) мир с двумя сущностями - пищей и опасностью. Снабдить его сенсорами (опасность слева, еда справа..., отдаляемся/приближаемся к еде/опасности и т.д....), моторами (движение влево/вправо). Запустить симуляцию, и посмотреть, что будет получаться.
Спойлер: что-то получилось.
LIF нейрон.
У него есть мембранный потенциал. Это целое число. Для мембранного потенциала задан порог. При превышении порога нейрон генерирует импульс (спайк). Этот импульс убегает с "выхода" нейрона к другим нейронам, с которыми у этого нейрона есть соединения.
Как меняется мембранный потенциал? У нейрона есть вход, на который прибегают входные импульсы от других нейронов. Каждый входной импульс увеличивает мембранный потенциал на единицу.
Когда мембранный потенциал достигает порога и генерирует импульс (спайкует) его мембранный потенциал сбрасывается до нуля.
Кроме того, мембранный потенциал постоянно "утекает". Через заданное число тактов, с момента последнего обновления, если ничего не произошло, потенциал уменьшается на единицу.
На видео показан чуть более сложный общий случай. Но суть должна быть понятна. Входящие спайки увеличивают мембранный потенциал. Эффекты входных спайков суммируются. Если ничего не происходит, потенциал утекает. При превышении порога, происходит "разряд".
2. STDP синапс. Будем (в рамках нашей модели) называть синапсом некую сущность, связь, коннект, которая соединяет два нейрона. Синапс - штука направленная, я бы даже осмелился сказать - анизотропная. Он двумя концами соединён с двумя нейронами. Но эти нейроны для него на равнозначны. Картинка несимметрична. Синапс различает PRE-нейрон (он подключен к выходу этого нейрона) и POST-нейрон (он подключен к входу этого нейрона).
Синапс может быть активен (пропускает через себя импульс от пре к пост) или неактивен (не пропускает импульс). Это зависит от некой внутренней величины - синаптического веса. Если синаптический вес равен нулю - синапс неактивен. Если синаптический вес больше нуля, синапс активен.
Каким образом меняется синаптический вес? Он меняется в соответствии с простым алгоритмом который как раз и называется STDP. Состоит он в следующем:
если после спайка ПРЕ нейрона в течение некоторого заданного (не очень большого) промежутка времени произошёл спайк ПОСТ нейрона, синаптический вес увеличивается на единицу (связь усиливается);
если после спайка ПОСТ нейрона произошёл спайк ПРЕ нейрона, синаптический вес уменьшается на единицу (связь ослабевает);
Для чего это нужно? Какой в этом может быть смысл? Представим себе "кучу" нейронов, которые как-то хаотически соединены между собой и хаотически спайкуют. Наличие механизма STDP позволяет сигналу пробивать в этом хаотическом конгломерате упорядоченные, направленные "дороги". В некотором смысле, прокладывать кабели, по которым сигнал будет распространяться от сенсоров ... куда-то. Непонятно куда. Процесс сугубо локальный. Он задействует только два нейрона и коннект между ними. Ему без разницы, что там происходит в большом внешнем мире. И есть ли он вообще этот большой внешний мир.
3. А большой внешний мир существует. И из него поступает информация через специальные сенсоры. Приходят специфические сигналы. Награда (reward). Или наказание (penalty). Обратная связь. Этот сигнал, который участвует в механизме R-STDP. Reward-Modulated STDP. То есть STDP, модулированный вознаграждением. И работает он - проще некуда. Что такое "чистый" STDP мы уже знаем. Теперь мы будем применять его только если активен сигнал вознаграждения. А если сигнала вознаграждения нет, ничего не делаем.
А ещё мы будем использовать в модели зеркальный механизм, основанный на сигнале наказания. Как он работает сообразить нетрудно. Если у нас реализовалось событие пре-пост спайков, в случае присутствия в системе активного сигнала вознаграждения, мы синаптический вес увеличиваем на единицу. В случае же сигнала наказания (penalty) мы синаптический вес уменьшаем.
И казалось, после предварительного изучения теории - это всё, что необходимо для реализации финальной стадии упражнения. То есть, если написать вычислительное ядро на си++, например, собрать мозг, смоделировать мир, то оно вероятно заработает. Нет... не заработало. Началась круговерть отладки-тестов-проверки гипотез... которая привела к следующему:
R-STDP часто называют трёхфакторной пластичность. Награда, reward - это третий фактор вдобавок к двум основным: спайк-активности и зависимости от времени. Чтобы всё заработало, пришлось добавить "четвёртый фактор" - инерционность подкрепления. То есть, после увеличения синаптического веса в присутствии сигнала вознаграждения, синапс на некоторое время делается нечувствительным к сигналам наказания. И наоборот, после увеличения синаптического веса в присутствии сигнала наказания, синапс на некоторое время делается нечувствительным к сигналам вознаграждения.
В модель пришлось ввести "случайные блуждания". Весь мозг, все нейроны спонтанно спайкуют с регулируемой интенсивностью. Эта случайная активность - движок, источник энергии всего механизма построения и адаптации сети. Я не знаю как там в настоящих биологических мозгах, но в такой простой модели без этих случайных блужданий просто ничего не запустится и не будет работать. И на старте это было совсем неочевидно.
Прунинг. Неиспользуемые связи с заданной периодичностью разрываем и переподключаем. Ну это уже наверное скорее из любви к искусству. Работало как-то и без него, но с ним заработало красиво и наглядно.
Неожиданно модель получилась совсем не детерминированная. Я ожидал, что (при успехе) в мозге будут пробиваться дороги от сенсоров к "моторам" по которым будут бегать спайки как по жёстко пропаянным проводам. Получилось совсем не так. Импульсы бьют стохастически по обоим моторным нейронам (мир одномерный, поэтому агент может двигаться только вправо-влево). И если "ничего не делать" то вероятность каждого из исходов будет где-то 0.5. Всё, что делают (в модели) эти красивые теоретические механизмы - немного смещают распределение в нужную сторону. В результате "чудик" уверенно научается "в среднем" двигаться в правильную сторону.
В заключение наверное следовало бы извиниться перед теми, кто ждал строгой теории, формул и теорем. Ничего этого нет. Чисто вычислительный эксперимент. Как писал Сергей Марков, исследователи (условно) делятся на "чистюль" и "грязнуль". Здесь я выступаю как грязнуля. Потенциально могу и как чистюля тоже. И даже верю и надеюсь, что до этого когда-нибудь время дойдёт. Но не в этот раз.
Весь код вычислительного ядра и симуляции (на всякий случай) в открытом репозитории.
https://github.com/evgenyagantaev/binary_rstdp
Конечно, сама собой напрашивается тема сравнения с ANN. Понятно каким образом сделать и обучить простенькую нейронку, которая будет "железобетонной" реализацией нужного поведения. Но проблема как раз в этой железобетонности. Модель с мозгом на основе SNN пластична, адаптивна, может обучаться-переобучаться "на лету". И это отражено даже в интерфейсе симуляции. Можно "на горячую", в процессе переключателями менять логику предъявления награды/пенальти, и модель подхватит. И я уверен, что именно за SNN будущее ИИ. По крайней мере, в качестве мозгов для автономных роботов.
Всем добра.
Источник


