我正在查看使用 python 中的 optimize.leastsq 方法获取拟合参数的标准错误,因为我想使用 optimize.least_squares 来拟合一些数据,但是我的参数有界限(出于物理原因),例如参数 A 必须为 [0 ,1]。我看到使用协方差矩阵并乘以残差的方法会导致误差线超出参数范围。什么是统计上正确和严谨的事情?在允许的范围内人为地切断我的误差线,还是有其他方法可以将误差线保持在边界内?
import numpy as np
from scipy import optimize
import random
def f( x, p0, p1, p2):
return p0*x + 0.4*np.sin(p1*x) + p2
def ff(x, p):
return f(x, *p)
# These are the true parameters.
p0 = 1.0 #In the fit we will bound p0 from 0 to 1 for e.g., some physical/modeling reason
p1 = 40
p2 = 2.0
# These are initial guesses for fits:
pstart = [0.8,40,2]
# Generate data with a bit of randomness
# (the noise-less function that underlies the data is shown as a blue line)
xdata = np.array(np.linspace(0., 1, 120))
np.random.seed(42)
err_stdev = 0.2
yvals_err = np.random.normal(0., err_stdev, len(xdata))
ydata = f(xdata, p0, p1, p2) + yvals_err
def fit_leastsq(p0, datax, datay, function, bounds1):
errfunc = lambda p, x, y: function(x,p) - y
all_results= optimize.least_squares(errfunc, p0, args=(datax, datay),bounds=bounds1 )
pfit=all_results.x
J=final_results.jac #the jacobian matrix
pcov=np.linalg.inv(2*J.T.dot(J)) #This calculates the inverse Hessian which is used to approximate the covariance
s_sq = (errfunc(pfit, datax, datay)**2).sum()/(len(datay)-len(p0))
pcov = pcov * s_sq
error = []
for i in range(len(pfit)):
try:
error.append(np.absolute(pcov[i][i])**0.5)
except:
error.append( 0.00 )
pfit_leastsq = pfit
perr_leastsq = np.array(error)
return pfit_leastsq, perr_leastsq
#Set Bounds on Parameters
bounds=([0,0,0],[1,40,2.5]) #this means first parameter is restricted 0-1, second is 0-40, and this is 0-2.5
pfit, perr = fit_leastsq(pstart, xdata, ydata, ff, bounds)
print("\n# Fit parameters and parameter errors from lestsq method :")
print("pfit = ", pfit)
print("perr = ", perr)
我得到的结果是:
# Fit parameters and parameter errors from lestsq method :
pfit = [ 1. 39.97612883 1.98430673]
perr = [0.07545234 0.07611141 0.01546065]
请注意,参数上的 perr 超出了边界范围。也许有办法获得方向错误?也就是说,例如,第一个参数上的误差线只会在负方向?