有没有办法计算两个变量中多项式模型的参数。它们是独立的:
z = a + bx + cx^2 + dy + ey^2
我被告知你可以使用numpy.polyfit
但这只能支持两个变量而不是我需要的三个变量。我的数据当前存储在三个numpy数组中,这样数组中每个数据的索引与其他变量中该索引处的数据相关联。即
Y = [1 2 3 4 5]
X = [3 5 7 9 11]
Z = [2 4 6 2 6]
1与3和2相关; 2与5和4相关,依此类推。 我该如何处理这个问题?
答案 0 :(得分:2)
polyfit
假设一个变量。但是,你想要做的是解决一般的线性方程组。
你有一个等式:
z = a + bx + cx^2 + dy + ey^2
观察到x,y和z的5个点。这给了我们5个方程:
z1 = a + bx1 + cx1^2 + dy1 + ey1^2
z2 = a + bx2 + cx2^2 + dy2 + ey2^2
z3 = a + bx3 + cx3^2 + dy3 + ey3^2
z4 = a + bx4 + cx4^2 + dy4 + ey4^2
z5 = a + bx5 + cx5^2 + dy5 + ey5^2
最容易将其视为线性代数问题。我们可以将方程组重写为矩阵乘法:
|z1| |1 x1 x1^2 y1 y1^2| |a|
|z2| |1 x2 x2^2 y2 y2^2| |b|
|z3| = |1 x3 x3^2 y3 y3^2| x |c|
|z4| |1 x4 x4^2 y4 y4^2| |d|
|z5| |1 x5 x5^2 y5 y5^2| |e|
我们知道x1..5
,y1..5
和z1..5
,但a, b, c, d, e
是未知数。我们分别称这些矩阵为B
,A
和x
:
B = A x
我们要解决x
,这是我们a, b, c, d, e
参数的矩阵。
然而,我们有一个皱纹。您为x
,y
和z
提供的确切数字会导致A
的奇异矩阵。换句话说,行不是独立的。我们有效地将两次相同的等式放入。事实上,在这个确切的情况下,我们只有3个方程式。另外两个只是前三个的组合。
无法用你提供的X,Y,Z数据求解方程组。
考虑到这一点,让我们改变问题,使用5个随机的x,y,z点。
在这个特定的情况下,我们有5个未知数和5个方程。因此,我们可以准确地解决这个问题(例如使用np.linalg.solve
)。这被称为“甚至确定的问题”。
import numpy as np
np.random.seed(1)
# Each array with have 5 random points
x, y, z = np.random.random((3, 5))
# A is going to look like:
# |1 x1 x1^2 y1 y1^2|
# |1 x2 x2^2 y2 y2^2|
# |1 x3 x3^2 y3 y3^2|
# |1 x4 x4^2 y4 y4^2|
# |1 x5 x5^2 y5 y5^2|
A = np.column_stack([np.ones(len(x)), x, x**2, y, y**2])
# And "B" will just be our "z" array
B = z
# Now we can solve the system of equations Ax = B
a, b, c, d, e = np.linalg.solve(A, B)
然而,假设我们有10次观察或100次。在这种情况下,我们会有一个过分确定的问题。我们无法准确地解决它,而是需要使用最小二乘拟合。
在这种情况下,你仍然用矩阵乘法来表达事物并解决Ax = B
。但是,A
不是方阵。因此,我们需要使用不同的工具来解决问题。对于numpy
,它是np.linalg.lstsq
而不是np.linalg.solve
:
我会很快详细说明(可能会有点),但目前:
import numpy as np
np.random.seed(1)
# Each array with have 20 random points this time
x, y, z = np.random.random((3, 20))
# We're solving Ax = B
A = np.column_stack([np.ones(len(x)), x, x**2, y, y**2])
B = z
# Solve the system of equations.
result, _, _, _ = np.linalg.lstsq(A, B)
a, b, c, d, e = result
如果您想从等式中删除bx
和dy
条款,则可以将它们从A
中删除:
import numpy as np
np.random.seed(1)
x, y, z = np.random.random((3, 20))
# Note that we've remove the `x` and `y` terms.
# We're solving `z = a + cx^2 + ey^2`
A = np.column_stack([np.ones(len(x)), x**2, y**2])
B = z
# Solve the system of equations.
result, _, _, _ = np.linalg.lstsq(A, B)
a, c, e = result