我正在尝试在巨大的矩阵与其自身之间找到点积。
矩阵的形状(371744,36154) Num of NonZero - 577731 [非常稀疏]
mat1是scipy.sparse.csr_matrix 如果我使用 mat1 * mat1.T 我得到一个值错误,这看起来像是因为在结果矩阵中有太多的非零元素,并且索引指针根据here溢出
dp_data = data_m * data_m.T
File "/usr/lib/python2.7/dist-packages/scipy/sparse/base.py", line 247, in __mul__
return self._mul_sparse_matrix(other)
File "/usr/lib/python2.7/dist-packages/scipy/sparse/base.py", line 300, in _mul_sparse_matrix
return self.tocsr()._mul_sparse_matrix(other)
File "/usr/lib/python2.7/dist-packages/scipy/sparse/compressed.py", line 290, in _mul_sparse_matrix
indices = np.empty(nnz, dtype=np.intc)
ValueError: negative dimensions are not allowed
我也尝试了 np.dot
但是doc说,
“从NumPy 1.7开始,np.dot不知道稀疏矩阵,因此使用它会导致意外的结果或错误。应首先获得相应的密集矩阵”
当我到mat1.toarray()或todense()时,我得到一个内存错误,因为矩阵是巨大的!!我有16GB的内存!该程序似乎适用于较小的输入!
data_array = data_m.toarray()
File "/usr/lib/python2.7/dist-packages/scipy/sparse/compressed.py", line 550, in toarray
return self.tocoo(copy=False).toarray()
File "/usr/lib/python2.7/dist-packages/scipy/sparse/coo.py", line 219, in toarray
B = np.zeros(self.shape, dtype=self.dtype)
MemoryError
我正在使用 Numpy版本1.8.1 Numpy版本0.9.0
我怎么做这个乘法?
答案 0 :(得分:3)
将点积称为稀疏矩阵的方法:
dp_data = data_m.dot(data_m)
numpy.dot是一个Universal Function,它不知道你的矩阵的稀疏性,而scipy.sparse.csc_matrix.dot是一个为你的矩阵类型量身定制的方法,因此使用稀疏算法。
答案 1 :(得分:1)
首先,稀疏输出矩阵的大小和计算所需的CPU工作量取决于稀疏矩阵的结构。如果有很多空行,事情会变得更容易。另一方面,如果您的数据均匀分布,则需要计算很多。
首先要意识到的是,在这种特定情况下(a * a.T
),您实际上是计算每行的每个行(36154元素向量)的点积。这有助于您将计算时间减半,因为结果将是对称的。 (这为您留下了大约5亿个矢量点产品。)
现在,无论你是否匆忙,问题都是很多。如果您赶时间(性能很重要),那么可能有一些方法可以使计算更快,具体取决于数据中非零的分布方式。
一个相当简单的算法如下:
# a is in row-form (n_row lists of non-zeros in each row)
for r in 0..n_row-1
if all elements in the row are zero
skip the row
for c in r..n_row-1
d := dot(a[c],a[r])
if d <> 0
result[r,c] = d
result[c,r] = d
通过查找a[c]
和a[r]
中非零元素集的交集,可以轻松计算点积。大部分时间交叉点都是空的,只有当它不为空时才需要进行计算。
根据矩阵中的空行数,这可能相对较快。另一方面,如果您没有任何空行或列,则需要花费时间计算500 000 000套交叉点。 (在这种情况下,大多数是在1组之间,因此它们是简单的比较。)
这种方法需要很少的内存,但仍然需要很多时间,从几小时到几天,除非有很多空行。