2009/02/21

[Common Lisp][ニューラルネットワーク] 単純なニューラルネットワーク

『脳 回路網のなかの精神』を読んだ。

おもしろい。ニューラルネットワークで遊んでみたくなった。まずはしめは、この本にも出てくる3つの入力と3つの出力からなる単純なネットワークを作ってみる。

重みづけを学習するのは次のステップとして、今回は期待する出力が得らるれまで、ランダムで重みづけをしながらネットワーク作成する。

#|
パターン1
● ●
○ -> ○
● ○

パターン2
● ○
● -> ●
● ○

パターン3
○ ○
● -> ○
○ ●
|#

(defclass value-mixin ()
((value :initarg :value :initform nil :accessor value-of)))

(defclass name-mixin ()
((name :initarg :name :initform "unknown" :accessor name-of)))

(defclass 2layer-network ()
((input :initarg :input :initform nil :accessor input-of)
(output :initarg :ouput :initform nil :accessor output-of)))

(defclass connection ()
((from :initarg :from :accessor from-of)
(to :initarg :to :accessor to-of)
(weight :initarg :weight :accessor weight-of)))

(defclass neuron (value-mixin name-mixin)
((connections :initarg :connections :initform nil :accessor connections-of))
(:default-initargs :value 0.0))

(defmethod print-object ((x connection) stream)
(print-unreadable-object (x stream)
(format stream "~a *~d ~a" (name-of (from-of x)) (weight-of x)
(name-of (to-of x)))))

(defmethod print-object ((x neuron) stream)
(print-unreadable-object (x stream)
(mapc (lambda (connection) (print-object connection stream))
(connections-of x))))

(defmethod fire ((neuron neuron))
(mapc #'fire (connections-of neuron)))

(defmethod fire ((connection connection))
(fired (to-of connection) (weight-of connection)))

(defmethod fired ((neuron neuron) weight)
(incf (value-of neuron) weight))

(defmethod fire-p ((neuron neuron))
(prog1 (< 0.8 (value-of neuron))
(setf (value-of neuron) 0.0)))

(defun init-random-weight ()
(1- (random 2.0)))

(defmethod connect ((from neuron) (to neuron)
&optional (weight (init-random-weight)))
(let ((connection
(make-instance 'connection :from from :to to :weight weight)))
(push connection (connections-of from))))

(defmacro with-2layer-network ((inputs outputs) &body body)
`(let ,(mapcar (lambda (x) `(,x (make-instance 'neuron :name ',x)))
(append inputs outputs))
(loop for i in (list ,@inputs)
do (loop for j in (list ,@outputs)
do (connect i j)))
,@body))

(defun main ()
(loop
until (with-2layer-network ((a b c) (x y z))
(let* ((r1 (progn (mapc #'fire (list a c))
(list (fire-p x) (fire-p y) (fire-p z))))
(r2 (progn (mapc #'fire (list a b c))
(list (fire-p x) (fire-p y) (fire-p z))))
(r3 (progn (mapc #'fire (list b))
(list (fire-p x) (fire-p y) (fire-p z)))))
(and (equal r1 '(t nil nil))
(equal r2 '(nil t nil))
(equal r3 '(nil nil t))
(print (list r1 r2 r3))
(print (list a b c)))))))

0 件のコメント: