Hi David,
Those two are not recursive, but they call into other recursive
functions. Do I need to make sure all recursive functions use the loop/
recur pattern? Or maybe not nest recursive calls like this?
Here is the whole source:
;threshold
(defn threshold [x] (if (>= x 0) 1 0))
;signum (threshold)
(defn signum [x] (cond (> x 0) 1 (= x 0) 0 (< x 0) -1))
;piecewise linear
(defn piecewise [x] (cond (>= x 0.5) 1 (and (> x -0.5) (< x 0.5)) x
(<= x -0.5) 0))
;logistic (sigmoidal)
(defn sigmoid [x slopeParameter] (/ 1 (+ 1 (Math/exp (* -1 (* x
slopeParameter))))))
;hyberbolic tangent (sigmoidal)
(defn hyperbolicTangent [x] (Math/tanh x))
;arctangent (sigmoidal)
(defn arcTangent [x] (Math/atan x))
;gompertz curve (sigmoidal)
; a is the upper asymptote
; c is the growth rate
; b, c are negative numbers
(defn gompertzCurve [x a b c] (* a (Math/pow Math/E (* b (Math/pow
Math/E (* c x))))))
;algebraic sigmoid
(defn algebraicSigmoid [x] (/ x (Math/sqrt (+ 1 (Math/pow x 2)))))
;; Matrix Functions
(defn transpose [matrix]
(if (not (nil? matrix))
(apply map list matrix)))
(defn transpose2 [matrix]
(apply map (fn [& column] column) matrix))
(defn matrixMultiply [matrixA matrixB]
(map
(fn [row] (apply map (fn [& column] (apply + (map * row column)))
matrixB))
matrixA))
(defn matrixAdd [matrixA matrixB]
(if (and (not (empty? matrixA)) (not (empty? matrixB)))
(conj
(matrixAdd (rest matrixA) (rest matrixB))
(map + (first matrixA) (first matrixB)))))
(defn matrixMultiplyScalar [matrixA scalar]
(if (not (empty? matrixA))
(conj
(matrixMultiplyScalar (rest matrixA) scalar)
(map (fn [arg] (* arg scalar)) (first matrixA)))))
;; Vector Functions
(defn transposeVector [v]
(if (not (nil? v))
(transpose (vector v))))
(defn vectorMultiplyScalar [v scalar]
(map * v (cycle [ scalar ])))
;; Binary Logic Input/Output
(def infiniteInputCollection (cycle [[[-1 -1]] [[-1 1]] [[1 -1]] [[1
1]]]))
(def infiniteAndOutputCollection (cycle [-1 -1 -1 1]))
(defn buildInputs [numberOfInputs]
(loop [inputVector []
binaryInputCollection infiniteInputCollection
remainingCount numberOfInputs]
(if (> 0 remainingCount)
inputVector
(recur
(conj inputVector (first binaryInputCollection)) (rest
binaryInputCollection) (dec remainingCount)))))
(defn buildOutputs [numberOfOutputs outputCollection]
(loop [outputVector []
andOutputCollection outputCollection
remainingCount numberOfOutputs]
(if (> 0 remainingCount)
outputVector
(recur (conj outputVector (first andOutputCollection))
(rest andOutputCollection) (dec remainingCount)))))
;; Main
;learning rate parameter eta
(def learningRateParameter 0.5)
;the weight vector of the perceptron
(def weightVector (ref nil))
;multiply the transpose of the weight vector with the input vector
;apply the signum function to the scalar result
(defn computeActualResponse [signumFunction weights inputs]
(if (and (not (nil? weights)) (not (nil? inputs)))
;;TODO create a function that will apply first to a collection
until the inner item is obtained
(signumFunction (first (first (matrixMultiply (transpose
weights) inputs))))))
(defn computeActualResponse2 [signumFunction weights inputs]
;;(if (and (not (nil? weights)) (not (nil? inputs)))
;;(signumFunction (first (first (matrixMultiply (transpose
weights) inputs))))))
4)
;return an updated weight vector of the perceptron
(defn getAdaptedWeightVector [weights inputs desiredResponse
actualResponse]
(let [etaDeltaDesiredActual (* learningRateParameter (-
desiredResponse actualResponse))]
(matrixAdd weights (matrixMultiplyScalar inputs
etaDeltaDesiredActual))))
;;(dosync (ref-set weightVector newWeights))))
(defn getAdaptedWeightVector2 [weights inputs desiredResponse
actualResponse]
(let [etaDeltaDesiredActual (* learningRateParameter (-
desiredResponse actualResponse))
scaledResponses (matrixMultiplyScalar inputs
etaDeltaDesiredActual)]
(matrixAdd weights [[0 0]])))
;train the perceptron with the inputs and corresponding known outputs
(defn trainPerceptron [beginningWeightVector allInputs allOutputs]
(loop [weightVector beginningWeightVector
inputs allInputs
responses allOutputs]
(if (and (not (empty? inputs)) (not (empty? responses)))
(let [adaptedWeightVector
(getAdaptedWeightVector
weightVector
(first inputs)
(first responses)
(computeActualResponse signum weightVector (first
inputs)))]
(recur adaptedWeightVector (rest inputs) (rest
responses)))
weightVector)))
(defn trainPerceptron2 [beginningWeightVector allInputs allOutputs]
(loop [inputs allInputs
responses allOutputs]
(if (or (empty? inputs) (empty? responses))
(deref weightVector)
bv(dosync (ref-set weightVector (matrixAdd (deref
weightVector) (deref weightVector))))
(recur (rest inputs) (rest responses)))))
(defn main [sizeOfDataSet]
(let [weights [[0 0]]
inputs (buildInputs sizeOfDataSet)
outputs (buildOutputs sizeOfDataSet
infiniteAndOutputCollection)]
(trainPerceptron weights inputs outputs)))
(defn main-test [sizeOfDataSet]
(let [weights [[0 0]]
inputs (buildInputs sizeOfDataSet)
outputs (buildOutputs sizeOfDataSet
infiniteAndOutputCollection)]
(trainPerceptron2 weights inputs outputs)))
On Apr 20, 6:32 am, David Nolen <[email protected]> wrote:
> You have two other function calls
> getAdaptedWeightVector
> computeActualResponse
>
> Are these recursive as well?
>
> On Sun, Apr 19, 2009 at 11:26 PM, jleehurt <[email protected]> wrote:
>
> > Hi all, I have the following code that trains a perceptron with the
> > given inputs and corresponding desired inputs. For input/output
> > vectors, when the size gets to about 2000, I am getting a
> > java.lang.StackOverflowError in the following function:
>
> > (defn trainPerceptron [beginningWeightVector allInputs allOutputs]
> > (loop [weightVector beginningWeightVector
> > inputs allInputs
> > responses allOutputs]
> > (if (and (not (empty? inputs)) (not (empty? responses)))
> > (let [adaptedWeightVector
> > (getAdaptedWeightVector
> > weightVector
> > (first inputs)
> > (first responses)
> > (computeActualResponse signum weightVector (first
> > inputs)))]
> > (recur adaptedWeightVector (rest inputs) (rest
> > responses)))
> > weightVector)))
>
> > Is not the purpose of loop/recur to avoid stack overflow problems?
> > What am I doing wrong?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---