我是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()函数的文档有什么关系?如果解释可视化这些想法会很棒。
答案 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)
在你的情况下,
A
是一个二维数组,即一个矩阵,其形状为(2,3)。来自numpy.matrix
的文档字符串:
矩阵是一种专门的二维阵列,通过操作保留其二维特性。
numpy.rank
返回数组的维度的数量,这与rank in linear algebra的概念完全不同,例如A
是维度/等级2的数组。
np.dot(V, M)
或V.dot(M)
将矩阵V
与M
相乘。请注意,numpy.dot尽可能地进行乘法运算。 如果V为N:1且M为N:N ,则V.dot(M)
会引发ValueError
。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]])