NumPy数组的维度必须以数据结构的意义理解,而不是数学意义,即它是获取标量值所需的标量索引数量。(*)
例如,这是一个3维数组:
>>> 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]])
索引两次会得到一个一维数组(向量),索引三次会得到一个标量。
X
的秩是它的维数。
>>> X.ndim
3
>>> np.rank(X)
3
轴大致等同于维度;它在广播操作中使用:
>>> 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]])
坦白说,我认为这个“rank”的定义令人困惑,因为它既不符合属性
ndim
的名称,也不符合
线性代数定义的rank。
现在关于
np.dot
,你需要理解的是,在NumPy中有三种表示向量的方式:1维数组、形状为
(n, 1)
的列向量或形状为
(1, n)
的行向量。(实际上还有更多的方式,例如作为一个形状为
(1, n, 1)
的数组,但这些方式非常少见。)当两个参数都是1维时,
np.dot
执行向量乘法,当一个参数是1维而另一个参数是2维时,执行矩阵-向量乘法,否则执行(广义的)矩阵乘法:
>>> 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对象视为标量。