Numpy/Python:作为输入矩阵笛卡尔积乘法的有效矩阵

Numpy/Python:作为输入矩阵笛卡尔积乘法的有效矩阵,python,arrays,numpy,matrix,Python,Arrays,Numpy,Matrix,问题: 输入是(i,j)-矩阵M。期望输出是(i^n,j^n)矩阵K,其中n是所取乘积的数量。获取所需输出的详细方法如下 生成n行排列I的所有数组(I**n个数组的总数) 生成n列置换J的所有数组(J**n个数组的总数) K[i,j]=m[i[0],j[0]]*…*m[I[n],J[n]]表示范围内的所有n(len(J)) 我所做的最简单的方法是,分别为行和列生成范围(len(np.shape(m)[0])和范围(len(np.shape(m)[1])中的所有n个数字排列的标签列表。之后,你

问题:

输入是(i,j)-矩阵M。期望输出是(i^n,j^n)矩阵K,其中n是所取乘积的数量。获取所需输出的详细方法如下

  • 生成n行排列I的所有数组(I**n个数组的总数)
  • 生成n列置换J的所有数组(J**n个数组的总数)
  • K[i,j]=m[i[0],j[0]]*…*m[I[n],J[n]]表示范围内的所有n(len(J))
我所做的最简单的方法是,分别为行和列生成范围(len(np.shape(m)[0])和范围(len(np.shape(m)[1])中的所有n个数字排列的标签列表。之后,你可以像上面最后一点那样将它们相乘。然而,这对于大型输入矩阵是不实用的——因此我正在寻找优化上述矩阵的方法。先谢谢你

例如:

输入

np.数组([[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. 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.]

部分解决方案:

我发现的最好的方法是创建此处提出的矩阵笛卡尔积的函数: 问题在于,输出不是一个矩阵,而是一个数组数组。将每个数组的元素相乘得到我想要的值,但是是无序的。我已经尝试了一段时间,但我不知道如何明智地重新排序

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
这应该起作用:

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

这是一种矢量化方法,使用和的组合-

运行时测试和输出验证-

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

如果您实现了一个低效的版本,请添加到问题中?很抱歉。完成。因此,对于
n=4
,您需要在那里添加
*m[labels_i[i][3],labels_j[j][3]
,对吗?我猜更高的
n
也是如此。
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