问题:
输入是(i,j) - 矩阵M.期望的输出是(i ^ n,j ^ n)矩阵K,其中n是所采用的乘积的数量。获得所需输出的详细方法如下
我这样做的直接方法是生成范围内所有n个排列数的标签列表(len(np.shape(m)[0]))和范围(len(np。 shape(m)[1]))分别用于行和列。之后,您可以将它们乘以上面的最后一个项目符号点。然而,这对于大输入矩阵是不实用的 - 所以我正在寻找优化上述方法的方法。提前谢谢
示例:
输入
np.array([[1,2,3],[4,5,6]])
n = 3
的输出[[1. 2. 3. 2. 4. 6. 3. 6. 9. 2. 4. 6。 4. 8. 12. 6. 12. 18. 3. 6. 9. 6. 12. 18。 9. 18. 27。]
[4. 5. 6. 8. 10. 12. 12. 15. 18. 8. 10. 12。 16. 20. 24. 24. 30. 36. 12. 15. 18. 24. 30. 36。 36. 45. 54。]
[4. 8. 12. 5. 10. 15. 6. 12. 18. 8. 16. 24。 10. 20. 30. 12. 24. 36. 12. 24. 36. 15. 30. 45。 18. 36. 54。]
[16. 20. 24. 20. 25. 30. 24. 30. 36. 32. 40. 48。 40. 50. 60. 48. 60. 72. 48. 60. 72. 60. 75. 90。 72. 90. 108。]
[4. 8. 12. 8. 16. 24. 12. 24. 36. 5. 10. 15。 10. 20. 30. 15. 30. 45. 6. 12. 18. 12. 24. 36。 18. 36. 54。]
[16. 20. 24. 32. 40. 48. 48. 60. 72. 20. 25. 30。 40. 50. 60. 60. 75. 90. 24. 30. 36. 48. 48. 60. 72。 72. 90. 108。]
[16. 32. 48. 20. 40. 60. 24. 48. 72. 20. 40. 60。 25. 50. 75. 30. 60. 90. 24. 48. 72. 30. 60. 90。 36. 72. 108。]
[64. 80. 96. 80. 100. 120. 96. 120. 144. 80. 100. 120。 100. 125. 150. 120. 150. 180. 96. 120. 144. 120. 150. 180。 144. 180. 216。]]
部分解决方案:
我发现的最好的功能是创建这里提出的矩阵的笛卡尔积:https://stackoverflow.com/a/1235363/4003747 问题是输出不是矩阵而是数组数组。将每个数组的元素相乘得到I' m之后的值,但是以无序的方式。我已经尝试了一段时间,但我不知道如何明智地重新排序它们。
n = 3的低效解决方案:
import numpy as np
import itertools
m=np.array([[1,2,3],[4,5,6]])
def f(m):
labels_i = [list(p) for p in itertools.product(range(np.shape(m)[0]),repeat=3)]
labels_j = [list(p) for p in itertools.product(range(np.shape(m)[1]),repeat=3)]
out = np.zeros([len(labels_i),len(labels_j)])
for i in range(len(labels_i)):
for j in range(len(labels_j)):
out[i,j] = m[labels_i[i][0],labels_j[j][0]] * m[labels_i[i][1],labels_j[j][1]] * m[labels_i[i][2],labels_j[j][2]]
return out
答案 0 :(得分:6)
以下是使用broadcasting
和linear indexing
组合的矢量化方法 -
from itertools import product
# Get input array's shape
r,c = A.shape
# Setup arrays corresponding to labels i and j
arr_i = np.array(list(product(range(r), repeat=n)))
arr_j = np.array(list(product(range(c), repeat=n)))
# Use linear indexing with ".ravel()" to extract elements.
# Perform elementwise product along the rows for the final output
out = A.ravel()[(arr_i*c)[:,None,:] + arr_j].prod(2)
运行时测试和输出验证 -
In [167]: # Inputs
...: n = 4
...: A = np.array([[1,2,3],[4,5,6]])
...:
...: def f(m):
...: labels_i = [list(p) for p in product(range(np.shape(m)[0]),repeat=n)]
...: labels_j = [list(p) for p in product(range(np.shape(m)[1]),repeat=n)]
...:
...: out = np.zeros([len(labels_i),len(labels_j)])
...: for i in range(len(labels_i)):
...: for j in range(len(labels_j)):
...: out[i,j] = m[labels_i[i][0],labels_j[j][0]] \
...: * m[labels_i[i][1],labels_j[j][1]] \
...: * m[labels_i[i][2],labels_j[j][2]] \
...: * m[labels_i[i][3],labels_j[j][3]]
...: return out
...:
...: def f_vectorized(A,n):
...: r,c = A.shape
...: arr_i = np.array(list(product(range(r), repeat=n)))
...: arr_j = np.array(list(product(range(c), repeat=n)))
...: return A.ravel()[(arr_i*c)[:,None,:] + arr_j].prod(2)
...:
In [168]: np.allclose(f_vectorized(A,n),f(A))
Out[168]: True
In [169]: %timeit f(A)
100 loops, best of 3: 2.37 ms per loop
In [170]: %timeit f_vectorized(A,n)
1000 loops, best of 3: 202 µs per loop
答案 1 :(得分:0)
这应该有效:
import numpy as np
import itertools
m=np.array([[1,2,3],[4,5,6]])
n=3 # change your n here
def f(m):
labels_i = [list(p) for p in itertools.product(range(np.shape(m)[0]),repeat=n)]
labels_j = [list(p) for p in itertools.product(range(np.shape(m)[1]),repeat=n)]
out = np.zeros([len(labels_i),len(labels_j)])
for i in range(len(labels_i)):
for j in range(len(labels_j)):
out[i,j] = np.prod([m[labels_i[i][k],labels_j[j][k]] for k in range(n)])
return out