I have several data points:
X = np.array([0.01,0.05,0.2,1,10,100,400,2000])
Y = np.array([623,3245.5,710564,332456,540124.5,1851657,5679457,10096844])
And I want to fit these data points to the sigmoid function :
S=D+(A-D)/(1+(X/C)**B)
A,B,C,D
are four parameters need to be determined by giving the initial value p(A0,B0,C0,D0)
.
In addition, each point should add a weight factor to the residual , thus making the sum of square reach global minimum :
weight = ([100,90,80,70,60,50,40,30])
I am a novice in algorithm as well as coding, can anyone give some ideas on how to fit these data? Million thanks!
Here is my Levenberg-Maquardt code:
from numpy import *
def function(p):
r = array([10*(p[1]-p[0]**2),(1-p[0])])
fp = dot(transpose(r),r) #= 100*(p[1]-p[0]**2)**2 + (1-p[0])**2
J = (array([[-20*p[0],10],[-1,0]]))
grad = dot(transpose(J),transpose(r))
return fp,r,grad,J
def lm(p0,tol=10**(-5),maxits=100):
nvars=shape(p0)[0]
nu=0.01
p = p0
fp,r,grad,J = function(p)
e = sum(dot(transpose(r),r))
nits = 0
while nits<maxits and linalg.norm(grad)>tol:
nits += 1
fp,r,grad,J = function(p)
H=dot(transpose(J),J) + nu*eye(nvars)
pnew = zeros(shape(p))
nits2 = 0
while (p!=pnew).all() and nits2<maxits:
nits2 += 1
dp,resid,rank,s = linalg.lstsq(H,grad)
pnew = p-dp
fpnew,rnew,gradnew,Jnew = function(pnew)
enew = sum(dot(transpose(rnew),rnew))
rho = linalg.norm(dot(transpose(r),r)-dot(transpose(rnew),rnew))
rho /= linalg.norm(dot(transpose(grad),pnew-p))
if rho>0:
update = 1
p = pnew
e = enew
if rho>0.25:
nu=nu/10
else:
nu=nu*10
update = 0
print fp, p, e, linalg.norm(grad), nu
p0 = array([-1.92,2])
lm(p0)