为什么 numpy SVD 在给定一组恰好位于平面内的点时返回非法向量?

问题描述 投票:0回答:1

我正在尝试使用 numpy 的 SVD 方法安装飞机

np.linalg.svd()
。作为测试,我将在R3中使用两组点。在这两种情况下,所有点在第 3 维中的值为 100。由于我创建的点集完全在
Z=100
平面内,我希望:

  1. 第三个奇异值将为 0(在机器精度内)。
  2. vh
    的第三列将是
    [0, 0, 1]
    (在机器精度内)。

套装 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 列的前两个维度更接近于零(更像是在机器精度范围内),但这对于我的拟合应用程序是可行的。

第 2 组

对于这个集合中的所有点,第一个和第二个值的大小都小于第三个值。

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 的东西不能提供更高精度的结果? 我只是没有正确使用它还是误解了结果?

python numpy linear-algebra
1个回答
0
投票

编辑:查看您编辑的帖子。

我认为你想要从你的 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.        ]]))


© www.soinside.com 2019 - 2024. All rights reserved.