Skip to content

Instantly share code, notes, and snippets.

@m0a0t0
Last active December 13, 2015 21:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m0a0t0/4976438 to your computer and use it in GitHub Desktop.
Save m0a0t0/4976438 to your computer and use it in GitHub Desktop.
An implementation of artificial neural network and back-propagation in Clojure.
(ns ann.core)
; usage:
; (train-many (generate-neural-network 2 3 1) [[0 0] [1 1] [1 0] [0 1]] [[0] [0] [1] [1]] 0.1 900000)
; for XOR
(defn sum
[col]
(reduce + col))
(defn sigmoid
[x]
(/ 1 (+ 1 (Math/exp (- x)))))
(defn generate-layer
[weights? n-neurons n-neurons-next]
(vec
(for [i (range n-neurons)]
(let [m (-> {} (assoc :activation -1))]
(if weights?
(assoc m :weights (vec (map (fn [x] (rand)) (replicate n-neurons-next 0))))
m)))))
(defn generate-network
[n-inputs n-hidden n-outputs]
(->
{}
(assoc :inputs (generate-layer true n-inputs n-hidden))
(#(assoc % :inputs (conj (:inputs %) {:weights (vec (map (fn [x] (rand)) (replicate n-hidden 0))) :activation 1})))
(assoc :hidden (generate-layer true n-hidden n-outputs))
(assoc :outputs (generate-layer false n-outputs 0))))
(defn activate-inputs
[neural-network inputs]
(let [new-inputs
(vec (for [i (range (count inputs))]
(assoc (get (:inputs neural-network) i) :activation (get inputs i))))]
(assoc neural-network :inputs (conj new-inputs (last (:inputs neural-network))))))
(defn activate-layer
[neural-network layer-index previous-layer-index]
(assoc neural-network layer-index
(let [layer (get neural-network layer-index)
previous-layer (get neural-network previous-layer-index)]
(vec (for [i (range (count layer))]
(assoc (get layer i) :activation
(sigmoid (sum (for [neuron previous-layer] (* (:activation neuron) (get (:weights neuron) i)))))))))))
(defn forward-pass
[neural-network inputs]
(->
(activate-inputs neural-network inputs)
(activate-layer :hidden :inputs)
(activate-layer :outputs :hidden)))
(defn calculate-output-deltas
[neural-network expected]
(loop [i 0
neural-net neural-network]
(if (< i (count (:outputs neural-network)))
(let [activation (get-in neural-net [:outputs i :activation])
target (get expected i)
delta (* activation (- 1 activation) (- target activation))]
(recur (inc i) (assoc-in neural-net [:outputs i :delta] delta)))
neural-net)))
(defn calculate-layer-deltas
[neural-network layer-index next-layer-index]
(let [layer (get neural-network layer-index)
next-layer (get neural-network next-layer-index)]
(loop [neuron 0
net neural-network]
(if (< neuron (count layer))
(let [s (sum
(for [next-neuron (range (count next-layer))]
(* (:delta (get next-layer next-neuron)) (get (:weights (get layer neuron)) next-neuron))))
a (get-in layer [neuron :activation])
v (* a (- 1 a) s)]
(recur (inc neuron) (assoc-in net [layer-index neuron :delta] v)))
net))))
(defn calculate-deltas
[neural-network expected]
(->
(calculate-output-deltas neural-network expected)
(calculate-layer-deltas :hidden :outputs)
(calculate-layer-deltas :inputs :hidden)))
(defn train-layer
[neural-network layer-index next-layer-index rate]
(let [layer (get neural-network layer-index)
next-layer (get neural-network next-layer-index)]
(loop [neuron 0
net neural-network]
(if (< neuron (count layer))
(recur (inc neuron) (loop [next-neuron 0
net-1 net]
(if (< next-neuron (count next-layer))
(let [change (* (get-in next-layer [next-neuron :delta]) (get-in layer [neuron :activation]))
weight (+ (get-in layer [neuron :weights next-neuron]) (* rate change))]
(recur (inc next-neuron) (assoc-in net-1 [layer-index neuron :weights next-neuron] weight)))
net-1)))
net))))
(defn train
[neural-network rate]
(->
neural-network
(train-layer :hidden :outputs rate)
(train-layer :inputs :hidden rate)))
(defn train-with-data
[neural-net inputs expected rate]
(->
neural-net
(forward-pass inputs)
(calculate-deltas expected)
(train rate)))
(defn train-many
[neural-net inputs expected rate iterations]
(loop [data-index 0
i 0
net neural-net]
(if (>= i iterations)
net
(if (< data-index (count inputs))
(recur (inc data-index) (inc i) (train-with-data net (get inputs data-index) (get expected data-index) rate))
(recur 0 i net)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment