I'm having great difficulty getting praxis to optimize just a simplified least squares error for a linear fit. I can't get it to alter the parameter to minimize error. I just get the same error over and over again.
Here's the code:
pts=5
double ydata[pts], xdata[pts]
objref dvec
double parm[1]
dvec = new Vector(pts)
dvec.x[0]=12.0589
dvec.x[1]=15.3894
dvec.x[2]=20.7632
dvec.x[3]=30.8094
dvec.x[4]=39.5046
//----------------------------load data pts somewhere here
proc init() { //intial guesses
for q=0, pts - 1 {
x=dvec.x[q]
xdata[q]=x //mean distances
ydata[q] = 2*q //this should be # firings or amp (will change later)
}
m=(ydata[pts-1]-ydata[0])/(xdata[pts-1]-xdata[0]) //intial guess for slope
b=0 //intial guess for vertical shift
parm[0]= m
iterations=0
sum=0
}
//----------------------------- linear fit
func model() {local x, y, i
for i=0,4 {
x = $1
y = ($2*x) //+$3 // fit data to line y=mx+b
return y
}
}
//---------------------------------------------least squares error
func errfun() { local sum, y, i
iterations = iterations + 1
sum = 0
for i=0, pts-1 {
y = model(xdata, $1) - ydata
sum = sum + y*y //sq of distance bt model&data
}
lserror=sqrt(sum)
print "error=",lserror
return lserror
}
init()
attr_praxis(0.5, 1, 0)
fit_praxis(1, "errfun", &parm[0])
praxis
praxis
I had a look at how these functions are used in a builtin function (see file funfit.hoc).
First the parameters passed have to be in a vector, see the fit_praxis documentation aswell, although I think a vector of doubles would invite you to do variable declaration with a double statement.
Second $1 in errfun should refer to the number of parameters passed and is not the parameter, the actual parameter is in the second argument to the function.
But the second argument is passed by reference, so it needs to be dereferenced before we use it, which explains the extra & in the $&2.
Putting it all together in your file gives:
which seems to work well.
First the parameters passed have to be in a vector, see the fit_praxis documentation aswell, although I think a vector of doubles would invite you to do variable declaration with a double statement.
Second $1 in errfun should refer to the number of parameters passed and is not the parameter, the actual parameter is in the second argument to the function.
But the second argument is passed by reference, so it needs to be dereferenced before we use it, which explains the extra & in the $&2.
Putting it all together in your file gives:
Code: Select all
pts=5
double ydata[pts], xdata[pts]
objref dvec
//double parm[1]
objref parm
parm = new Vector(2)
dvec = new Vector(pts)
dvec.x[0]=12.0589
dvec.x[1]=15.3894
dvec.x[2]=20.7632
dvec.x[3]=30.8094
dvec.x[4]=39.5046
//----------------------------load data pts somewhere here
proc init() { //intial guesses
for q=0, pts - 1 {
x=dvec.x[q]
xdata[q]=x //mean distances
ydata[q] = 2*q //this should be # firings or amp (will change later)
}
m=(ydata[pts-1]-ydata[0])/(xdata[pts-1]-xdata[0]) //intial guess for slope
b=0 //intial guess for vertical shift
parm.x[0]= m
iterations=0
sum=0
}
//----------------------------- linear fit
func model() {local x, y, i
for i=0,4 {
x = $1
y = ($2*x) //+$3 // fit data to line y=mx+b
return y
}
}
//---------------------------------------------least squares error
func errfun() { local sum, y, i
iterations = iterations + 1
sum = 0
for i=0, pts-1 {
y = model(xdata[i], $&2[0]) - ydata[i]
sum = sum + y*y //sq of distance bt model&data
}
lserror=sqrt(sum)
print "noofargs=" , $1, ", derivative= ", $&2[0] , ", error=" , lserror
return lserror
}
init()
attr_praxis(0.5, 1, 0)
fit_praxis(1, "errfun", &parm.x[0])