2010年6月7日月曜日

Multilayer perceptrons in Clojure - Part I (feed-forward)


(use 'clojure.contrib.pprint)

(defn rand-weight
"Return a random number r, where -1/sqrt(n) < r < 1/sqrt(n)"
[n]
(let [rand-weight-max (/ 1 (Math/sqrt n))]
(- (rand (* 2 rand-weight-max)) rand-weight-max)))

(defn create-layer
"Creates a single network layer with the specified number of units and inputs (+ one for the bias) to these units"
[inputs units]
(map
(fn [_] (map (fn [_] (rand-weight inputs)) (range (inc inputs))))
(range units)))

(defn create-network
"Creates a fully connected feed-forward neural network"
[& units-per-layer]
(map
(fn [[inputs units]] (create-layer inputs units))
(partition 2 1 units-per-layer)))

(defn feed-forward
"Feeds an input vector through the network layer by layer and returns the output vector"
[network input activations]
(reduce
(fn [previous-outputs [layer activation]]
(map
(fn [unit] (activation (reduce + (map * (cons 1 previous-outputs) unit)))) ; (cons 1) adds the bias
layer))
input
(map list network activations)))

(def binary-inputs [[0 0] [0 1] [1 0] [1 1]])

(def or-targets [[0] [1] [1] [1]])
(def and-targets [[0] [0] [0] [1]])
(def xor-targets [[0] [1] [1] [0]])

(defn create-sigmoid
[beta]
(fn [x] (/ 1 (+ 1 (Math/exp (* (- beta) x))))))

(defn create-sigmoid-prime
[beta]
(let [sigmoid (create-sigmoid beta)]
(fn [x] (let [sigmoid-x (sigmoid x)] (* beta (- 1 sigmoid-x) sigmoid-x)))))

(defn step-function
[x]
(if (> x 0) 1 0))

(def an-and-perceptron '(((-3 2 2))))
(def an-or-perceptron '(((-1 2 2))))
(def a-zero-perceptron '(((0 0 0))))

(feed-forward (create-network 2 1) [0 1] [step-function])

(do (prn) (pprint (map #(let [[t] %2 [y] (feed-forward an-and-perceptron %1 [step-function])] {:output y :target t :diff (- y t)}) binary-inputs and-targets)))

0 件のコメント:

コメントを投稿

フォロワー