nflow v0.2.0

топ 100 блогов love5an30.01.2011 Полностью переработал модель распространения данных в neural-flow 
Не без помощи nflow v0.2.0 [info]dmitry_vk  в lisp@c.j.r, надо сказать.

Библиотека стала больше походить на cells. Но, её интерфейс и dataflow-модель - намного проще и удобнее в использовании.

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

Что значит "автоматически"? Это значит, что, в отличие от предыдущей версии, теперь не нужно руками делать add-connection и remove-connection. Нейрон сам вычислит, с кем он связан и соответствующим образом распространяет поток данных.

Что значит "динамически"? Это значит, что связи между нейронами создаются и изменяются во время выполнения программы, на основе взаимодействия нейронов, а не на основе каких-либо статически заданных формул. Короче, как и у настоящих нейронов.
А связи между настоящими нейронами зависят от множества факторов - от расположения нейрона, от количества алкоголя в крови, да и даже от фазы луны.

Кстати, о фазе луны. Вот сразу  пример :)

(defparameter *input* (neuron ()
nil))

(defparameter *first* (neuron ()
(neuron-value *input*)
:first))

(defparameter *second* (neuron ()
(neuron-value *input*)
:second))

(defparameter *output* (neuron ()
(if (evenp (floor (get-universal-time) ;;количество секунд с 1 января 1900 года
(* 60 60 24 29.5 1/2))) ;;количество секунд в лунном полуцикле
(neuron-value *second*)
(neuron-value *first*))))

(defun query-lunar-phase ()
(update-neuron *input*)
(neuron-value *output*))

В первую половину лунного цикла нейрон *output* будет узнавать значение лунной фазы из нейрона *first*, а во вторую половину - из *second*. Ну, довольно очевидно, что на сегодняшний день он будет хранить значение :second :)

Макрос neuron это просто удобная форма записи (make-instance 'neuron ...)
Выглядит он так:

(defmacro neuron ((&optional (neuron-class 'neuron) (value-var (gensym)) &rest args)
&body body)
(check-type value-var symbol)
`(make-instance ',neuron-class
:function (lambda (,value-var) (declare (ignorable ,value-var)) ,@body)
,@args))
Таким образом, что каждый нейрон представляет собой функтор, являющийся звеном в некоторой цепочке вычислений.

Как видно, в функции query-lunar-phase мы не указываем явно, что нам нужно обновить именно нейрон *output*, который собственно и вычисляет фазу луны. Напротив, мы обновляем только нейрон *input*. И тем не менее, поток данных проходит весь путь от *input* к *output*.

Как это достигается? Очень просто - вызов функции neuron-value записывает нейрон, из которого мы эту функцию вызываем, в список зависимостей нейрона, к которому мы обращаемся.

(defun neuron-value (neuron)
(declare (type neuron neuron))
(when *current-neuron*
(pushnew *current-neuron* (slot-value neuron '%dependents) :test #'eq))
(slot-value neuron '%value))
Сама же функция-обработчик-данных нейрона, вызывается, среди прочего, при его создании.

Таким образом, связи между нейронами зависят исключительно от того, куда нейрон дотягивается "дендритами" во время выполнения программы. Для вышеописанного примера, на сегодняшнее число, связи будут выглядеть так:
нейроны
Прослеживается аналогия с монадами - нейрон, как и монада, это некое звено в цепочке вычислений. Отличие в том, что функция нейрона выполняет роли как bind, так и return; впрочем, я думаю позже ввести "синапсы"  - обобщенные функции, которые бы обрабатывали значение, полученное из нейрона, и значение, возвращаемое самим функтором. 

Важное отличие от традиционного FRP(functional reactive programming) состоит в том, что в моей библиотеке используется data-driven(push-based, eager) модель, в противоположность demand-driven(pull-based, lazy) моделям, которые обычно используются в FRP-фреймворках.

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

Напоследок, еще один пример:

;;В объектах классов, являющихся экземплярами метакласса dataflow-class
;; все слоты являются нейронами
;; При этом, мы можем продолжать с ними работать как с обычными слотами.
(defclass textbox (dataflow-object)
((text :initform "" :accessor textbox-text))
(:metaclass dataflow-class))

(defclass checkbox (dataflow-object)
((checked :initform nil :accessor checkbox-checked))
(:metaclass dataflow-class))

(defun event-example ()
(let* ((textbox (make-instance 'textbox))
(checkbox (make-instance 'checkbox)))
;;bindf это обобщенная функция, устанавливающая нейрону или слоту(как здесь)
;; новую функцию-обработчик, или же устанавливающая слоту новый нейрон.
(bindf (lambda (old-value)
(declare (ignore old-value))
(if (checkbox-checked checkbox)
"Checked"
"Unchecked"))
textbox
:slot 'text)
;;просто некий нейрон, который будет нас оповещать об изменениях
;; слота text у textbox'а
(let ((observer (neuron ()
(format t "Text changed. New value: ~s"
(textbox-text textbox)))))
(declare (ignorable observer))
checkbox)))


;;При изменении слота checked, слот textbox'a также будет изменяться -
;; устанавливаться в "Checked" или "Unchecked" соответственно.
;; А при изменении самого слота text, этим, или
;; другим способом(например через (setf slot-value)),
;; об изменении нас будет оповещать нейрон observer

Оставить комментарий

Архив записей в блогах:
Попробуйте угадать гражданство автора поста: ПыСы подобным говном забита вся лента в Одноклассниках((( ...
Было это в старших классах, девяносто какой-то год. Как раз мода пошла на психологическое обследование детей, и к нам в лицей прислали специалиста. Специалист сначала диктовала тесты из тетрадки, и я выяснила, что единственный для меня способ ...
Что лучше, разгребать ямы с дерьмом за 10 тысяч рублей, работать в пятерочке сторожем за 15 или гонять креаклов за 20? --------------------------------------------- Вытер соплю (в прямом смысле) и пафосно сообщил - "Мне нравится, что живу спокойно в стране, что нет конфликтов, что я ...
На Хабре лежит полезная статья про переезд внутри ЕС, если уже есть на руках "Голубая карта" для высококвалифицированного специалиста - https://habr.com/ru/articles/940192/ . Ребята переезжали из Болгарии в Германию, с двумя собаками. Почему Германия? Да, в ЕС есть страны, где платят ...
...