作者热门文章
- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有4个非线性方程,要解决的三个未知数X
,Y
和Z
。等式的形式为:
F(m) = X^2 + a(m)Y^2 + b(m)XYcosZ + c(m)XYsinZ
a
,
b
和
c
是常数,它们取决于四个方程式中
F
的每个值。
最佳答案
有两种方法可以做到这一点。
F_i = X^2 + a_i Y^2 + b_i X Y cosZ + c_i X Y sinZ
F_i = a^2 + X_i b^2 + Y_i a b cos(c) + Z_i a b sin(c)
F
)知道
X
,
Y
,
Z
和
F_0, F_1, ... F_i
的位置。
a^2
,
b^2
,
a b cos(c)
和
a b sin(c)
。为了使操作更简单,让我们再次重新标记:
d = a^2
e = b^2
f = a b cos(c)
g = a b sin(c)
F_i = d + e X_i + f Y_i + g Z_i
。对
d
,
e
,
f
和
g
进行最小二乘线性反转很容易。然后,我们可以从以下位置获取
a
,
b
和
c
:
a = sqrt(d)
b = sqrt(e)
c = arctan(g/f)
F_i = d + e X_i + f Y_i + g Z_i
|F_0| |1, X_0, Y_0, Z_0| |d|
|F_1| = |1, X_1, Y_1, Z_1| * |e|
|F_2| |1, X_2, Y_2, Z_2| |f|
|F_3| |1, X_3, Y_3, Z_3| |g|
F = G * m
(我是地球物理学家,所以我们将
G
用作“格林函数”,并将
m
用作“模型参数”。通常,我们也将
d
用作“数据”,而不是
F
。)
def invert(f, x, y, z):
G = np.vstack([np.ones_like(x), x, y, z]).T
m, _, _, _ = np.linalg.lstsq(G, f)
d, e, f, g = m
a = np.sqrt(d)
b = np.sqrt(e)
c = np.arctan2(g, f) # Note that `c` will be in radians, not degrees
return a, b, c
scipy.optimize
解决此问题,如@Joe所建议。
scipy.optimize
中最易访问的函数是
scipy.optimize.curve_fit
,默认情况下使用Levenberg-Marquardt方法。
scipy.optimize
),然后沿着参数空间
observed - predicted
的斜率向下倾斜。
scipy.optimize
不能处理的问题。如果您的模型参数具有不同的幅度(例如
a=1, b=1000, c=1e-8
),则需要重新缩放比例,以使其大小相似。否则,
scipy.optimize
的“爬山”算法(如LM)将无法准确计算局部梯度的估计值,并且会给出非常不准确的结果。现在,我假设
a
,
b
和
c
具有相对相似的幅度。另外,请注意,基本上所有非线性方法都需要您进行初始猜测,并且对此猜测很敏感。我将其保留在下面(只需将其作为
p0
kwarg传递给
curve_fit
即可),因为默认
a, b, c = 1, 1, 1
是对
a, b, c = 3, 2, 1
的相当准确的猜测。
curve_fit
传递给函数,进行观测的一组点(作为单个
ndim x npoints
数组)和观测值。
def func(x, y, z, a, b, c):
f = (a**2
+ x * b**2
+ y * a * b * np.cos(c)
+ z * a * b * np.sin(c))
return f
curve_fit
之前,需要包装它以接受稍有不同的参数。
def nonlinear_invert(f, x, y, z):
def wrapped_func(observation_points, a, b, c):
x, y, z = observation_points
return func(x, y, z, a, b, c)
xdata = np.vstack([x, y, z])
model, cov = opt.curve_fit(wrapped_func, xdata, f)
return model
import numpy as np
import scipy.optimize as opt
def main():
nobservations = 4
a, b, c = 3.0, 2.0, 1.0
f, x, y, z = generate_data(nobservations, a, b, c)
print 'Linear results (should be {}, {}, {}):'.format(a, b, c)
print linear_invert(f, x, y, z)
print 'Non-linear results (should be {}, {}, {}):'.format(a, b, c)
print nonlinear_invert(f, x, y, z)
def generate_data(nobservations, a, b, c, noise_level=0.01):
x, y, z = np.random.random((3, nobservations))
noise = noise_level * np.random.normal(0, noise_level, nobservations)
f = func(x, y, z, a, b, c) + noise
return f, x, y, z
def func(x, y, z, a, b, c):
f = (a**2
+ x * b**2
+ y * a * b * np.cos(c)
+ z * a * b * np.sin(c))
return f
def linear_invert(f, x, y, z):
G = np.vstack([np.ones_like(x), x, y, z]).T
m, _, _, _ = np.linalg.lstsq(G, f)
d, e, f, g = m
a = np.sqrt(d)
b = np.sqrt(e)
c = np.arctan2(g, f) # Note that `c` will be in radians, not degrees
return a, b, c
def nonlinear_invert(f, x, y, z):
# "curve_fit" expects the function to take a slightly different form...
def wrapped_func(observation_points, a, b, c):
x, y, z = observation_points
return func(x, y, z, a, b, c)
xdata = np.vstack([x, y, z])
model, cov = opt.curve_fit(wrapped_func, xdata, f)
return model
main()
关于python - 在python中求解非线性方程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19542801/
目标 给定一组点,我试图找出满足所提供所有点的线性方程的系数。 例如,如果我想求线性方程 (ax + by + c = z): 3x + 2y + 2 = z 我至少需要三个三维点: (2, 2, 1
我是一名优秀的程序员,十分优秀!