我只需要解决基本相同的问题,而且我还发现手册的相关部分令人困惑。在这篇文章中,他们使用定义相关系统的“示例”uncertainties.correlated_values
实际上是重新键入了一个协方差矩阵,该矩阵是他们在半页前通过应用于uncertainties.covariance_matrix
一对不相关的变量和一个函数而获得的。这既不是最小的例子,也不是uncertainties.correlated_values
.
简短的回答是,当您声明多个ufloat
对象时,uncertainties
始终定义这些对象之间的相关性。但是要在声明变量序列时分配uncertainties.correlated_values
这些相关性,您必须使用方法而不是使用uncertainties.ufloat
方法进行声明。
下面说明了各种协方差方法如何与拟合参数和误差传播相互作用。
首先,我们需要一些相关的拟合参数。
import uncertainties
from scipy.optimize import curve_fit
import numpy as np
#define fitting model
def model(x, a, b):
return a*x + b
#generate ydata that will produce significant parameter correlations
xdata=np.asarray([0,1,2,3,4,5])
ydata=np.zeros(len(xdata))
modata=np.zeros(len(xdata))
for i in range(len(xdata)):
ydata[i]=xdata[i]**2 + xdata[i]**0.5
#fitting the data to the model specifies how correlated a and b are.
par,cov=curve_fit(model,xdata,ydata)
print(par,cov)
#define the function we wish to propagate the parameters a and b through
def func(a,b):
return a**3 + 2*b
接下来,让我们在没有的情况下进行错误传播,uncertainties
以便我们知道它应该生成什么值。请注意,像这样手动输入导数通常是不切实际的,因此以下方法不是一个好的通用方法。
fval = func(par[0],par[1]) #should evaluate to 152.76871905750235
dfa = (3*(par[0])**2) #should evaluate to 87.9417774777352
dfb = 2
#ferr should evaluate to 55.90407506588157
ferr = ( dfa**2 *cov[0][0] + dfb**2 *cov[1][1] + 2*dfa*dfb*cov[0][1] )**0.5
print('estimated value {:.1f}'.format(fval))
print('correlated uncertainty {:.1f}'.format(ferr))
#ferr_uncorr should evaluate to 59.36418474861461
ferr_uncorr = ( dfa**2 *cov[0][0] + dfb**2 *cov[1][1] )**0.5
print('uncorrelated uncertainty {:.1f}'.format(ferr_uncorr))
print('\n')
我们希望使用 获得相同的结果uncertainties
。这需要我们声明一个相关变量的系统,并且uncertainties.correlated_values
是使用的方法来实现这一点。幸运的是,它scipy.optimize.curve_fit
已经生成了一系列平均值和协方差矩阵。我们只需要将它们分配给uncertainties
可以实际使用的对象,我们将调用的对象pA
和pB
。如果您必须显式输入输入,您将有一个类似uncertainties.correlated_values([a_val, b_val],[[cov_aa, cov_ab], [cov_ba, cov_bb]])
.
pA,pB = uncertainties.correlated_values(par, cov)
顺便说一句,我们可以打印我们刚刚定义的系统和原始参数协方差矩阵,以验证它们是否表示相同的数值数组。
print (cov)
print (uncertainties.covariance_matrix([pA,pB]))
正确声明相关性后,uncertainties
将正确处理相关错误传播。
corr_F = func(pA,pB)
print('correlated {:.3u}'.format(corr_F))
如果我们只是将参数声明为单独的 ufloat,我们仍然会生成协方差矩阵,但相关的非对角线元素已在后台自动分配为零。pA2
因此,当我们在和上传播时pB2
,我们会得到不相关的结果。
pA2 = uncertainties.ufloat(par[0],cov[0][0]**0.5)
pB2 = uncertainties.ufloat(par[1],cov[1][1]**0.5)
print(uncertainties.covariance_matrix([pA2,pB2]))
uncorr_F = func(pA2,pB2)
print('uncorrelated {:.3u}'.format(uncorr_F))
最后,让我们讨论一下代替手册中的最小示例给出的协方差矩阵类型。 a
和b
是随机变量,因此f(a,b)
也是随机变量。因此,在相关和不相关的情况下,我们都可以生成一个与 和 相关的协方差a
矩阵。额外的矩阵元素告诉你方差、个体和相关性。b
f(a,b)
f(a,b)
a-f(a,b)
b-f(a,b)
print(uncertainties.covariance_matrix([pA,pB,func(pA,pB)]))
print(uncertainties.covariance_matrix([pA2,pB2,func(pA2,pB2)]))