为什么 Numpy 有维度 (n,) 而不是 (n,1) 只有
Why Numpy has dimension (n,) instead of (n,1) only
我对此好奇有一段时间了。我可以忍受,但如果不小心,它总是会咬我,所以我决定 post 在这里。假设下面的例子(Numpy version = 1.8.2):
a = array([[0, 1], [2, 3]])
print shape(a[0:0, :]) # (0, 2)
print shape(a[0:1, :]) # (1, 2)
print shape(a[0:2, :]) # (2, 2)
print shape(a[0:100, :]) # (2, 2)
print shape(a[0]) # (2, )
print shape(a[0, :]) # (2, )
print shape(a[:, 0]) # (2, )
不知道别人怎么想的,反正我觉得是不符合的。最后一行是列向量,而倒数第二行是行向量,它们应该有不同的维度——在线性代数中它们是这样的! (第 5 行是另一个惊喜,但我暂时忽略它)。考虑第二个例子:
solution = scipy.sparse.linalg.dsolve.linsolve.spsolve(A, b) # solution of dimension (n, )
analytic = reshape(f(x, y), (n, 1)) # analytic of dimension (n, 1)
error = solution - analytic
现在错误的维度是(n, n)。是的,在第二行我应该使用 (n, ) 而不是 (n, 1),但是为什么呢?我以前经常使用 MATLAB,其中一维向量具有维度 (n, 1),linspace/arange returns 维度数组 (n, 1),并且永远不存在 (n, )。但是在 Numpy 中 (n, 1) 和 (n, ) 并存,并且有很多单独处理维度的函数:atleast、newaxis 和 reshape 的不同用途,但对我来说这些函数更多的是混乱而不是帮助。如果一个数组打印成 [1,2,3],那么直觉上维度应该是 [1,3] 而不是 [3,],对吗?如果 Numpy 没有 (n, ),我只能看到清晰度的提高,而不是功能的损失。
所以这背后一定有一些设计原因。我一直在不时地寻找,没有找到明确的答案或报告。有人可以帮助澄清这种困惑或为我提供一些有用的参考资料吗?非常感谢您的帮助。
numpy
的哲学不是一般情况下 a[:, 0]
是 "column vector" 而 a[0, :]
是 "row vector"。相反,它们都是,非常简单,向量——即具有一维且只有一维的数组。这实际上是高度合乎逻辑和一致的(但是,是的,对于我们这些习惯了 Matlab 的人来说可能会很烦人)。
我说 "in the general case" 因为这适用于 numpy 最通用的数据结构 array
,它适用于各种多维密集数据存储和操作应用程序——而不仅仅是矩阵数学。具有 "rows" 和 "columns" 是数组操作的高度专业化上下文——但是,是的,一个非常常见的上下文:这就是为什么 numpy
也提供 matrix
class。将您的数组转换为 numpy.matrix
(或使用 matrix
构造函数而不是 array
开始),您将看到更接近您预期的行为。有关详细信息,请参阅 What are the differences between numpy arrays and matrices? Which one should I use?
对于处理二维以上的情况,请查看 numpy.expand_dims
函数。虽然语法是烦人的冗余和非Python的冗长,当我处理超过2维的数组时(所以不能使用matrix
),我永远不得不使用expand_dims
来做这种东西:
A -= numpy.expand_dims( A.mean( axis=2 ), 2 ) # subtract mean-across-layers from A
而不是
A -= A.mean( axis=2 ) # throw an exception while naively attempting to subtract mean-across-layers from A
但相比之下,考虑一下 Matlab。 Matlab 隐含地断言不存在一维对象,并且事物可以拥有的最小维数是 2。当然,你和我都对此习以为常,但花点时间意识到它是多么的武断这是。一个基本的一维物体和一个二维物体恰好在其一个维度上具有 extent 1 之间显然存在概念上的差异:后者可以在其第二个维度上增长,而前者则不允许甚至知道二次元是什么意思——为什么要知道?因此 a.shape==(N,)
和 a.shape==(N,1)
作为单独的案例是完全合理的。你不妨问 "why is it not (N, 1, 1)
?" 或 "why is it not (N, 1, 1, 1, 1, 1, 1)
?"
我对此好奇有一段时间了。我可以忍受,但如果不小心,它总是会咬我,所以我决定 post 在这里。假设下面的例子(Numpy version = 1.8.2):
a = array([[0, 1], [2, 3]])
print shape(a[0:0, :]) # (0, 2)
print shape(a[0:1, :]) # (1, 2)
print shape(a[0:2, :]) # (2, 2)
print shape(a[0:100, :]) # (2, 2)
print shape(a[0]) # (2, )
print shape(a[0, :]) # (2, )
print shape(a[:, 0]) # (2, )
不知道别人怎么想的,反正我觉得是不符合的。最后一行是列向量,而倒数第二行是行向量,它们应该有不同的维度——在线性代数中它们是这样的! (第 5 行是另一个惊喜,但我暂时忽略它)。考虑第二个例子:
solution = scipy.sparse.linalg.dsolve.linsolve.spsolve(A, b) # solution of dimension (n, )
analytic = reshape(f(x, y), (n, 1)) # analytic of dimension (n, 1)
error = solution - analytic
现在错误的维度是(n, n)。是的,在第二行我应该使用 (n, ) 而不是 (n, 1),但是为什么呢?我以前经常使用 MATLAB,其中一维向量具有维度 (n, 1),linspace/arange returns 维度数组 (n, 1),并且永远不存在 (n, )。但是在 Numpy 中 (n, 1) 和 (n, ) 并存,并且有很多单独处理维度的函数:atleast、newaxis 和 reshape 的不同用途,但对我来说这些函数更多的是混乱而不是帮助。如果一个数组打印成 [1,2,3],那么直觉上维度应该是 [1,3] 而不是 [3,],对吗?如果 Numpy 没有 (n, ),我只能看到清晰度的提高,而不是功能的损失。
所以这背后一定有一些设计原因。我一直在不时地寻找,没有找到明确的答案或报告。有人可以帮助澄清这种困惑或为我提供一些有用的参考资料吗?非常感谢您的帮助。
numpy
的哲学不是一般情况下 a[:, 0]
是 "column vector" 而 a[0, :]
是 "row vector"。相反,它们都是,非常简单,向量——即具有一维且只有一维的数组。这实际上是高度合乎逻辑和一致的(但是,是的,对于我们这些习惯了 Matlab 的人来说可能会很烦人)。
我说 "in the general case" 因为这适用于 numpy 最通用的数据结构 array
,它适用于各种多维密集数据存储和操作应用程序——而不仅仅是矩阵数学。具有 "rows" 和 "columns" 是数组操作的高度专业化上下文——但是,是的,一个非常常见的上下文:这就是为什么 numpy
也提供 matrix
class。将您的数组转换为 numpy.matrix
(或使用 matrix
构造函数而不是 array
开始),您将看到更接近您预期的行为。有关详细信息,请参阅 What are the differences between numpy arrays and matrices? Which one should I use?
对于处理二维以上的情况,请查看 numpy.expand_dims
函数。虽然语法是烦人的冗余和非Python的冗长,当我处理超过2维的数组时(所以不能使用matrix
),我永远不得不使用expand_dims
来做这种东西:
A -= numpy.expand_dims( A.mean( axis=2 ), 2 ) # subtract mean-across-layers from A
而不是
A -= A.mean( axis=2 ) # throw an exception while naively attempting to subtract mean-across-layers from A
但相比之下,考虑一下 Matlab。 Matlab 隐含地断言不存在一维对象,并且事物可以拥有的最小维数是 2。当然,你和我都对此习以为常,但花点时间意识到它是多么的武断这是。一个基本的一维物体和一个二维物体恰好在其一个维度上具有 extent 1 之间显然存在概念上的差异:后者可以在其第二个维度上增长,而前者则不允许甚至知道二次元是什么意思——为什么要知道?因此 a.shape==(N,)
和 a.shape==(N,1)
作为单独的案例是完全合理的。你不妨问 "why is it not (N, 1, 1)
?" 或 "why is it not (N, 1, 1, 1, 1, 1, 1)
?"