给出变量和不确定性的线性方程:scipy-optimize?

时间:2014-04-22 22:36:02

标签: python optimization numpy scipy chemistry

我希望最小化一组方程,其中变量是已知的,具有不确定性。本质上,我想测试一个假设,即给定的测量变量符合方程给出的公式约束。这似乎是我应该能够用scipy-optimize做的事情。例如,我有三个方程式:

8 = 0.5 * x1 + 1.0 * x2 + 1.5 * x3 + 2.0 * x4  
4 = 0.0 * x1 + 0.0 * x2 + 1.0 * x3 + 1.0 * x4  
1 = 1.0 * x1 + 1.0 * x2 + 0.0 * x3 + 0.0 * x4  

四个测量未知数的1-sigma不确定性:

x1 = 0.246 ± 0.007  
x2 = 0.749 ± 0.010  
x3 = 1.738 ± 0.009  
x4 = 2.248 ± 0.007  

寻找正确方向的任何指针。

3 个答案:

答案 0 :(得分:4)

这是我的方法。假设x1-x4近似正态分布在每个均值周围(1-sigma不确定性),问题变成了最小化误差平方和的问题,具有3个线性约束函数。因此,我们可以使用scipy.optimize.fmin_slsqp()

攻击它
In [19]:

def eq_f1(x):
    return (x*np.array([0.5, 1.0, 1.5, 2.0])).sum()-8
def eq_f2(x):
    return (x*np.array([0.0, 0.0, 1.0, 1.0])).sum()-4
def eq_f3(x):
    return (x*np.array([1.0, 1.0, 0.0, 0.0])).sum()-1
def error_f(x):
    error=(x-np.array([0.246, 0.749, 1.738, 2.248]))/np.array([0.007, 0.010, 0.009, 0.007])
    return (error*error).sum()
In [20]:

so.fmin_slsqp(error_f, np.array([0.246, 0.749, 1.738, 2.248]), eqcons=[eq_f1, eq_f2, eq_f3])
Optimization terminated successfully.    (Exit mode 0)
            Current function value: 2.17576389592
            Iterations: 4
            Function evaluations: 32
            Gradient evaluations: 4
Out[20]:
array([ 0.25056582,  0.74943418,  1.74943418,  2.25056582])

答案 1 :(得分:0)

我觉得我有一个非常相似的问题。我对py比较陌生,主要用于对大熊猫进行排序和减少数据。

我有一组线性方程,我想在其中找到最合适的参数。但是,该数据集具有已知的不确定性,需要考虑在括号中给出)。

x1*99(1)+x2*45(1)=52(0.2)
x1*1(0.5)+x2*16(1)=15(0.1)

此外,还有一些约束条件:

x1>=0
x2>=0
x1+x2=1

我的方法是将等式视为约束,并求解残差之和,如上例所示。

毫无疑问地解决这个问题不是问题。我希望在寻找最佳拟合参数时获得有关如何解决不确定性的提示。

答案 2 :(得分:0)

正如所给的,问题没有解决的办法。这是因为如果输入x1,x2,x3和x4是高斯,则输出:

y1 = 0.5 * x1 + 1.0 * x2 + 1.5 * x3 + 2.0 * x4 - 8.0
y2 = 0.0 * x1 + 0.0 * x2 + 1.0 * x3 + 1.0 * x4 - 4.0
y3 = 1.0 * x1 + 1.0 * x2 + 0.0 * x3 + 0.0 * x4 - 1.0

也是高斯的。 假设x1,x2,x3和x4是独立的随机变量,使用OpenTURNS可以很容易地看出这一点:

import openturns as ot
x1 = ot.Normal(0.246, 0.007)
x2 = ot.Normal(0.749, 0.010)
x3 = ot.Normal(1.738, 0.009)
x4 = ot.Normal(2.248, 0.007)
y1 = 0.5 * x1 + 1.0 * x2 + 1.5 * x3 + 2.0 * x4 - 8.0
y2 = 0.0 * x1 + 0.0 * x2 + 1.0 * x3 + 1.0 * x4 - 4.0
y3 = 1.0 * x1 + 1.0 * x2 + 0.0 * x3 + 0.0 * x4 - 1.0

以下脚本生成图形:

graph1 = y1.drawPDF()
graph1.setLegends(["y1"])
graph2 = y2.drawPDF()
graph2.setLegends(["y2"])
graph3 = y3.drawPDF()
graph3.setLegends(["y3"])
graph1.add(graph2)
graph1.add(graph3)
graph1.setColors(["dodgerblue3",
                   "darkorange1", 
                   "forestgreen"])
graph1.setXTitle("Y")

上一个脚本产生以下输出。

Distribution of the output Y

鉴于此分布中0.0的位置,我想说在数学上不可能求解方程,但在物理上与数据一致。

实际上,我想您为x1,...,x4给出的高斯分布是根据数据估算的。所以我宁愿将问题改写如下:

给出一个观测值x1,x2,x3,x4的样本,那么e1,e2,e3的值是多少?

y1 = 0.5 * x1 + 1.0 * x2 + 1.5 * x3 + 2.0 * x4 - 8 + e1 = 0
y2 = 0.0 * x1 + 0.0 * x2 + 1.0 * x3 + 1.0 * x4 - 4 + e2 = 0
y3 = 1.0 * x1 + 1.0 * x2 + 0.0 * x3 + 0.0 * x4 - 1 + e3 = 0

这将问题变成反问题,可以通过校准e1,e2,e3来解决。此外,给定x1,...,x4的有限样本大小,我们可能要生成e1,e2,e3的分布。这可以通过引导输入/输出对(x,y)来完成:e1,e2,e3的分布然后反映了这些参数随手头样品的可变性。

首先,我们必须从分发中生成一个样本(我想您已经有这个样本,但是到目前为止尚未发布):

distribution = ot.ComposedDistribution([x1, x2, x3, x4])
sampleSize = 10
xobs = distribution.getSample(sampleSize)

然后我们定义模型:

formulas = [
    "y1 := 0.5 * x1 + 1.0 * x2 + 1.5 * x3 + 2.0 * x4 + e1 - 8.0",
    "y2 := 0.0 * x1 + 0.0 * x2 + 1.0 * x3 + 1.0 * x4 + e2 - 4.0",
    "y3 := 1.0 * x1 + 1.0 * x2 + 0.0 * x3 + 0.0 * x4 + e3 - 1.0"
]
program = ";".join(formulas)
g = ot.SymbolicFunction(["x1", "x2", "x3", "x4", "e1", "e2", "e3"],
                        ["y1", "y2", "y3"], 
                        program)

并设置观察到的输出,它是零的样本:

yobs = ot.Sample(sampleSize, 3)

我们从等于零的初始值开始,然后定义要校准的函数:

e1Initial = 0.0
e2Initial = 0.0
e3Initial = 0.0
thetaPrior = ot.Point([e1Initial,e2Initial,e3Initial])
calibratedIndices = [4, 5, 6]
mycf = ot.ParametricFunction(g, calibratedIndices, thetaPrior)

然后我们可以校准模型:

algo = ot.NonLinearLeastSquaresCalibration(mycf, xobs, yobs, thetaPrior)
algo.run()
calibrationResult = algo.getResult()
print(calibrationResult.getParameterMAP())

此打印:

[0.0265988,0.0153057,0.00495758]

这意味着错误e1,e2,e3很小。 我们可以计算出置信区间:

thetaPosterior = calibrationResult.getParameterPosterior()
print(thetaPosterior.computeBilateralConfidenceIntervalWithMarginalProbability(0.95)[0])

此打印:

[0.0110046, 0.0404756]
[0.00921992, 0.0210059]
[-0.00601084, 0.0156665]

第三个参数e3可能为零,但e1和e2都不为零。 最后,我们可以获得错误的分布:

thetaPosterior = calibrationResult.getParameterPosterior()

并绘制:

graph1 = thetaPosterior.getMarginal(0).drawPDF()
graph2 = thetaPosterior.getMarginal(1).drawPDF()
graph3 = thetaPosterior.getMarginal(2).drawPDF()
graph1.add(graph2)
graph1.add(graph3)
graph1.setColors(["dodgerblue3",
                  "darkorange1", 
                  "forestgreen"])
graph1

这将产生:

Distribution of e1, e2, e3

这表明给定观测输入x1,...,x4的可变性,e3可能为零。但是e1和e2不能为零。该样本的结论是,第三个方程近似地由观测值x1,...,x4求解,但不是两个第一个方程。