Lava-NC трёхфакторная пластичность (практикум)

Предъявите ваши факторы

— Раз есть трехфакторная, значит должна быть и двухфакторная? Или нет?

— Есть. Но её так не принято называть почему-то. Это так называемая STDP. Spike-Time Dependent Plasticity.

— А почему пластичность? Пластичность чего?

— Пластичность — это изменчивость. Изменчивость синаптических весов. То есть, можно считать, что пластичность здесь — синоним слова обучаемость. Синаптические веса меняются, и система чему-то обучается.

— Синапс это вроде такой разъём, который соединяет два нейрона?

— Ну типа того. И там ещё некоторая однонаправленность присутствует. Синапс пропускает разряды нейронов, спайки в одном направлении. То есть нейроны, относительно синапса становятся неравноправными. Один как бы «перед» синапсом, и называется пресинаптическим, а второй — «после» синапса, и называется постсинаптическим.

— Это в реальной биологии так, или в модели, или и там, и там?

— Скорее конечно в модели. В биологии всё очень сложно. Понятно, что модели много заимствуют из биологии, названия, например, все эти нейроны, синапсы, мембранные потенциалы… Но очень многое упрощается, где-то даже примитивизируется.

— А эти синаптические веса — это что-то типа проводимости или коэффициента усиления?

— Да. Пожалуй. С формальной точки зрения — это просто некоторый множитель.

— Как и в «обычных», не импульсных нейронных сетях?

— Да. Типа того.

— И ещё про эту самую трехфакторность. Что собственно за факторы? Вот в этой двухфакторной…, о каких двух факторах речь?

— Это пресинаптическая и постсинаптическая активность нейронов. Нейроны генерируют импульсы-спайки по некоторым правилам. Генерируют и пресинаптический и постсинаптический. И в зависимости от того, в какой последовательности эти спайки генерируются, меняются веса синапсов. Мы это позже подробно разберём.

— А что за третий фактор в трёхфакторной схеме?

— Это некая дополнительная сущность — вознаграждение, поощрение. То есть логика понятная: если система сделала что-то хорошее, некоторый её модуль, назовём его, например, мотивационным модулем (он должен уметь видеть результаты действий системы и оценивать их в категориях хорошо-плохо), генерирует специальный сигнал — поощрение, награду, и если сигнал поощрения сгенерирован, те связи между нейронами, то есть, синапсы, которые были активны незадолго до генерации сигнала поощрения, в некотором смысле укрепляются.

Динамика изменения синаптических весов

— Можно вживую на это посмотреть. Соберём вот такую систему.

0fb598ee3ad8770d97361c9af075d085.png

Тут один пресинаптический нейрон и два постсинаптических. Они соединены пластичным полносвязным слоем. То есть, там как бы живут синапсы, с изменяемыми, обучаемыми весами. Зададим какие-то начальные значения и прогоним 200 тактов моделирования. Можно посмотреть, как изменились веса.

eb9bb585862b9b4a8e1319822e6f5a7b.png

— А это всё у нас что?

— Это всё у вас Lava-NC фреймворк.

— И что, система при этом чему-то обучилась?

— Хороший вопрос… И да, и нет. Понятно, что любая система, в любом своём текущем состоянии «умеет что-то делать». В каком смысле? В том смысле, что она реализует некоторую функцию, которая отображает входные данные в выходные. После такого «обучения» функция изменилась. То есть система, как бы, «научилась» делать что-то новое, чего она «не умела» делать изначально.

— Понятно, что это формально. Речь же не идёт о распознавании котиков и собачек по фотографиям…

— Ну естественно. Во-первых, система маловата — всего три нейрона; во-вторых, никто и не ставил перед собой такую цель, научить её чему-то. Это просто учебный пример, тьюториал от разработчиков Lava.

— Да. Так и что такое Lava, и зачем?

— Lava-NC видится мне, в своем текущем состоянии, двуединой системой. С одной стороны, это готовый фреймворк для программирования чипов семейства Loihi, с другой стороны, это такой полигон для моделирования и экспериментов со всякими штуками в области нейроморфных вычислений, импульсных нейронных сетей и, возможно, прочего подобного.

— А что такое Loihi?

— Loihi — это будущее, чувак!

Вознаграждение? Дайте два

— Вот ты сказал, что в присутствии сигнала поощрения, связи некоторым образом укрепляются. А каким это некоторым образом? Мы тут уже практически программировать собрались, а как такие расплывчатые формулировки можно программировать? Нельзя ли поточнее?

— Да. Конечно. Здесь важно понять принцип. Принцип состоит в том, что сам по себе сигнал поощрения ничего, в том числе и синаптические веса, не меняет. Он работает поверх уже имеющегося механизма изменения весов, пластичности. Называется этот базовый механизм (который, собственно, знает как, когда и на сколько менять веса синапсов) STDP. Наша трёхфакторная схема называется Reward-Modulated STDP, или R-STDP. Сигнал поощрения в этой схеме работает как некий катализатор, или аналог нейромодуляторов в реальных биологических системах. Механика очень простая: правило модификации весов STDP применяется только в присутствии активного сигнала поощрения. Да. Это всё. Так просто. Больше ничего не надо. Этого достаточно. Осталось только разобраться с тем, что такое собственно STDP?

Криптопалеонтология

— Давай разбираться. Что умеет делать система из двух нейронов и синапса между ними? Она умеет либо распространять спайк (импульс) через синапс от пресинаптического нейрона к постсинаптическому и дальше, либо подавлять это распространение, пресекать его на уровне синапса. Как это делается в рамках модели LIF-нейрона и правила обучения STDP (spike-time dependent plasticity)? Очень просто, если постсинаптический нейрон выдал спайк вскоре после того, как был сгенерирован спайк пресинаптическим нейроном, это нам нравится, это мы поощряем, и вес синапса, который соединяет эти два нейрона, увеличивается. В противном случае, если постсинаптический нейрон спайканул, а спайка пресинаптического нейрона перед этим не было…, более того, пресинаптический нейрон спайканул после того, как спайканул постсинаптический — это нам не нравится, это уже где-то покушение на наше непреодолимое желание приписать внешнему миру строгую каузальность, мы это не любим и не поощряем, и, как результат, вес синапса, который соединяет такие два нейрона, понижается (штрафуется).

Причём вот эти «мы», которым предположительно что-то нравится или не нравится во временных диаграммах спайкующих нейронов, это не какие-нибудь там безродные разработчики машин-лёрнинг алгоритмов, это сама Её Величество Эволюция! Общепризнанно, что STDP поведение синаптических связей — это глобальный принцип организации нервной системы всех организмов, которые сподобились эту самую нервную систему иметь.

— Но это же тупо. Как такую модель можно чему-то более-менее сложному научить? Это разомкнутая система с однонаправленной передачей сигналов. Кому нужны разомкнутые системы?

— Так-то да. Но это нам сейчас хорошо так рассуждать. У нас сейчас тела, где всё, до мельчайших деталей охвачено контурами обратной связи. Без этих обратных связей мы не можем ни вдохнуть, ни выдохнуть. А вот представь себе какого-нибудь Примитивуса Стелящегося, у него еще не было нервной системы, у него был непонятный кисель из клеток, которые вдруг научились спонтанно хаотически спайковать.

5c35025323da4920731b93c464303149.png

И ему надо было в этом спонтанно пульсирующем, хаотически вспыхивающем желе «проложить кабели», то есть, выстроить каналы распространения сигналов, хотя бы чуть более определённые, чем броуновское движение. И тогда, в незапамятные времена, когда STDP возникла и эволюционно победила — это был настоящий прорыв, это была настоящая революция! Наверное можно сказать, что только с того момента, как в нервной ткани организма воцаряется принцип STDP, в его личной маленькой, персональной вселенной возникают такие категории как Восприятие, Пространство и Время.

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

d60fc03551664cf5ab447271d7191ddf.png

Супер-глазастикусом его назвали конечно не потому, что он мог пронзать орлиным взором толщу вод кембрийских морей, а потому, что, как это часто бывает в палеонтологии, у него было 50–70 (ну или 500–700) светочувствительных клеток, которые худо-бедно могли различать два-три уровня освещенности.

Жил он в раковине и знал, что если вдруг среди бела дня свет солнца заметно меркнет, значит нужно быстро-быстро за счёт сокращения своих мускулюсов втянуть себя в раковину. Потому, что это практически наверняка означало, что приплыл кто-то большой, чтобы схватить его, вытащить из раковины и сожрать.

Понятно, что это метафора, ничего такого он не думал и не знал. Ему и не надо было ни думать, ни знать. Ему достаточно было одной, многократно продублированной разомкнутой схемы передачи сигнала от светочувствительных клеток до клеток мышц. Эти мышцы быстро, без лишних раздумий, сокращались и обеспечивали очень своевременное втягивание вкусного тельца Глазастикуса в раковину.

Базовая STDP модель

— Перейдём, однако, от спекулятивных криптопалеонтологических умозаключений к материям более строгим, к математике. Попытаемся формальным языком формул описать, как мы себе представляем этот самый механизм STDP.

Пусть \alpha — идентификатор пресинаптического нейрона; \beta — идентификатор постсинаптического нейрона; \omega_{\alpha\beta} — вес синапса, соединяющего нейроны \alpha и \beta . Обозначим через t_i^{\alpha} моменты времени генерации спайков пресинаптическим нейроном \alpha, где i = 1, 2, \dots , N номера спайков. Аналогично: t_j^{\beta} — моменты времени генерации спайков постсинаптическим нейроном \beta, и j = 1, 2, \dots , M номера спайков. Суммарное изменение синаптического веса \Delta \omega_{\alpha \beta} по результатам N пресинаптических и M постсинаптических спайков, вычисляется следующим образом:

\Delta \omega_{\alpha \beta} = \sum_{i=1}^N\sum_{j=1}^M W(t_j^{\beta} - t_i^{\alpha})

Здесь W(x) — STDP-функция (иначе называемая еще окном обучения).

W(x) = A_{+}\exp{(-\frac{x}{\tau_{+}})} \qquad \text{для} \quad x > 0» src=«https://habrastorage.org/getpro/habr/upload_files/9ce/ed9/ffd/9ceed9ffd605e3975719a03d3142adc3.svg» /><img alt=

Параметры A_{+} и A_{-} могут зависеть от текущего значения синаптического веса \omega_{\alpha \beta} . Временные константы \tau_{+} и \tau_{-} имеют порядок 10 миллисекунд. Ну и заметим, что всё это обретает смысл, если мы дополнительно оговоримся, что A_{+} и A_{-} неотрицательны, а \tau_{+} и \tau_{-} положительны.

— Такая вот формула. Что мы из неё видим?

— Мы видим, во-первых, что эффект от генерации пары спайков тем меньше, чем дальше во времени отстоит второй спайк от первого. Там везде экспонента с отрицательным показателем, пропорциональным длительности промежутка времени между спайками. Во-вторых, мы видим, что слагаемые от пары «сначала пре, потом пост» входят в сумму со знаком плюс, а слагаемые от пары «сначала пост, потом пре» входят со знаком минус.

— То есть это (пока) ещё далеко не формула, которую можно было бы уже напрямую имплементировать в коде, слишком много вопросов про всякие детали реализации возникнет, ответов на которые в этой формуле нет. Это скорее переформулировка принципов STDP на несколько другом языке. То есть, что нам хочет сказать эта формула? Три вещи: первое — эффект от спайка, каким бы он ни был, убывает со временем (экспоненциально, хотя это, на самом деле, не так уж принципиально); второе — пресинаптический спайк перед постсинаптическим — это хорошо; третье — постсинаптический спайк перед пресинаптическим — это плохо. Всё.

— Но уже теплее. Значительно теплее!

Дифференциальные уравнения

— Ты заметил, что в формуле из предыдущего параграфа чего-то не хватает? Чего?

— В ней не хватает жизни! Динамики. В ней нет зависимости от времени. В ней всё статично: моменты спайков статичны, промежутки времени между спайками статичны, суммирование статично. Там всё замерло и умерло.

— Отлично! Покинем же область мёртвой, статичной арифметики и окунемся в бурлящее, живое море дифференциальных уравнений. Вот тебе первое… Хотя, нет, стоп, давай сначала разберёмся, что такое, собственно спайк?

— Ну… Сигнал…, импульс…, потенциал…, кислотность…, что там еще может быть? Нет. Ерунда всё это, по барабану. Для нас спайк — это функция времени. Так? То есть, некоторая (скалярная, хотя, это тоже не важно) величина, которая меняется с течением времени по некоторому закону.

— И как мы будем задавать эту величину и закон изменения её во времени?

— Конечно, как решение некоторого дифференциального уравнения. Так?

— Вот тут, как это ни печально, нет… Увы. Классики теории импульсных нейронных сетей предлагают нам считать спайк неким одномоментным актом, лишённым, так сказать, телесности, протяжённости пространственной и временной. И, говорят, есть подходящая математическая абстракция для описания подобных сущностей — дельта-функция Дирака.

— Я чувствую, как с твёрдой почвы обыкновенных дифференциальных уравнений, ты пытаешься увести меня в зыбкие трясины функционального анализа и теории обобщённых функций.

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

Итак, обозначим через x(t) не сам спайк пресинаптического нейрона, а некоторую функцию времени, которую мы будем называть следом спайка (в данном случае, пресинаптического нейрона). То есть каждый спайк, после того, как он случился, оставляет в нашей системе след. Как метеор в ночном небе. И как след метеора в ночном небе меркнет со временем, так же и след спайка будет меркнуть в нашей системе, по некоторому закону. По какому? Сейчас выясним. Для этого мы будем искать x(t) как решение дифференциального уравнения

\tau_{+}\frac{dx(t)}{dt} = -x(t) + a_{+}[x(t)]\sum_i\delta(t - t_i)

где i = 1, 2, \dots — номера спайков, а t_i — моменты генерации спайков.

Аналогично, обозначим через y(t) след спайка (спайков) постсинаптического нейрона, и будем искать его как решение уравнения

\tau_{-}\frac{dy(t)}{dt} = -y(t) + a_{-}[y(t)]\sum_i\delta(t - t_j)

— Ну что скажешь?

— Слушай, это же какой-то адок…

— Да. Я стараюсь, по-возможности, обойтись без отсебятины, поэтому уравнения даю в том виде, в каком они приведены в статьях, на которые ссылаются разработчики Lava-NC. У меня предложение, давай не будем впадать в истерику. Давай останемся максимально конструктивными. Мы же знаем, что уравнения для нейрофизиологов — это скорее такой метаязык для выражения концепций. И мы же догадываемся, что нам здесь хотят сказать. Поэтому давай поступим так: сначала слегка, да практически незаметно изменим эти уравнения

\tau_{+}\frac{dx(t)}{dt} = -x(t) + a_{+}\sum_i\delta(t - t_i)\tau_{-}\frac{dy(t)}{dt} = -y(t) + a_{-}\sum_i\delta(t - t_j)

а потом как бы решим их. Решения у нас получатся такие

x(t) = A_{+} \sum_i e^{-\frac{t-t_i}{\tau_{+}}}H(t-t_i)y(t) = A_{-} \sum_j e^{-\frac{t-t_j}{\tau_{-}}}H(t-t_j)

где A_{+} = \frac{a_{+}}{\tau_{+}}, A_{-} = \frac{a_{-}}{\tau_{-}}, а H(t) — функция Хевисайда. Понятно, как это выглядит: скачки «ступеньки» в моменты времени когда случается спайк, и экспоненциальное ниспадание между спайками. Но самое главное…

Это уже можно программировать

— Так давай этим и займёмся. Сначала установим и настроим Lava-NC фреймворк. Ставится не очень заморочно. Есть кое-какие огрехи, типа опечаток и т.п., но всё это достаточно легко преодолимо. Затем быстренько выполним все тьюториалы с первого по седьмой.

— Ты смеешься?

— Нет. Они все простые, технические, и помогают освоиться со средой, чтобы увереннее себя в ней чувствовать. Мы не будем тратить на это время. Ты вполне в состоянии сделать это самостоятельно. Мы лучше подробнее обсудим какие-то нюансы, которые показались мне нетривиальными. Все тьюториалы сделаны в виде Jupyter Notebook файлов, однако мне кажется, удобнее настроить, скажем, Visual Studio питоновский проект и перетаскивать код из тьюториалов туда. При этом потребуются кое-какие модификации исходников, но они простые и понятные.

Интересное начинается с восьмого тьюториала. Но обо всём по порядку. Мы бросили дифуры, несмотря на то, что как будто уже к успеху шли. Нам (мне) захотелось посмотреть на те самые спайковые следы пре и пост-нейронов воочию. Можно было и так нарисовать конечно, но зачем? Когда у нас есть среда, в которой мы всё это можем, и хотим, и будем моделировать. Давай же создадим пару нейронов и синапс, сгенерируем спайки и посмотрим, как там у ей внутре всё это вспыхывает и меркнет.

Тьюториал предлагает нам смоделировать вот такую систему

d6fd393625b2551224342386faebb833.png

Мы её собираем, запускаем 200 тактов моделирования и получаем вот такую картину

a97c1f468cb100ae07b4d8308580951d.png

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

Habrahabr.ru прочитано 3233 раза