initial som gui code (can draw a moving map of neurons w/2D weights)
[neural-net.git] / src / neural_net / som.clj
bloba5a7c45832b7d4c6e9a49eb013f595c56dae3e97
1 (ns neural-net.som                      ; Kohonen maps
2   (:use neural-net.core)
3   (:use clojure.set))
5 (defn self-organizing-map:run
6   "Return a map of the dot product of each neurons weight against x" [this x]
7   (reduce (fn [a [k v]] (cons [k (reduce + (map * x (v :weights)))] a))
8           [] (get (this :map) :vertices)))
10 (defn self-organizing-map:learn
11   "Return a map of learning spread through the map." [this x y d]
12   (let [verts (map first (reverse (sort-by second y)))]
13     (loop [ns [(first verts)] rem (set (rest verts)) dist 0 out {}]
14       (if (empty? ns)
15         out
16         (let [m (filter (partial contains? rem) (mapcat (partial neighbors (this :map)) ns))]
17           (recur m (difference rem (set m)) (inc dist)
18                  (reduce (fn [a n] (assoc a n ((this :update) this dist n x)))
19                          out ns)))))))
21 (defn self-organizing-map:train [this delta]
22   (assoc this
23     :map (neural-net.core.Graph.
24           (reduce (fn [a [k d]] (assoc a
25                                  k {:weights (map + d ((get a k) :weights))}))
26                   (get (this :map) :vertices) delta)
27           (get (this :map) :edges))))
29 (comment                                ; train a self organizing map
30   (let [som {:phi self-organizing-map:run
31              :learn self-organizing-map:learn
32              :train self-organizing-map:train
33              :eta 1
34              :update (fn [this dist n x]
35                        (map (fn [x] (* (/ x (inc dist)) (this :eta)))
36                             (map -
37                                  x (((get (this :map) :vertices) n) :weights))))
38              :map (neural-net.core.Graph.
39                    {:a {:weights [ 1  0]}
40                     :b {:weights [ 0  1]}
41                     :c {:weights [-1  0]}
42                     :d {:weights [ 0 -1]}}
43                    [[:a :b] [:b :c] [:c :d]])}]
44     (first (train som [0.8 0.2] nil nil)))
45   ;; =>
46   ;; {:d (0.2 0.3),  :c (0.6 0.06666666666666667),
47   ;;  :b (0.4 -0.4), :a (-0.19999999999999996 0.2)}  
48   )