目标
给定一组点,我试图找到满足所有点的线性方程的系数。
例如,如果我想找到线性方程(ax + by + c = z):
3x + 2y + 2 = z
我需要至少三个三维点:
(2, 2, 12)
(3, 4, 19)
(4, 5, 24)
给定坐标(x,y,z)的足够点,我应该能够使用高斯消除法找到(a,b,c)。
但是,我认为在特殊情况下,我遇到了解决矩阵的问题。你可以在这里查看我在python实现的第一次尝试:https://gist.github.com/anonymous/8188272
让我们来看几个例子......
数据集1
使用以下“手工制作”点(x,y,z):
(2, 2, 12)
(3, 4, 19)
(4, 5, 24)
对以下矩阵执行LU分解:
[[ 2. 2. 1. 12.]
[ 3. 4. 1. 19.]
[ 4. 5. 1. 24.]]
返回解决U矩阵:
[[ 4. 5. 1. 24. ]
[ 0. -0.5 0.5 0. ]
[ 0. 0. 0.5 1. ]]
返回的结果(a,b,c):
[3.0, 2.0, 2.0]
正确!一切似乎都很好......
数据集2
使用以下“手工制作”点(x,y,z):
(3, 4, 19)
(4, 5, 24)
(5, 6, 29)
对以下矩阵执行LU分解:
[[ 3. 4. 1. 19.]
[ 4. 5. 1. 24.]
[ 5. 6. 1. 29.]]
返回解决U矩阵:
[[ 5.00000000e+00 6.00000000e+00 1.00000000e+00 2.90000000e+01]
[ 0.00000000e+00 4.00000000e-01 4.00000000e-01 1.60000000e+00]
[ 0.00000000e+00 0.00000000e+00 4.44089210e-16 0.00000000e+00]]
返回的结果(a,b,c):
[1.0, 4.0, 0.0]
虽然从技术上讲它是一种解决方案,但不是我想要的!
数据集3
使用以下“手工制作”点(x,y,z):
(5, 6, 29)
(6, 7, 34)
(7, 8, 39)
对以下矩阵执行LU分解:
[[ 5. 6. 1. 29.]
[ 6. 7. 1. 34.]
[ 7. 8. 1. 39.]]
返回解决U矩阵:
[[ 7.00000000e+00 8.00000000e+00 1.00000000e+00 3.90000000e+01]
[ 0.00000000e+00 2.85714286e-01 2.85714286e-01 1.14285714e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 3.55271368e-15]]
实施崩溃......
思想
在数据集2和3中,最后一行和倒数第二行是“特殊”。倒数第二行对“b”和“c”具有相同的值(在我的特殊示例中也是如此!)。不幸的是,我缺乏从中得到正面或反面的数学知识。
当最后一行全部为零并且其上方的行具有相等的值时,是否需要处理一些特殊情况?
提前致谢!
答案 0 :(得分:5)
是的,这是一个特殊情况,您需要以不同的方式处理。在案例2和3中,您有一个rank deficient matrix。一般来说,它可能意味着存在无限多的解决方案,或者没有解决方案。
您可以通过堆叠这些3向量来检查您制作的矩阵的determinant来确定是否会发生这些情况。
>>> import numpy as np
>>> from scipy.linalg import det
>>> data1 = np.array([(2, 2, 12), (3, 4, 19), (4, 5, 24)])
>>> data2 = np.array([(3, 4, 19), (4, 5, 24), (5, 6, 29)])
>>> data3 = np.array([(5, 6, 29), (6, 7, 34), (7, 8, 39)])
>>> det(data1)
-1.9999999999999982
>>> det(data2)
5.551115123125788e-17
>>> det(data3)
8.881784197001213e-16
示例1是一个满秩矩阵,几何上告诉您3个点是linearly independent。
示例2和3使矩阵具有零行列式,它告诉您这些点是线性相关的。
答案 1 :(得分:4)
结帐numpy.linalg
,scipy.linalg
和scipy.optimize
。
(2, 2, 12)
(3, 4, 19)
(4, 5, 24)
3x + 2y + 2 = z
使用numpy.linalg.solve
>>> a = np.array([[2, 2, 1],
[3, 4, 1],
[4, 5, 1]])
>>> b = np.array([12, 19, 24])
>>> np.linalg.solve(a, b)
array([ 3., 2., 2.])
(3, 4, 19)
(4, 5, 24)
(5, 6, 29)
我明白了......
>>> a = np.array([[3, 4, 1], [4, 5, 1], [5, 6, 1]])
>>> b = np.array([19, 24, 29])
>>> np.linalg.solve(a, b)
array([ 0.73333333, 4.26666667, -0.26666667])
这是您正在寻找的答案吗?这是一个有效的答案,但由于a
是等级2,[2., 3., 1.]
也是有效的答案。见下文......
(5, 6, 29)
(6, 7, 34)
(7, 8, 39)
重复过程...
>>> a = np.array([[5, 6, 1], [6, 7, 1], [7, 8, 1]])
>>> b = np.array([29, 34, 39])
>>> np.linalg.solve(a, b)
LinAlgError: Singular matrix
这意味着系数的determinant为零,因此矩阵的inverse是无限的,或者一般来说,system of equations有无数个解或者没有溶液
>>> np.linalg.det(a)
0.0
>>> 1. / np.linalg.det(a)
inf
请记住,您正在通过假设ax = b
因此x = inv(a)b
必须存在并且是有限的来解决系统inv(a)
。如果a
是单数,则inv(a)
是无限的。
>>> np.linalg.inv(a)
LinAlgError: Singular matrix
那么如何尝试least squares method来找到最佳解决方案呢。
>>> np.linalg.lstsq(a,b)
(array([ 2., 3., 1.]), # solution "x"
array([], dtype=float64), # residuals, empty if rank > a.shape[0] or < a.shape[1]
2, # rank
array([ 1.61842911e+01, 2.62145599e-01, 2.17200830e-16])) # singular values of "a"
所以它找到了[2., 3., 1.]
的最佳解决方案,幸运的是,它实际上是您的条件的解决方案!残差返回为空,因为如@wim所说,a
排名不足, EG:不等于方阵a
或全等级的维度。
答案 2 :(得分:2)
您正在寻找的是包含所有3个点的飞机。您的解决方案似乎对数据集2&amp;图3中的三个点是共线的,因此不存在唯一的解决方案(即,存在包含任何给定线的无限数量的平面)。这反映在LU分解中,出现“零”行,因为矩阵是等级2。
假设您坚持找到包含所有3个点的平面,您需要确保您的矩阵实际上是等级3.如果是,那么您有一个解决方案。如果它是等级2,那么包含公共线的任何平面都是有效的解决方案。
注意:如果你试图找到4点的公共平面,那么你可能会发现没有这样的解决方案。
答案 3 :(得分:0)
以数据集3为例,
(6, 7, 34) = ((5, 6, 29) + (7, 8, 39))/2
这表明矩阵中的向量不是独立的。结果,逆操作将导致巨大的错误。一种可能的解决方案是计算(A'*A+lambda*I)
的倒数,然后乘以A'
得到pseudo-inverse。其中A'
是A
的转置,lambda是一个非常小的值,I
是单位矩阵。如您在问题中提到的那样,也可以使用LU分解来实现。
但请注意,这种线性方程的解决方案并不是唯一的。伪逆方法只为您提供其中之一。您可能需要向矩阵添加另一个独立的行,并从中删除一个原始行以获得一个解决方案。