nekomata / moe /sparse-activate.lisp
SNAPKITTYWEST's picture
push from SNAPKITTYWEST/nekomata
3b70664 verified
Raw History Blame Contribute Delete
1.73 kB
(in-package #:nekod.moe)
;; Sparse activation with noise injection (Noisy Top-K Gating)
;; Adds Gaussian noise during training to improve expert utilization
(defun gaussian-noise (mean stddev)
"Box-Muller transform for Gaussian random number."
(let* ((u1 (+ 1e-10 (random 1.0d0)))
(u2 (random 1.0d0))
(z (* (sqrt (* -2.0d0 (log u1))) (cos (* 2.0d0 pi u2)))))
(+ mean (* stddev z))))
(defun noisy-top-k (router h &optional (noise-stddev 0.1d0) (training t))
"Top-K gating with noise for training. In inference mode: no noise."
(let* ((scores (all-scores router h))
(noisy-scores
(if training
(mapcar (lambda (s)
(cons (car s)
(+ (cdr s) (gaussian-noise 0.0d0 noise-stddev))))
scores)
scores))
(sorted (sort noisy-scores #'> :key #'cdr))
(selected (subseq sorted 0 (min (router-k router) (length sorted)))))
(softmax-over-selected selected)))
;; Load balancing — prevent expert collapse
(defun load-balance-loss (router activations)
"Auxiliary loss to prevent all traffic going to one expert.
Returns scalar loss value — lower is more balanced."
(let* ((n (length (router-expert-names router)))
(counts (make-array n :initial-element 0)))
(dolist (act activations)
(let ((idx (position (car act) (router-expert-names router))))
(when idx (incf (aref counts idx)))))
(let ((total (reduce #'+ counts)))
(if (zerop total) 0.0d0
(loop for c across counts
sum (let ((p (/ c total)))
(if (zerop p) 0.0d0 (* p (log p)))))))))