#| 1. Need to map from attribute vector to Euclidean vector (both input & output) Used when converting the training data to numerical form, which is done once at initialization. Also used when running the net on a test input. If 3 or more mutually exclusive attribute values, each one gets a separate unit. If 2, use one unit. If less than 2, ignore. 2. Need to map from Euclidean vector to attribute vector (output only) Used when running the net on a test input. In this case, each attribute should yield a list of elements of the form (value score). If only one unit used, 2 possibilites: (a) direct numerical interpretation, so corresponding attribute just gets properly scaled numerical value; (b) 2 mutually exclusive values, so attribute should look like ((other-value, (- 1 score)) (value score)). |# (defvar *nbr-inputs*) ;includes bias input (defvar *nbr-outputs*) (defvar *input-semantics*) (defvar *output-semantics*) ;;;; User-level procedure (defun show-neural-net-representation () (show-nnet-semantics 'input) (show-nnet-semantics 'output)) ;;;; Auxiliary procedures (defun convert-data-to-nnet-form () ;returns list of Euclidean vector pairs (setq *nbr-inputs* (1+ (reduce #'+ (mapcar #'allocate-units *input-ranges*)))) (setq *nbr-outputs* (reduce #'+ (mapcar #'allocate-units *output-ranges*))) (setq *input-semantics* (nnet-att-val-pairs *input-ranges*)) (setq *output-semantics* (nnet-att-val-pairs *output-ranges*)) (mapcar #'list (mapcar #'convert-input-to-euclid-vec (mapcar #'first *training-data*)) (mapcar #'convert-output-to-euclid-vec (mapcar #'second *training-data*)))) (defun convert-input-to-euclid-vec (input-att-vec) ; attaches bias line at end (append (convert-att-vec-to-euclid-vec input-att-vec *input-ranges*) (list 1))) (defun convert-output-to-euclid-vec (output-att-vec) (convert-att-vec-to-euclid-vec output-att-vec *output-ranges*)) (defun convert-output-to-att-vec (output-euclid-vec) (convert-euclid-vec-to-att-vec output-euclid-vec *output-ranges*)) (defun convert-input-to-att-vec (input-euclid-vec) (convert-euclid-vec-to-att-vec (butlast input-euclid-vec) *input-ranges*)) (defun convert-euclid-vec-to-att-vec (euclid-vec ranges) (let ((result nil) (vec-tail euclid-vec) ) (dolist (spec ranges (reverse result)) (if (num-range-spec-p spec) (progn (push (unscale-from-0-1 (car vec-tail) spec) result) (setq vec-tail (cdr vec-tail))) (let ((n (allocate-units spec)) (list-of-nums nil)) (if (< n 2) (push (- 1 (car vec-tail)) list-of-nums)) (dotimes (i n) (push (car vec-tail) list-of-nums) (setq vec-tail (cdr vec-tail))) (push (mapcar #'list spec (reverse list-of-nums)) result) ))))) (defun convert-att-vec-to-euclid-vec (att-vec range-specs) (reduce #'append (mapcar #'euclid-vec att-vec range-specs))) (defun euclid-vec (value value-list) (let* ((n (allocate-units value-list)) (vec (make-list n :initial-element 0)) (invalid-value nil)) (cond ((> n 2) (let ((p (position value value-list))) (if p (setf (nth p vec) 1) (setq invalid-value t)))) ((num-range-spec-p value-list) (let ((scaled-val (scale-to-0-1 value value-list))) (if (<= 0 scaled-val 1) (setf (car vec) scaled-val) (setq invalid-value t)))) ((eql value (second value-list)) (setf (car vec) 1)) ((not (eql value (first value-list))) (setq invalid-value t)) ) (if invalid-value (format t "~%Ignoring invalid value ~a" value)) vec )) (defun allocate-units (value-list) (let ((nbr-values (length value-list))) (cond ((< nbr-values 2) 0) ((= nbr-values 2) 1) (t nbr-values) ))) (defun nnet-att-val-pairs (list-of-value-lists) (let ((att-num -1)) (reduce #'append (mapcar #'(lambda (value-list) (nnet-att-val-pairs-for-att (incf att-num) value-list)) list-of-value-lists)))) (defun nnet-att-val-pairs-for-att (att-num value-list) (mapcar #'(lambda (v) (list att-num v)) (if (> (length value-list) 2) value-list (cdr value-list)))) (defun dot-prod (seq1 seq2) (reduce #'+ (map 'list #'* seq1 seq2))) (defun show-layer (name vector &optional format-string) (format t name) (show-vector vector format-string) (format t "~%")) (defun show-vector (vector &optional format-string) (map nil #'(lambda (x) (format t (cond (format-string) ((typep x 'float) "5,2f") (t " ~a")) x)) vector)) (defun show-nnet-semantics (type) (if (eql type 'input) (format t "~%Input:~%") (format t "~%Output:~%")) (format t "~%Unit Attribute Value") (format t "~%---- --------- -----") (let ((unit -1)) (dolist (s (if (eql type 'input) *input-semantics* *output-semantics*)) (format t "~%~3d~10,0t~2d~20,0t~a" (incf unit) (first s) (second s))) (if (eql type 'input) (format t "~%~3d Bias Unit~%" (incf unit)) (format t "~%~%"))) (values))