Hi Dimiter, Thank you! I'm still a bit confused as to why this was happening. Does lazy evaluation not work well with recursion?
On Apr 20, 11:06 pm, "Dimiter \"malkia\" Stanev" <mal...@gmail.com> wrote: > I blindly tried printing out stuff from matrixMultiply, and found out > that if I print matrixA and matrixB it doesn't run out of stack, so I > guess I was "forcing" them to "work", here is a version with (dorun) > that has the same side effect, without printing: > > (defn matrixMultiply [matrixA matrixB] > (dorun matrixA) > (dorun matrixB) > (map > (fn [row] > (apply map > (fn [& column] > (apply + (map * row column))) > matrixB)) > matrixA)) > > user> (main 100000) > ((0.5 50000.5)) > user> (main 1000000) > ((0.5 500000.5)) > user> (time (main 1000000)) > "Elapsed time: 8314.617 msecs" > ((0.5 500000.5)) > user> (time (main 10000000)) > ; Evaluation aborted. ;; Actually not stack overflow, but HEAP > overflow (it took a while though) > user> > > Thanks, > Dimiter "malkia" Stanev. > > On Apr 20, 10:01 pm, jleehurt <jleeh...@gmail.com> wrote: > > > Hi David, > > > Those two are not recursive, but they call into other functions that > > are. Do I need to make sure that all recursive functions use the loop/ > > recur pattern? Or should I not nest recursive calls like this? > > > Here is the whole source: > > > ;; Neuron Activation Functions > > > ;threshold > > (defn threshold [x] (if (>= x 0) 1 0)) > > > ;signum (threshold) > > (defn signum [x] (cond (> x 0) 1 (= x 0) 0 (< x 0) -1)) > > > ;; 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))) > > (signumFunction (first (first (matrixMultiply (transpose > > weights) inputs)))))) > > > ;return an updated weight vector of the perceptron > > (defn getAdaptedWeightVector [weights inputs desiredResponse > > actualResponse] > > (let [etaDeltaDesiredActual (* learningRateParameter (- > > desiredResponse actualResponse))] > > (matrixAdd weights (matrixMultiplyScalar inputs > > etaDeltaDesiredActual)))) > > > ;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 main [sizeOfDataSet] > > (let [weights [[0 0]] > > inputs (buildInputs sizeOfDataSet) > > outputs (buildOutputs sizeOfDataSet > > infiniteAndOutputCollection)] > > (trainPerceptron weights inputs outputs))) > > > On Apr 20, 6:32 am, David Nolen <dnolen.li...@gmail.com> wrote:> You have > > two other function calls > > > getAdaptedWeightVector > > > computeActualResponse > > > > Are these recursive as well? > > > > On Sun, Apr 19, 2009 at 11:26 PM, jleehurt <jleeh...@gmail.com> 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 clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---