0

借助“不确定性”包,python 在通过计算传播不确定性方面非常强大。是否有可能也包括相关性?比方说,我拟合了一些数据,scipy.optimize.curve_fit这些数据返回了最佳拟合参数及其相关矩阵,通常称为poptpcov。现在我想评估一个函数f(popt)

没有相关性,例如可以按如下方式进行(在 2D 中)

f(p0, p1):
    return p0 * unumpy.exp(p1)

p0 = ufloat(popt[0], pcov[0,0]**0.5)
p1 = ufloat(popt[1], pcov[1,1]**0.5)
result = f(p0, p1)

带有whataver功能f。这忽略了 p0 和 p1 的相关性。在“不确定性”的文档中提到了相关性,但我真的不明白是否以及如何将其应用于我的问题。

编辑:这似乎可行,但老实说,我真的不明白它的作用以及这是否真的是正确的解决方案。

import numpy as np
import uncertainties
from uncertainties import ufloat, unumpy

def f(p0, p1):
    return p0 * unumpy.exp(p1)

popt = np.array([1, 2])
pcov = np.array([[1, 2], [3, 4]])

p0, p1 = uncertainties.correlated_values(popt, pcov)
print(f(p0, p1))  # 7+/-25

p0 = ufloat(popt[0], pcov[0,0]**0.5)
p1 = ufloat(popt[1], pcov[1,1]**0.5)
print(f(p0, p1))  # 7+/-17
4

2 回答 2

1

我只需要解决基本相同的问题,而且我还发现手册的相关部分令人困惑。在这篇文章中,他们使用定义相关系统的“示例”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可以实际使用的对象,我们将调用的对象pApB。如果您必须显式输入输入,您将有一个类似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))

最后,让我们讨论一下代替手册中的最小示例给出的协方差矩阵类型。 ab是随机变量,因此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)]))
于 2022-01-04T20:26:55.323 回答
0

用户指南示例:

(u2, v2, sum2) = uncertainties.correlated_values([1, 10, 21], cov_matrix)

在你的情况下,我猜你可能只是写:

p0, p1 = uncertainties.correlated_values(popt, pcov)
于 2021-04-15T12:44:42.753 回答