我正在尝试使用 numpy 的 SVD 方法安装飞机
np.linalg.svd()
。作为测试,我将在R3中使用两组点。在这两种情况下,所有点在第 3 维中的值为 100。由于我创建的点集完全在 Z=100
平面内,我希望:
vh
的第三列将是[0, 0, 1]
(在机器精度内)。对于这个集合中的某些点,第一个和第二个值的幅度比第三个值大得多。
pts = [[2345,-124, 100], [981, -123, 100], [4987,12345, 100], [-1324, 0, 100]]
svd = np.linalg.svd(pts)
这里的结果大致符合预期:
svd[1]
产生 array([13349.56221861, 2705.21722461, 158.26983058])
。我希望第三个奇异值更接近 0,因为我的点完全适合一个平面,但它至少足够清楚地表明 svd[2]
的第三列将是我的平面法向量。
svd[2]
产生以下内容:
array([[-0.38833201, -0.92148669, -0.00778029],
[-0.92117922, 0.38840419, -0.02389612],
[ 0.02504185, -0.00211259, -0.99968417]])
再次,它很接近。我希望第 3 列的前两个维度更接近于零(更像是在机器精度范围内),但这对于我的拟合应用程序是可行的。
对于这个集合中的所有点,第一个和第二个值的大小都小于第三个值。
pts = [[57, 37, 100], [34, 37, 100], [11, -37, 100], [-11, 38, 100]]
svd = np.linalg.svd(pts)
这就是事情开始看起来很奇怪的地方。
svd[1]
产生 array([209.35774076, 64.78329726, 46.58820429])
。这令人惊讶。第三个奇异值应该更接近于 0.
svd[2]
产生以下内容:
array([[-0.23396901, -0.2018738 , -0.95105493],
[ 0.31100035, 0.91126958, -0.26993803],
[-0.92116084, 0.35893555, 0.15042602]])
这太出乎意料了。
vh
的第三列与[0, 0, 1]
相当远。外机精度当然好。它实际上更接近[1, 0, 0]
.
这里发生了什么?是否有关于如何在 numpy 中实现 SVD 的东西不能提供更高精度的结果? 我只是没有正确使用它还是误解了结果?
编辑:查看您编辑的帖子。
我认为你想要从你的 SVD 中得到的是将你的点转移到它们的平均值之后的结果。这样做后你应该得到你想要的确切结果。
pts = np.array([[57, 37, 100], [34, 37, 100], [11, -37, 100], [-11, 38, 100]])
pts = pts - pts.mean(axis=0)
svd = np.linalg.svd(pts)
(array([[-0.45221016, 0.51373144, 0.15971725, 0.71139045],
[-0.31606121, 0.06525962, 0.8397871 , -0.43658232],
[ 0.83162358, 0.2416381 , 0.42832508, 0.25797456],
[-0.06335221, -0.82062916, 0.29289188, 0.48658876]]),
array([67.13174076, 47.06197384, 0. ]),
array([[-0.39738768, -0.91765082, -0. ],
[ 0.91765082, -0.39738768, -0. ],
[ 0. , 0. , 1. ]]))