【问题标题】:python uncertainties and correlationpython的不确定性和相关性
【发布时间】:2020-11-16 12:41:25
【问题描述】:

借助“不确定性”包,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

【问题讨论】:

    标签: python uncertainty


    【解决方案1】:

    我只需要解决基本相同的问题,而且我还发现relevant part of the manual 令人困惑。截至本文发布时,他们使用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,我们仍然会生成协方差矩阵,但相关的非对角线元素已在后台自动分配为零。因此,当我们在pA2pB2 上传播时,我们会得到不相关的结果。

    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) 也是随机变量。所以在相关和不相关的情况下,我们可以生成一个与abf(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)]))
    

    【讨论】:

      【解决方案2】:

      来自User Guide 示例:

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

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

      p0, p1 = uncertainties.correlated_values(popt, pcov)
      

      【讨论】:

      • 我已经编辑了这个问题,你的解决方案似乎做了一些事情,但我不太明白是什么。你能解释一下吗?
      猜你喜欢
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      • 2019-07-02
      • 2011-04-26
      相关资源
      最近更新 更多