scipy 使用最小二乘法协助解线性方程组

6yoyoihd  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(157)

我希望得到一些概念上的帮助,关于如何解决一个线性方程组与罚函数。示例代码在底部。
假设我试着拟合这个方程:

Ie=IaX+IbY+IcZ

其中Ie,Ia,Ib,Ic是常数,X,Y,Z是变量,我可以很容易地用scipy,least_squares来解这个方程组,但是我想用两个约束来约束这个系统。

1. X+Y+Z=1
2. X,Y,Z > 0 and X,Y,Z < 1

为了做到这一点,我随后修改了上述函数。

Ie-Ic=X(Ia-Ic)+Y(Ib-Ic) where X+Y+Z=1 I solved for Z
therefore
Ax=B where A=[Ia-Ic,Ib-Ic] and B=[Ie-Ic] given bounds (0,1)

这解决了X,Y,Z > 0 and X,Y,Z < 1的第二个标准,但没有解决第一个问题。要解决第一个问题,需要做一个额外的约束,其中X+Y<1,我不太知道如何做。
所以我假设最小二乘有一些内置的惩罚函数的界限。

chi^2=||A-Bx||^2+P
where P is the conditions, if X,Y,Z>0 then P = 10000
thus, giving high chi squared values and thus setting the constraints

我不知道如何添加进一步的条件,所以if X+Y<1 then P=10000或者类似的东西。
简而言之,least_squares允许您设置单个值的边界,但我想设置一些进一步的约束,但我不太知道如何使用least_squares来实现这一点。我在scipy.minimize中看到了其他不等式约束选项,但我不太知道如何将其应用于格式为Ax=B的线性方程组。
作为一个示例代码,假设我已经完成了计算,得到了常数矩阵A和向量B。我使用最小二乘法,得到了X和Y的值,并且可以计算Z,因为X+Y+Z=1。这里的问题是在我的最小化中,我没有设置X+Y〈1的约束,所以在某些情况下,你可以得到X+Y〉1的值。所以我想找到一个方法,除了单个变量的边界约束之外,我还可以设置附加约束:

Ax=np.array([[1,2],[2,4],[3,4]])
B=np.array([0,1,2])

solution=lsq_linear(Ax,B,lsq_solver='lsmr',bounds=(0,1))

X=solution.x[0]
Y=solution.x[1]
Z=1-sum(solution.x)

如果最小化是这里的解决方案,你能告诉我如何设置它给上面的矩阵A和数组B?
任何建议,提示,或帮助我在正确的方向是非常感谢!
编辑:所以我在这里找到了类似的东西:Minimizing Least Squares with Algebraic Constraints and Bounds所以我想我应该把它应用到我的案例中,但我不认为我已经能够正确地应用它。

Ax=np.array([[1,2],[2,4],[3,4]])
B=np.array([0,1,2])
def fun(x,a1,a2,y):
   fun_output=x[0]*a1+x[1]*a2
   return np.sum((fun_output-y)**2)

cons = [{"type": "eq", "fun": lambda x: x[0] + x[1] - 1}]
bnds = [(0, 1), (0, 1)] 
xinit = np.array([1, 1]) 
solution=minimize(fun,args=(Ax[:,0],Ax[:,1], B), x0=xinit, bounds=bnds, constraints=cons)
solution_2=lsq_linear(Ax,B,bounds=(0,1))
print(solution.x)
print(solution_2.x)

问题是,这个函数的输出与lsq_linear不同,无论输入数组是什么,我几乎总是得到一个非常接近于零的Z值。我不知道我是否正确地设置/理解了这个函数。

blmhpbnm

blmhpbnm1#

你最初的猜测xinit是不可行的,也不满足你的约束。
我认为,直接将初始问题作为约束非线性优化问题(NLP)来求解,而不是重写它是更简单的方法。假设您有所有的数据点Ia, Ib, IcIe(您没有提供所有的数据点),您可以使用下面的代码片段,它与我在您的问题中的链接答案是相同的。

from scipy.optimize import minimize
import numpy as np

def fun_to_fit(coeffs, *args):
    x, y, z = coeffs
    Ia, Ib, Ic = args
    return Ia*x + Ib*y + Ic*z

def objective(coeffs, *args):
    Ia, Ib, Ic, Ie = args
    residual = Ie - fun_to_fit(coeffs, Ia, Ib, Ic)
    return np.sum(residual**2)

# Constraint: x + y + z == 1
con = [{'type': 'eq', 'fun': lambda coeffs: np.sum(coeffs) - 1}]

# bounds
bounds = [(0, 1), (0, 1), (0, 1)]

# initial guess (fulfils the constraint and lies within the bounds)
x0 = np.array([0.25, 0.5, 0.25])

# your given data points
#Ia = np.array(...)
#Ib = np.array(...)
#Ic = np.array(...)
#Ie = np.array(...)

# solve the NLP
res = minimize(lambda coeffs: objective(coeffs, Ia, Ib, Ic, Ie), x0=x0, bounds=bounds, constraint=con)

相关问题