[SciPy-user] incorrect variance in optimize.curvefit and leastsq
josef.pktd at gmail.com
josef.pktd at gmail.com
Fri Feb 13 11:21:41 EST 2009
> I think for the weighted least squares problem the weights should go
> into the SSE calculation. I didn't find directly the reference, but I
> am somewhat confident that this is correct, from the analogy to the
> transformed
> model ynew = y*weight where weight_i = 1/sigma_i in the linear case.
> But it's too late today to try to check this.
>
> SSE = np.sum((err*weight)**2)
>
I looked at the weighted function some more:
Since the error calculation for the s_sq uses `func =
_weighted_general_function`
the above weighting for the SSE is automatically done. But then, in
this case there is no renormalization
necessary when calculation s_sq. The special casing of the weighted
function should be dropped (the commented out part below)
if (len(ydata) > len(p0)) and pcov is not None:
s_sq = (func(popt, *args)**2).sum()/(len(ydata)-len(p0))
## if sigma is not None:
## s_sq /= (args[-1]**2).sum()
pcov = pcov * s_sq
else:
pcov = inf
Below is the test for the weighted case, rewritten from the
unweighted NIST example.
Note: I multiplied y and and f(x) by the weight, which then is
corrected again by the weighted least squares, and so I get the
original NIST estimates back. This test passes with the above
correction but fails in the current version, r5551.
Josef
-----------------------
def test_curvefit_weights():
'''test against NIST certified case at
http://www.itl.nist.gov/div898/strd/nls/data/misra1b.shtml
add weights to test curvefit with weights'''
data = array([[ 10.07, 77.6 ],
[ 14.73, 114.9 ],
[ 17.94, 141.1 ],
[ 23.93, 190.8 ],
[ 29.61, 239.9 ],
[ 35.18, 289. ],
[ 40.02, 332.8 ],
[ 44.82, 378.4 ],
[ 50.76, 434.8 ],
[ 55.05, 477.3 ],
[ 61.01, 536.8 ],
[ 66.4 , 593.1 ],
[ 75.47, 689.1 ],
[ 81.78, 760. ]])
y,x = data[:,0],data[:,1]
pstd_c = [3.1643950207E+00, 4.2547321834E-06]
popt_c = [3.3799746163E+02, 3.9039091287E-04]
SSE_c = 7.5464681533E-02
Rstd_c = 7.9301471998E-02
decimal = 5 #accuracy of parameter estimate and standard deviation
w = 1.0 + np.arange(len(x)) # 1/weights = sigma
print w
def funct(x, b1, b2):
#weighted function for y
return w * b1 * (1-(1+b2*x/2)**(-2))
y = w * y #weighted y
start1 = [500, 0.0001]
start2 = [300, 0.0002]
for start in [start1, start2]:
popt, pcov = curve_fit(funct, x, y, p0=start, sigma=w)
pstd = np.sqrt(np.diag(pcov))
assert_almost_equal(popt, popt_c, decimal=decimal)
assert_almost_equal(pstd, pstd_c, decimal=decimal)
---------------------------
More information about the SciPy-User
mailing list