在你的榜样,C
是kron
In [4]: A=np.array([[1,2],[3,4]])
In [5]: B=np.array([[0,5],[6,7]])
In [6]: np.kron(A,B)
Out[6]:
array([[ 0, 5, 0, 10],
[ 6, 7, 12, 14],
[ 0, 15, 0, 20],
[18, 21, 24, 28]])
In [7]: np.kron(A,B)[[0,3],:]
Out[7]:
array([[ 0, 5, 0, 10],
[18, 21, 24, 28]])
kron
包含为np.outer
相同值的第一和最后一排,但他们以不同的顺序。
对于大型密集阵列,einsum
可能会提供良好的速度:
np.einsum('ij,ik->ijk',A,B).reshape(A.shape[0],-1)
sparse.kron
做同样的事情作为np.kron
:
As = sparse.csr_matrix(A); Bs ...
sparse.kron(As,Bs).tocsr()[[0,3],:].A
sparse.kron
是用Python编写的,所以你很可能修改如果是做不必要的计算。
迭代求解似乎是:
sparse.vstack([sparse.kron(a,b) for a,b in zip(As,Bs)]).A
迭代性,我不希望它是比削减下来的全部kron
更快。但短期掘到sparse.kron
逻辑的,它可能是我能做到的最好。
vstack
使用bmat
,所以计算公式是:
sparse.bmat([[sparse.kron(a,b)] for a,b in zip(As,Bs)])
但bmat
是相当复杂的,所以它不会容易进一步简化这一点。
np.einsum
解决方案不能轻易扩展为稀疏 - 没有sparse.einsum
,而中间产品是3d,稀疏不处理。
sparse.kron
使用coo
格式,这是没有好与行的工作。但是本着这个功能的精神,我已经制定了一个函数,对csr
格式矩阵的行进行迭代。像kron
和bmat
我正在构建data
,row
,col
阵列,并从这些构建coo_matrix
。这又可以转换为其他格式。
def test_iter(A, B):
m,n1 = A.shape
n2 = B.shape[1]
Cshape = (m, n1*n2)
data = np.empty((m,),dtype=object)
col = np.empty((m,),dtype=object)
row = np.empty((m,),dtype=object)
for i,(a,b) in enumerate(zip(A, B)):
data[i] = np.outer(a.data, b.data).flatten()
#col1 = a.indices * np.arange(1,a.nnz+1) # wrong when a isn't dense
col1 = a.indices * n2 # correction
col[i] = (col1[:,None]+b.indices).flatten()
row[i] = np.full((a.nnz*b.nnz,), i)
data = np.concatenate(data)
col = np.concatenate(col)
row = np.concatenate(row)
return sparse.coo_matrix((data,(row,col)),shape=Cshape)
有了这些小2×2矩阵,以及较大的(例如A1=sparse.rand(1000,2000).tocsr()
),这是关于3×比使用bmat
版本更快。对于足够大的矩阵,它比密集的版本(可能有内存错误)更好。
谢谢!我想到了运行kron并切分结果,但不确定这是否是一个好主意,因为在我的情况下,它会生成一个有数万亿行的矩阵。重写克朗是一个好主意。将介绍您建议的一些想法并查看最佳效果。 – xenocyon 2014-10-02 16:32:18
我已经完成了一个'kron'重写,与之前的'bmat'计算相比,这个重写提供了3倍的加速比。 – hpaulj 2014-10-03 00:14:20
谢谢!你重写的test_iter函数确实要快得多。 我很好奇的一件事:如果输入矩阵中的行数增加,CPU时间增加比线性更差。这似乎很奇怪,因为行没有彼此的交互。任何想法,为什么这可能是这种情况? – xenocyon 2014-10-03 20:41:08