在numpy中解释昏暗,形状,等级,尺寸和轴之间的差异

时间:2014-03-01 13:20:50

标签: python arrays numpy matrix

我是python和numpy的新手。我阅读了几个教程,但仍然对昏暗,等级,形状,aix和尺寸的差异感到困惑。我的想法似乎停留在矩阵表示。所以,如果你说A是一个看起来像这样的矩阵:

A = 

1 2 3
4 5 6

然后我能想到的是一个2x3矩阵(两行三列)。在这里,我知道形状是2x3。但我真的无法超越二维矩阵的思维。我不明白例如dot() documentation,当它说“对于N维时,它是a的最后一个轴上的和和b的倒数第二个”。我很困惑,无法理解这一点。我不明白,如果V是N:1向量而M是N:N矩阵,点(V,M)或点(M,V)如何工作以及它们之间的差异。

那么有人可以向我解释什么是N维数组,什么是形状,什么是轴以及它与dot()函数的文档有什么关系?如果解释可视化这些想法会很棒。

3 个答案:

答案 0 :(得分:11)

NumPy数组的维度必须在data structures sense中理解,而不是数学意义,即它是获取标量值所需的标量索引的数量。(*)

例如,这是一个三维数组:

>>> X = np.arange(24).reshape(2, 3, 4)
>>> X
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

索引一次得到一个二维数组(矩阵):

>>> X[0]
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

索引两次给出1-d数组(向量),索引三次给出一个标量。

X的排名是维度数:

>>> X.ndim
3
>>> np.rank(X)
3

Axis大致是维度的同义词;它用于广播业务:

>>> X.sum(axis=0)
array([[12, 14, 16, 18],
       [20, 22, 24, 26],
       [28, 30, 32, 34]])
>>> X.sum(axis=1)
array([[12, 15, 18, 21],
       [48, 51, 54, 57]])
>>> X.sum(axis=2)
array([[ 6, 22, 38],
       [54, 70, 86]])

说实话,我发现“排名”这个定义令人困惑,因为它既不匹配属性ndim也不匹配linear algebra definition of rank

现在关于np.dot,你必须要了解的是,在NumPy中有三种表示向量的方法:1-d数组,形状(n, 1)的列向量或形状的行向量(1, n)。 (实际上,有更多的方法,例如作为(1, n, 1)形状的数组,但这些很少见。)np.dot当两个参数都是1-d时执行向量乘法,当一个参数时执行矩阵向量乘法是1-d而另一个是2-d,否则它执行(广义)矩阵乘法:

>>> A = np.random.randn(2, 3)
>>> v1d = np.random.randn(2)
>>> np.dot(v1d, A)
array([-0.29269547, -0.52215117,  0.478753  ])
>>> vrow = np.atleast_2d(v1d)
>>> np.dot(vrow, A)
array([[-0.29269547, -0.52215117,  0.478753  ]])
>>> vcol = vrow.T
>>> np.dot(vcol, A)
Traceback (most recent call last):
  File "<ipython-input-36-98949c6de990>", line 1, in <module>
    np.dot(vcol, A)
ValueError: matrices are not aligned

规则“对a的最后一个轴上的乘积和b的倒数第二个”进行匹配并推广矩阵乘法的通用定义。

(*)dtype=object的数组有点异常,因为它们将任何Python对象视为标量。

答案 1 :(得分:4)

np.dot是矩阵乘法的推广。 在规则矩阵乘法中,(N,M)形矩阵乘以(M,P)形矩阵得到(N,P)形矩阵。可以认为所得到的形状是通过将两个形状挤压在一起((N,M,M,P))然后移除中间数字M(以产生(N,P))而形成的。这是np.dot在推广到更高维数组时保留的属性。

当文档说,

  

“对于N维度,它是a和a的最后一个轴上的和积   b的倒数第二个。

这是说到这一点。形状为(u,v,M)的数组(w,x,y,M,z)的数组将生成一个形状为(u,v,w,x,y,z)的数组。


让我们看看这条规则在应用于

时的外观
In [25]: V = np.arange(2); V
Out[25]: array([0, 1])

In [26]: M = np.arange(4).reshape(2,2); M
Out[26]: 
array([[0, 1],
       [2, 3]])

首先,简单的部分:

In [27]: np.dot(M, V)
Out[27]: array([1, 3])

这里并不奇怪;这只是矩阵向量乘法。

现在考虑

In [28]: np.dot(V, M)
Out[28]: array([2, 3])

看看V和M的形状:

In [29]: V.shape
Out[29]: (2,)

In [30]: M.shape
Out[30]: (2, 2)

所以np.dot(V,M)就像(2,)形状矩阵与(2,2)形矩阵的矩阵乘法,这应该产生(2,)形状的矩阵。

V的最后一个(也是唯一的)轴和M的倒数第二个轴(又称M的第一个轴)乘以并求和,只留下M的最后一个轴。

如果您想要看到这个:np.dot(V, M)看起来好像V有1行和2列:

[[0, 1]] * [[0, 1],
            [2, 3]] 

等等,当V乘以M时,np.dot(V, M)等于

[[0*0 + 1*2],     [2, 
 [0*1 + 1*3]]   =  3] 

但是,我并不建议尝试以这种方式可视化NumPy阵列 - 至少我从来没有这样做过。我几乎专注于形状。

(2,) * (2,2)
   \   /
    \ /
    (2,)

你只要想到“中间”轴是点缀的,并从最终的形状中消失。


np.sum(arr, axis=0)告诉NumPy将arr 中的元素求和第0轴。如果arr是2维,则第0轴是行。例如,如果arr看起来像这样:

In [1]: arr = np.arange(6).reshape(2,3); arr
Out[1]: 
array([[0, 1, 2],
       [3, 4, 5]])

然后np.sum(arr, axis=0)将沿着列相加,因此消除第0轴(即行)。

In [2]: np.sum(arr, axis=0)
Out[2]: array([3, 5, 7])

3是0 + 3的结果,5等于1 + 4,7等于2 + 5.

注意arr具有形状(2,3),并且在求和之后,第0轴被移除,因此结果是形状(3,)。第0轴的长度为2,每个总和由添加这2个元素组成。形状(2,3)“变成”(3,)。您可以提前知道结果形状!这有助于指导您的思考。

为了测试您的理解,请考虑np.sum(arr, axis=1)。现在删除了1轴。因此,结果形状将为(2,),结果中的元素将是3个值的总和。

In [3]: np.sum(arr, axis=1)
Out[3]: array([ 3, 12])

3等于0 + 1 + 2,12等于3 + 4 + 5.


所以我们看到将轴相加从结果中消除轴。这与np.dot有关,因为np.dot执行的计算是产品的总和。由于np.dot沿某些轴执行求和操作,因此将从结果中移除该轴。这就是为什么将np.dot应用于形状(2,)和(2,2)的数组会产生一个形状(2,)的数组。将两个数组中的前两个相加,消除两者,仅在第二个数组中留下第二个2。

答案 2 :(得分:1)

在你的情况下,

  1. A是一个二维数组,即一个矩阵,其形状为(2,3)。来自numpy.matrix的文档字符串:

      

    矩阵是一种专门的二维阵列,通过操作保留其二维特性。

  2. numpy.rank返回数组的维度的数量,这与rank in linear algebra的概念完全不同,例如A是维度/等级2的数组。

  3. np.dot(V, M)V.dot(M)将矩阵VM相乘。请注意,numpy.dot尽可能地进行乘法运算。 如果V为N:1且M为N:N ,则V.dot(M)会引发ValueError
  4. e.g:

    In [125]: a
    Out[125]: 
    array([[1],
           [2]])
    
    In [126]: b
    Out[126]: 
    array([[2, 3],
           [1, 2]])
    
    In [127]: a.dot(b)
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-127-9a1f5761fa9d> in <module>()
    ----> 1 a.dot(b)
    
    ValueError: objects are not aligned
    

    编辑:

    我不明白(N,)和(N,1)的形状之间的区别,它与dot()文档有关。

    V形状(N,)表示长度为N的1D数组,而形状(N,1)表示具有N行,1列的2D数组:

    In [2]: V = np.arange(2)
    
    In [3]: V.shape
    Out[3]: (2,)
    
    In [4]: Q = V[:, np.newaxis]
    
    In [5]: Q.shape
    Out[5]: (2, 1)
    
    In [6]: Q
    Out[6]: 
    array([[0],
           [1]])
    

    正如np.dot的文档字符串所说:

      

    对于二维阵列,它相当于矩阵乘法,对于1-D   阵列到载体的内积(没有复共轭)。

    如果其中一个参数是向量,它还执行向量矩阵乘法。说V.shape==(2,); M.shape==(2,2)

    In [17]: V
    Out[17]: array([0, 1])
    
    In [18]: M
    Out[18]: 
    array([[2, 3],
           [4, 5]])
    
    In [19]: np.dot(V, M)  #treats V as a 1*N 2D array
    Out[19]: array([4, 5]) #note the result is a 1D array of shape (2,), not (1, 2)
    
    In [20]: np.dot(M, V)  #treats V as a N*1 2D array
    Out[20]: array([3, 5]) #result is still a 1D array of shape (2,), not (2, 1)
    
    In [21]: Q             #a 2D array of shape (2, 1)
    Out[21]: 
    array([[0],
           [1]])
    
    In [22]: np.dot(M, Q)  #matrix multiplication
    Out[22]: 
    array([[3],            #gets a result of shape (2, 1)
           [5]])