我将拟合与optimize.curve_fit和optimize.least_squares进行比较。使用curve_fit,我得到协方差矩阵pcov作为输出,我可以通过以下方法计算拟合变量的标准偏差:
perr = np.sqrt(np.diag(pcov))
如果我使用least_squares进行拟合,我没有得到任何协方差矩阵输出,我无法计算变量的标准偏差。
这是我的例子:
#import modules
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.optimize import least_squares
noise = 0.5
N = 100
t = np.linspace(0, 4*np.pi, N)
# generate data
def generate_data(t, freq, amplitude, phase, offset, noise=0, n_outliers=0, random_state=0):
#formula for data generation with noise and outliers
y = np.sin(t * freq + phase) * amplitude + offset
rnd = np.random.RandomState(random_state)
error = noise * rnd.randn(t.size)
outliers = rnd.randint(0, t.size, n_outliers)
error[outliers] *= 10
return y + error
#generate data
data = generate_data(t, 1, 3, 0.001, 0.5, noise, n_outliers=10)
#initial guesses
p0=np.ones(4)
x0=np.ones(4)
# create the function we want to fit
def my_sin(x, freq, amplitude, phase, offset):
return np.sin(x * freq + phase) * amplitude + offset
# create the function we want to fit for least-square
def my_sin_lsq(x, t, y):
# freq=x[0]
# phase=x[1]
# amplitude=x[2]
# offset=x[3]
return (np.sin(t*x[0]+x[2])*x[1]+ x[3]) - y
# now do the fit for curve_fit
fit = curve_fit(my_sin, t, data, p0=p0)
print 'Curve fit output:'+str(fit[0])
#now do the fit for least_square
res_lsq = least_squares(my_sin_lsq, x0, args=(t, data))
print 'Least_squares output:'+str(res_lsq.x)
# we'll use this to plot our first estimate. This might already be good enough for you
data_first_guess = my_sin(t, *p0)
#data_first_guess_lsq = x0[2]*np.sin(t*x0[0]+x0[1])+x0[3]
data_first_guess_lsq = my_sin(t, *x0)
# recreate the fitted curve using the optimized parameters
data_fit = my_sin(t, *fit[0])
data_fit_lsq = my_sin(t, *res_lsq.x)
#calculation of residuals
residuals = data - data_fit
residuals_lsq = data - data_fit_lsq
ss_res = np.sum(residuals**2)
ss_tot = np.sum((data-np.mean(data))**2)
ss_res_lsq = np.sum(residuals_lsq**2)
ss_tot_lsq = np.sum((data-np.mean(data))**2)
#R squared
r_squared = 1 - (ss_res/ss_tot)
r_squared_lsq = 1 - (ss_res_lsq/ss_tot_lsq)
print 'R squared curve_fit is:'+str(r_squared)
print 'R squared least_squares is:'+str(r_squared_lsq)
plt.figure()
plt.plot(t, data)
plt.title('curve_fit')
plt.plot(t, data_first_guess)
plt.plot(t, data_fit)
plt.plot(t, residuals)
plt.figure()
plt.plot(t, data)
plt.title('lsq')
plt.plot(t, data_first_guess_lsq)
plt.plot(t, data_fit_lsq)
plt.plot(t, residuals_lsq)
#error
perr = np.sqrt(np.diag(fit[1]))
print 'The standard deviation errors for curve_fit are:' +str(perr)
我非常感谢任何帮助,祝福
ps:我从这个来源获得了很多输入,并使用了部分代码Robust regression
答案 0 :(得分:2)
optimize.least_squares的结果在其中有一个名为jac的参数。来自documentation:
jac:ndarray,稀疏矩阵或LinearOperator,形状(m,n)
在解决方案中修改雅可比矩阵,在这个意义上,J ^ T J是成本函数的Hessian的Gauss-Newton近似。类型与算法使用的类型相同。
这可以用于使用以下公式估计参数的协方差矩阵:Sigma =(J'J)^ - 1。
J = res_lsq.jac
cov = np.linalg.inv(J.T.dot(J))
要查找参数的方差,可以使用:
var = np.sqrt(np.diagonal(cov))
答案 1 :(得分:0)
SciPy 程序 optimize.least_squares 要求用户在输入中提供函数 fun(...)
,该函数返回残差向量。这通常定义为
residuals = (data - model)/sigma
其中 data
和 model
是向量,其中包含要拟合的数据以及每个数据点的相应模型预测,而 sigma
是每个 data
值中的 1σ 不确定性.
在这种情况下,假设可以信任输入 sigma
的不确定性,可以使用 jac
返回的输出雅可比矩阵 least_squares
来估计协方差矩阵。此外,假设协方差矩阵是对角的,或者简单地忽略非对角项,还可以得到模型参数中的 1σ 不确定性 perr
(通常称为“形式误差”)如下(见第 15.4.2 节) Numerical Recipes 3rd ed.)
import numpy as np
from scipy import linalg, optimize
res = optimize.least_squares(...)
U, s, Vh = linalg.svd(res.jac, full_matrices=False)
tol = np.finfo(float).eps*s[0]*max(res.jac.shape)
w = s > tol
cov = (Vh[w].T/s[w]**2) @ Vh[w] # robust covariance matrix
perr = np.sqrt(np.diag(cov)) # 1sigma uncertainty on fitted parameters
上面获取协方差矩阵的代码与下面的简单代码形式相同(如 Alex 所建议的),但上面的主要优点是即使雅可比矩阵接近退化时也能工作,这是一种常见的出现在现实世界的最小二乘拟合中
cov = linalg.inv(res.jac.T @ res.jac) # covariance matrix when jac not degenerate
如果不相信输入的不确定性 sigma
,仍然可以假设拟合良好,从拟合本身估计数据的不确定性。这对应于假设 chi**2/DOF=1
,其中 DOF
是自由度数。在这种情况下,可以使用以下几行在计算不确定性之前重新调整协方差矩阵
chi2dof = np.sum(res.fun**2)/(res.fun.size - res.x.size)
cov *= chi2dof
perr = np.sqrt(np.diag(cov)) # 1sigma uncertainty on fitted parameters