renaming the protocol: NeuralElement -> Neural
[neural-net.git] / neural_net / core.clj
blobab449eafe5838fd89b6b1867ff32ef53d03f529f
1 (ns neural-net.core)
3 (defprotocol Neural
4   "Protocol implemented by any element of a neural network."
5   (spec    [this]   "Returns the specification -- useful for serialization")
6   (run     [this x] "Evaluates the net")
7   (learn   [this d] "Trains the net using d returning the updated net")
8   (inputs  [this]   "Number of inputs")
9   (outputs [this]   "Number of outputs"))
11 (extend-protocol
12  Neural
13  clojure.lang.IPersistentMap            ; a map initializes a single n
14  (spec    [this]   this)
15  (run     [this x] ((this :phi) ((this :accum)
16                                  (filter identity
17                                          (map (fn [x w] (when w (* x w)))
18                                               x (this :weights))))))
19  (learn   [this d] this)
20  (inputs  [this]   (count (this :weights)))
21  (outputs [this]   1)
22  clojure.lang.ISeq               ; a list of many ns in the same layer
23  (spec    [this]   (map spec this))
24  (run     [this x] (reduce (fn [x layer] (run layer x)) x this))
25  (learn   [this d] (reduce (fn [x layer] (run layer d)) d (reverse this)))
26  (inputs  [this]   (apply max (map inputs this)))
27  (outputs [this]   (reduce + (map outputs this)))
28  clojure.lang.IPersistentVector   ; a vector of ns in different layers
29  (spec    [this]   (vec (map spec this)))
30  (run     [this x] (reduce (fn [x layer] (run layer x)) x this))
31  (learn   [this d] (reduce (fn [x layer] (run layer d)) d (reverse this)))
32  (inputs  [this]   (inputs (first this)))
33  (outputs [this]   (outputs (last this)))
34  clojure.lang.IPersistentSet     ; arbitrary graphs, as a set of edges
35  (spec    [this]   {:vertices (set (map spec (set (apply concat this))))
36                     :edges    this})
37  (run     [this x]
38           (loop [edges this
39                  x (apply hash-map (apply concat (map-indexed #(vec %1 %2) x)))]
40             (if (empty? edges)
41               x
42               (recur
43                (filter (comp not (comp contains? (keys x)) first) edges)
44                (map (fn [edge]
45                       [(second edge) (run (second edge) (get x (first edge)))])
46                     (filter (comp (comp contains? (keys x)) first) edges))))))
47  (learn   [this d]
48           (loop [edges this
49                  d (apply hash-map (apply concat (map-indexed #(vec %1 %2) d)))]
50             (if (empty? edges)
51               d
52               (recur
53                (filter (comp not (comp contains? (keys d)) second) edges)
54                (map (fn [edge]
55                       [(first edge) (learn (first edge) (get d (second edge)))])
56                     (filter (comp (comp contains? (keys d)) second) edges))))))
57  (inputs  [this]   (count (set (filter (comp number? first) this))))
58  (outputs [this]   (count (set (filter (comp number? second) this)))))
60 ;;; example usage
61 (comment
62   ;; show the numbers of inputs and outputs of some networks
63   (let [n {:phi sigmoid :weights [1 2 1 4 1]}]
64     (outputs [n (list n n) n])          ; 1
65     (outputs (list n (list n n) n))     ; 4
66     (inputs [n (list n n) n])           ; 5
67     (inputs (list n (list n n) n)))     ; 3
68   ;; evaluate a simple neuron
69   (run {:phi identity
70         :accum (partial reduce +)
71         :weights [0.5 1]}
72        [1 0])                           ; 0.5
73   )