有没有办法计算两个变量中多项式模型的参数.它们是独立的,因此:
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相关,依此类推.
我该如何处理这个问题?
最佳答案 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)
超过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
删除条款
如果你想从等式中删除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