假设我有一个(稀疏)矩阵M
大小(N*N, N*N)
。我想从这个矩阵中选择grid
(一个(n,m)
数组,其中n*m=N
)为True的外积(它是一个布尔2D数组,na=grid.sum()
)。这可以按如下方式完成
result = M[np.outer( grid.flatten(),grid.flatten() )].reshape (( N, N ) )
result
是一个(na,na)
稀疏数组(和na < N
)。前一行是我想要实现的:从grid
的乘积中获取M的元素,并从数组中挤出那些不正确的元素。
当n
和m
(以及N
)增长,而M
和result
是稀疏矩阵时,我无法有效地执行此操作在记忆或速度方面。我最近尝试的是:
result = sp.lil_matrix ( (1, N*N), dtype=np.float32 )
# Calculate outer product
A = np.einsum("i,j", grid.flatten(), grid.flatten())
cntr = 0
it = np.nditer ( A, flags=['multi_index'] )
while not it.finished:
if it[0]:
result[0,cntr] = M[it.multi_index[0], it.multi_index[1]]
cntr += 1
# reshape result to be a N*N sparse matrix
最后一次重塑可以由this approach完成,但我还没有到达那里,因为while循环需要永远。
我也尝试过选择A的非零元素,然后循环,但这会占用所有内存:
A=np.einsum("i,j", grid.flatten(), grid.flatten())
nzero = A.nonzero() # This eats lots of memory
cntr = 0
for (i,j) in zip (*nzero):
temp_mat[0,cntr] = M[i,j]
cnt += 1
上面例子中的'n'和'm'大约是300.
答案 0 :(得分:1)
我不知道这是错字还是代码错误,但您的示例缺少iternext
:
R=[]
it = np.nditer ( A, flags=['multi_index'] )
while not it.finished:
if it[0]:
R.append(M[it.multi_index])
it.iternext()
我认为附加到列表比R[ctnr]=...
更简单,更快捷。如果R
是常规数组,并且稀疏索引较慢(甚至是最快的lil
格式),那么它就具有竞争力。
ndindex
包含了对nditer的使用:
R=[]
for index in np.ndindex(A.shape):
if A[index]:
R.append(M[index])
ndenumerate
也有效:
R = []
for index,a in np.ndenumerate(A):
if a:
R.append(M[index])
但我想知道你是否真的想推进cntr
每个it
步骤,而不仅仅是True
个案例。否则,将result
重塑为(N,N)
并没有多大意义。但在那种情况下,不是你的问题
M[:N, :N].multiply(A)
或M
是一个密集阵列:
M[:N, :N]*A
事实上,如果M
和A
都稀疏,那么.data
的{{1}}属性将与multiply
列表相同。< / p>
R