【问题标题】:Adding a rowsum column to a large sparse matrix将 rowsum 列添加到大型稀疏矩阵
【发布时间】:2020-05-24 17:15:45
【问题描述】:

我有一个大的稀疏矩阵 X(2 百万行,23k 列),我想在其上添加一个 rowsum 列并返回一个稀疏矩阵。

下面我试过了

np.hstack( (X.toarray(),X.sum(axis=1)) )

但它不适用于大型稀疏矩阵。

问题是,当我调用 X.toarray() 时,它会炸毁并终止 python 内核,而不会给出任何错误消息。

类似的我试过

sparse.hstack( X ,sparse.csr_matrix(X.sum(axis=1)))
sparse.csr_matrix(X.sum(axis=1)).ndim    # is 2
X.ndim # 2 as well

但它给了我以下错误消息:

~/miniconda3/lib/python3.7/site-packages/scipy/sparse/construct.py in bmat(blocks, format, dtype)
    546 
    547     if blocks.ndim != 2:
--> 548         raise ValueError('blocks must be 2-D')
    549 
    550     M,N = blocks.shape

ValueError: blocks must be 2-D

有没有办法解决这个问题?

【问题讨论】:

  • 链接的答案没有说明使用np.hstacktoarray 经常失败,因为结果数组对于您的内存来说太大了。还有sparse.vstack
  • @hpaulj 不知何故我得到了错误的链接,我删除了它。
  • 查看sparse.stack 的文档。第一个 arg 应该是列表或元组。我在您的旧链接中的回答仍然正确。

标签: python numpy scikit-learn scipy


【解决方案1】:
In [93]: from scipy import sparse                                                              
In [94]: M = sparse.random(5,7, .2, 'csr')                                                     
In [95]: M                                                                                     
Out[95]: 
<5x7 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in Compressed Sparse Row format>

一个和是 (n,1) np.matrix:

In [96]: M.sum(axis=1)                                                                         
Out[96]: 
matrix([[0.92949904],
        [1.068337  ],
        [0.10927561],
        [0.        ],
        [0.68352182]])

另外一个(1,n)矩阵:

In [97]: M.sum(axis=0)                                                                         
Out[97]: 
matrix([[0.        , 0.90221854, 0.42335774, 1.35578158, 0.        ,
         0.        , 0.10927561]])

将列添加到矩阵中(注意参数细节):

In [98]: sparse.hstack((M, M.sum(axis=1)))                                                     
Out[98]: 
<5x8 sparse matrix of type '<class 'numpy.float64'>'
    with 11 stored elements in COOrdinate format>

添加行矩阵:

In [99]: sparse.vstack((M, M.sum(axis=0)))                                                     
Out[99]: 
<6x7 sparse matrix of type '<class 'numpy.float64'>'
    with 11 stored elements in COOrdinate format>

【讨论】:

  • 为了使我的答案完全过时,您应该证明这也适用于大型数组。 ;-) sparse.random 实际上没有,但请随意借用我的解决方法。
【解决方案2】:

一种可能的解决方法是像这样使用矩阵乘法。

首先是一个小例子,看看发生了什么。 x 是一个辅助矩阵,yy 将对应您的数据:

>>> K,N,D = 5,10,3
>>> 
>>> x = sparse.csc_matrix((np.ones(2*K),np.r_[np.arange(K),np.arange(K)],np.r_[np.arange(K+1),2*K]),(K,K+1))
>>> 
>>> x.A
array([[1., 0., 0., 0., 0., 1.],
       [0., 1., 0., 0., 0., 1.],
       [0., 0., 1., 0., 0., 1.],
       [0., 0., 0., 1., 0., 1.],
       [0., 0., 0., 0., 1., 1.]])
>>> 
>>> y = np.random.randint(0,N,(D,K))
>>> y.sort(0)
>>> yy = sparse.csc_matrix((np.ones(D*K),y.ravel(),np.arange(K+1)*D),(N,K))
>>> 
>>> yy.A
array([[1., 0., 0., 0., 0.],
       [2., 1., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 1., 1., 1., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0.],
       [0., 0., 2., 1., 0.],
       [0., 0., 0., 1., 1.],
       [0., 0., 0., 0., 1.]])
>>> 
>>> (yy@x).A
array([[1., 0., 0., 0., 0., 1.],
       [2., 1., 0., 0., 0., 3.],
       [0., 1., 0., 0., 0., 1.],
       [0., 1., 1., 1., 0., 3.],
       [0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 1.],
       [0., 0., 0., 0., 0., 0.],
       [0., 0., 2., 1., 0., 3.],
       [0., 0., 0., 1., 1., 2.],
       [0., 0., 0., 0., 1., 1.]])

还有一个更大的例子来展示它的比例:

>>> K,N,D = 23_000,2_000_000,100
>>> 
>>> x = sparse.csc_matrix((np.ones(2*K),np.r_[np.arange(K),np.arange(K)],np.r_[np.arange(K+1),2*K]),(K,K+1))
>>> x
<23000x23001 sparse matrix of type '<class 'numpy.float64'>'
        with 46000 stored elements in Compressed Sparse Column format>
>>> 
>>> y = np.random.randint(0,N,(D,K))
>>> y.sort(0)
>>> yy = sparse.csc_matrix((np.ones(D*K),y.ravel(),np.arange(K+1)*D),(N,K))
>>> yy
<2000000x23000 sparse matrix of type '<class 'numpy.float64'>'
        with 2300000 stored elements in Compressed Sparse Column format>
>>> 
>>> yy@x
<2000000x23001 sparse matrix of type '<class 'numpy.float64'>'
        with 3667102 stored elements in Compressed Sparse Column format>

【讨论】:

  • X.sum(axis=1) 方法使用yy@x[:,-1] - 这是一个矩阵乘以一列。实际上它使用 np.matrix(np.ones((1,n)))` 所以结果也是np.matrix。由于hstack 将元素数组的coo 属性组合成一个新的coo,因此您的多合一乘法可能会更快。
猜你喜欢
  • 2017-06-15
  • 2017-06-15
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 2021-11-18
  • 2015-03-01
  • 2013-06-09
  • 1970-01-01
相关资源
最近更新 更多