使用numpy polyfit

时间:2016-01-12 14:48:23

标签: python arrays numpy

有没有办法计算两个变量中多项式模型的参数。它们是独立的:

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相关,依此类推。 我该如何处理这个问题?

1 个答案:

答案 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..5y1..5z1..5,但a, b, c, d, e是未知数。我们分别称这些矩阵为BAx

B = A x

我们要解决x,这是我们a, b, c, d, e参数的矩阵。

奇异矩阵

然而,我们有一个皱纹。您为xyz提供的确切数字会导致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)

超过5次观察

然而,假设我们有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

删除条款

如果您想从等式中删除bxdy条款,则可以将它们从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