如何通过广播密集的1d数组元素乘以一个scipy.sparsematrix?
假设我有一个2d稀疏数组。 在我真正的用例中,行和列的数量都要大得多(比如20000和50000),因此当使用密集表示法时,它不能适应内存:
>>> import numpy as np >>> import scipy.sparse as ssp >>> a = ssp.lil_matrix((5, 3)) >>> a[1, 2] = -1 >>> a[4, 1] = 2 >>> a.todense() matrix([[ 0., 0., 0.], [ 0., 0., -1.], [ 0., 0., 0.], [ 0., 0., 0.], [ 0., 2., 0.]])
现在假设我有一个密度为1d的数组,其大小为3的所有非零元素(在我的现实生活中是50000):
>>> d = np.ones(3) * 3 >>> d array([ 3., 3., 3.])
我想用numpy的通常广播语义来计算a和d的元素相乘。 然而,scipy中的稀疏matrix是np.matrix的:'*'运算符被重载,以使其行为像一个matrix乘法而不是元素乘法:
>>> a * d array([ 0., -3., 0., 0., 6.])
一种解决scheme是将“a”切换到“*”运算符的数组语义,这将给出预期的结果:
>>> a.toarray() * d array([[ 0., 0., 0.], [ 0., 0., -3.], [ 0., 0., 0.], [ 0., 0., 0.], [ 0., 6., 0.]])
但是我不能这样做,因为toarray()的调用会实现不适合内存的密集版本(并且结果也会很密集):
>>> ssp.issparse(a.toarray()) False
任何想法如何build立这个,而只保留稀疏的数据结构,而不必做一个'a'的列上不够高效的python循环?
我在scipy.org也回复了,但是我想我应该在这里添加一个答案,以防其他人在search时find这个页面。
你可以把vector变成一个稀疏的对angularmatrix,然后用matrix乘法(用*)和广播一样做,但效率很高。
>>> d = ssp.lil_matrix((3,3)) >>> d.setdiag(np.ones(3)*3) >>> a*d <5x3 sparse matrix of type '<type 'numpy.float64'>' with 2 stored elements in Compressed Sparse Row format> >>> (a*d).todense() matrix([[ 0., 0., 0.], [ 0., 0., -3.], [ 0., 0., 0.], [ 0., 0., 0.], [ 0., 6., 0.]])
希望有所帮助!
我想A.multiply(B)应该scipy稀疏工作。 该方法乘“点”乘法,而不是matrix乘法。
HTH
那么,这是一个简单的代码,将做你想要的。 我不知道它是否有效,所以拿它或离开它:
import scipy.sparse as ssp def pointmult(a,b): x = a.copy() for i in xrange(a.shape[0]): if x.data[i]: for j in xrange(len(x.data[i])): x.data[i] *= b[x.rows[i]] return x
它只能与lilmatrix一起使用,所以如果你想要与其他格式一起工作,你必须做一些改变。