不使用for循环构建numpy数组



如果我有两个形状为(N, 3)的numpy数组

array1 = np.array([[x1, y1, 1],
........
[xn, yn, 1]])
array2 = np.array([[u1, v1, 1],
........
[un, vn, 1]])

我想要

A = np.array([[x1 * u1, x1 * v1, x1, y1 * u1, y1 * v1, y1, u1, v1, 1],
.........
[xn * un, xn * vn, xn, yn * un, yn * vn, yn, un, vn, 1]]

在不使用for循环迭代的情况下,我该如何做到这一点?

您显然希望沿第二维广播乘法。解决这类问题的诀窍是记住,numpy默认情况下是按照C的顺序移动/重塑的。

让我们分析输出的行,看看如何排列乘积。你有

[x1 * u1, x1 * v1, x1 * 1, y1 * u1, y1 * v1, y1 * 1, u1, v1, 1]

这是

的修改版本
[[x1 * u1, x1 * v1, x1 * 1],
[y1 * u1, y1 * v1, y1 * 1],
[ 1 * u1,  1 * v1,  1 * 1]]

依次是乘积

array1[0][:, None] * array2[0][None, :]

因此,您想要的产品保留第一个维度,并广播第二个维度,如上所示。然后将最后两个维度折叠在一起,得到部分克罗内克积:

A = (array1[:, :, None] * array2[:, None, :]).reshape(array1.shape[0], -1)

这就是Kronecker产品。您可以使用np.kron()函数这样做:

import numpy as np
array1 = np.array([[1,2,1], 
[3,4,1]])
array2 = np.array([[3,4,1], 
[1,0,1]])
N = array1.shape[0]
result = np.kron(array1, array2)
# A (NxN) x 9 output
#array([[ 3,  4,  1,  6,  8,  2,  3,  4,  1],
#       [ 1,  0,  1,  2,  0,  2,  1,  0,  1],
#       [ 9, 12,  3, 12, 16,  4,  3,  4,  1],
#       [ 3,  0,  3,  4,  0,  4,  1,  0,  1]])

如果你想要一个一对一的克罗内克产品,你也可以使用:

# N x 9 
np.kron(array1, array2)[0:N*N:N, :]
#array([[ 3,  4,  1,  6,  8,  2,  3,  4,  1],
#       [ 9, 12,  3, 12, 16,  4,  3,  4,  1]])

如果性能很重要,不建议使用。

最新更新