Skip to main content
 首页 » 编程设计

python之numpy 中点的规范表示是什么

2025年05月04日14jirigala

我将使用 numpy 进行一些涉及 2-D 和 3D 点的几何计算。

2-D 或 3-D 点的规范表示是什么?请假定您对 numpy、数据形状等有最低限度的了解。

请您参考如下方法:

笛卡尔空间中单个点的表示有些微不足道。你甚至可以使用平面元组或列表来表示它们,矩阵运算仍然有效,但如果你想添加或缩放它们(这就是 linear spaces 的根本目的),你必须使用数组。我看不出为什么不在 d 维度中使用形状为 (d,) 的一维数组:您可以将它们同时用作列向量和行向量使用 @ matmul 运算符的矩阵边:

import numpy as np  
 
rot90 = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]])  # rotate 90 degrees around z 
inp = np.array([1, 0, 0])  # x  
 
# rotate:  
inp_rot = rot90 @ inp  # y  
# inverse transform:  
inp_invrot = inp @ rot90  # -y  

一个更好的问题是如何在笛卡尔空间中表示点的集合。如果您有 N 点,您可能需要使用二维数组。但是它应该是哪种形状,(N, d) 还是 (d, N)?答案取决于您的用例,但在没有进一步输入的情况下,您需要选择 (N, d)。

numpy中的数组默认是“C-contiguous”,也叫行优先内存布局。这意味着在创建数组时默认占用一个连续的内存块,并且项目在内存中逐行布局,以这些索引为例:

>>> np.arange(2*3).reshape(2, 3) 
array([[0, 1, 2], 
       [3, 4, 5]]) 

我们使用 numpy 的原因之一是给定类型的连续内存块占用的空间比相同大小的 native python 容器少得多,至少对于大型数据集而言。另一个原因是我们可以使用“同时”对输入切片进行操作的矢量化操作。引号在那里是因为从根本上说 CPU 的手是绑定(bind)的,但事实证明,您可以通过充分利用 CPU 缓存来实现相当大的加速。这就是内存布局发挥作用的地方:通过在数组上使用访问内存中关闭的元素的操作,您更有可能使用缓存,并且减少 RAM 和 CPU 之间的通信将导致更短的运行时间。

这个问题并非微不足道,因为沿较大的非连续维度进行矢量化可能比沿较小的连续维度进行矢量化更快。然而,在没有任何额外信息的情况下,最好将这些维度放在最后,您可能会执行矢量化操作和缩减,例如 .mean() 或 .sum()。如果 N 点位于 d 维空间中,您很可能希望分别处理每个点。矩阵乘法中的循环以及标量积和向量范数之类的东西都需要您针对给定点一个接一个地处理一个分量。

这就是为什么您会看到 numpy 和 scipy 函数通常假定形状为 (N, d) 的数组:内部维度在其次,“批处理”索引在其次。考虑例如 numpy.linalg.eig :

Parameters:  
 
a : (…, M, M) array 
 
    Matrices for which the eigenvalues and right eigenvectors will be computed 
 
Returns:     
 
w : (…, M) array 
 
    The eigenvalues, each repeated according to its multiplicity. The eigenvalues 
    are not necessarily ordered. The resulting array will be of complex type, 
    unless the imaginary part is zero in which case it will be cast to a real 
    type. When a is real the resulting eigenvalues will be real (0 imaginary 
    part) or occur in conjugate pairs 
 
[...] 

它将多维数组视为一批矩阵,其中最后两个索引对应于笛卡尔索引。类似地,返回的特征值和特征向量首先具有批处理索引,最后是向量空间索引。

一个更直接的例子是scipy.spatial.distance.pdist它计算集合中点对之间的距离:

Parameters 
 
    X : ndarray 
        An m by n array of m original observations in an n-dimensional space. 
 
[...] 

您可以再次看到笛卡尔索引排在最后的约定。 scipy.interpolate.griddata也是如此可能还有一些其他功能。

因此,如果您有充分的理由使用任何一种表示:那就去做吧。但是,如果您没有一个好的指标(例如分析两种表示的结果),您应该坚持使用 numpy 和 scipy 通常采用的“向量/矩阵批处理”方法(shape (N, d)),因为您甚至可能最终会使用其中一些函数,然后您的表示将是原生的。