And*_*Pye 2 python numpy matrix linear-algebra
我正在使用 numpy 执行矩阵乘法,但我不知道如何利用 numpy 进行 3d 矩阵乘法。
假设我有一个 3x3 矩阵 a,我将它乘以 3x1 向量 b。这将给出一个 3x1 向量 c。
这是在 numpy 中完成的:
# (3, 3) * (3, 1) -> (3, 1)
c = np.matmul(a, b)
Run Code Online (Sandbox Code Playgroud)
好的,现在我想对 3d 矩阵执行类似的操作,该矩阵本质上是 2500 个 3x3 矩阵。现在我正在做一些事情,其效果是:
# (2500, 3, 3) * (2500, 3, 1) -> list of (3, 1) vectors with length 2500
C = [np.matmul(a, b) for a, b in zip(A, B)]
Run Code Online (Sandbox Code Playgroud)
它返回 (3, 1) 向量的列表。
我宁愿不循环,而是充分利用 numpy 的矢量化和矩阵/张量产品。有什么手术可以做吗...
# (2500, 3, 3) * (2500, 3, 1) -> (2500, 3, 1)
np.<function>(A, B, <args>)
Run Code Online (Sandbox Code Playgroud)
我看过有关使用 np.tensordot 的内容,但我不知道如何设置轴。
np.tensordot(A, B, axes=???)
Run Code Online (Sandbox Code Playgroud)
对于您拥有的 3 维数组(或 3 阶张量),您可以使用np.einsum doc进行更复杂的矩阵乘法。根据您的具体情况,您可以使用以下内容
>>> import numpy as np
>>> x = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> y = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> np.einsum('ijk,ikl->ijl', x, y) # still shape (3, 3, 3)
Run Code Online (Sandbox Code Playgroud)
特别是,该einsum表达式'ijk,ikl->ijl'意味着对每个i矩阵进行常规矩阵乘法jk,kl->jl,并将结果放入i结果张量 (ndarray) 的第一个条目中。该过程的更一般形式可以是
np.einsum('...jk,...kl->...jl', x, y)
Run Code Online (Sandbox Code Playgroud)
其中每个张量(ndarray)前面可以有任意数量的维度。
请参阅以下内容了解完整示例:
>>> import numpy as np
>>> x = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> x
array([[[0, 0, 1],
[2, 2, 1],
[2, 1, 1]],
[[2, 0, 2],
[2, 2, 1],
[2, 2, 2]],
[[2, 2, 2],
[1, 1, 2],
[0, 2, 2]]])
>>> y = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> y
array([[[0, 0, 1],
[2, 1, 0],
[0, 0, 2]],
[[1, 2, 0],
[2, 0, 1],
[2, 2, 1]],
[[0, 2, 1],
[0, 1, 0],
[0, 2, 1]]])
>>> np.einsum('ijk,ikl->ijl', x, y)
array([[[ 0, 0, 2],
[ 4, 2, 4],
[ 2, 1, 4]],
[[ 6, 8, 2],
[ 8, 6, 3],
[10, 8, 4]],
[[ 0, 10, 4],
[ 0, 7, 3],
[ 0, 6, 2]]])
>>> np.einsum('...ij,...jk->...ik', x, y)
array([[[ 0, 0, 2],
[ 4, 2, 4],
[ 2, 1, 4]],
[[ 6, 8, 2],
[ 8, 6, 3],
[10, 8, 4]],
[[ 0, 10, 4],
[ 0, 7, 3],
[ 0, 6, 2]]])
Run Code Online (Sandbox Code Playgroud)