【问题标题】:How to select some rows from sparse matrix then use them form a new sparse matrix如何从稀疏矩阵中选择一些行然后使用它们形成一个新的稀疏矩阵
【发布时间】:2019-10-12 15:49:17
【问题描述】:

我有一个非常大的稀疏矩阵(100000 列和 100000 行)。我想选择这个稀疏矩阵的一些行,然后用它们来形成一个新的稀疏矩阵。我试图通过首先将它们转换为密集矩阵然后再次将它们转换为稀疏矩阵来做到这一点。但是当我这样做时,python 会引发“内存错误”。然后我尝试了另一种方法,即我选择稀疏矩阵的行然后将它们放入一个数组中,但是当我尝试将此数组转换为稀疏矩阵时,它说:'ValueError:数组的真值大于一个元素是模棱两可的。使用 a.any() 或 a.all()。 那么如何将这个列表稀疏矩阵转换为单个大稀疏矩阵呢?

# X_train is a sparse matrix of size 100000x100000, it is in sparse form
# y_train is a 1 denmentional array with length 100000
# I try to get a new sparse matrix by using some rows of X_train, the 
#selection criteria is sum of the sparse row = 0

#y_train_new = []
#X_train_new = []
for i in range(len(y_train)):
    if np.sum(X_train[i].toarray()[0]) == 0:
        X_train_new.append(X_train[i])
        y_train_new.append(y_train[i])

当我这样做时:

X_train_new = scipy.sparse.csr_matrix(X_train_new)

我收到错误消息:

'ValueError: The truth value of an array with more than one element is 
ambiguous. Use a.any() or a.all().'

【问题讨论】:

    标签: python numpy scipy sparse-matrix


    【解决方案1】:

    我添加了一些标签,可以帮助我更快地看到您的问题。

    询问错误时,最好提供部分或全部回溯,以便我们查看错误发生的位置。问题函数调用的输入信息也有帮助。

    幸运的是,我可以很容易地重新创建问题 - 并且在一个合理的大小示例中。不用做一个100000 x10000的矩阵,没人看!

    制作一个大小适中的稀疏矩阵:

    In [126]: M = sparse.random(10,10,.1,'csr')                                                              
    In [127]: M                                                                                              
    Out[127]: 
    <10x10 sparse matrix of type '<class 'numpy.float64'>'
        with 10 stored elements in Compressed Sparse Row format>
    

    我可以对整个矩阵行求和,就像使用密集数组一样。稀疏代码实际上使用矩阵向量乘法来执行此操作,生成密集矩阵。

    In [128]: M.sum(axis=1)                                                                                  
    Out[128]: 
    matrix([[0.59659958],
            [0.80390719],
            [0.37251645],
            [0.        ],
            [0.85766909],
            [0.42267366],
            [0.76794737],
            [0.        ],
            [0.83131054],
            [0.46254634]])
    

    它足够稀疏,以至于有些行没有零。对于浮点数,尤其是在 0-1 范围内,我不会得到非零值抵消的行。

    或者使用你的逐行计算:

    In [133]: alist = [np.sum(row.toarray()[0]) for row in M]                                                
    In [134]: alist                                                                                          
    Out[134]: 
    [0.5965995802776853,
     0.8039071870427961,
     0.37251644566924424,
     0.0,
     0.8576690924353791,
     0.42267365715276595,
     0.7679473651419432,
     0.0,
     0.8313105376003095,
     0.4625463360625408]
    

    并选择总和为零的行(在本例中为空行):

    In [135]: alist = [row for row in M if np.sum(row.toarray()[0])==0]                                      
    In [136]: alist                                                                                          
    Out[136]: 
    [<1x10 sparse matrix of type '<class 'numpy.float64'>'
        with 0 stored elements in Compressed Sparse Row format>,
     <1x10 sparse matrix of type '<class 'numpy.float64'>'
        with 0 stored elements in Compressed Sparse Row format>]
    

    请注意,这是一个稀疏矩阵列表。这也是你得到的,对吧?

    现在,如果我尝试从中制作矩阵,我会收到您的错误:

    In [137]: sparse.csr_matrix(alist)                                                                       
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-137-5e20e6fc2524> in <module>
    ----> 1 sparse.csr_matrix(alist)
    
    /usr/local/lib/python3.6/dist-packages/scipy/sparse/compressed.py in __init__(self, arg1, shape, dtype, copy)
         86                                  "".format(self.format))
         87             from .coo import coo_matrix
    ---> 88             self._set_self(self.__class__(coo_matrix(arg1, dtype=dtype)))
         89 
         90         # Read matrix dimensions given, if any
    
    /usr/local/lib/python3.6/dist-packages/scipy/sparse/coo.py in __init__(self, arg1, shape, dtype, copy)
        189                                          (shape, self._shape))
        190 
    --> 191                 self.row, self.col = M.nonzero()
        192                 self.data = M[self.row, self.col]
        193                 self.has_canonical_format = True
    
    /usr/local/lib/python3.6/dist-packages/scipy/sparse/base.py in __bool__(self)
        285             return self.nnz != 0
        286         else:
    --> 287             raise ValueError("The truth value of an array with more than one "
        288                              "element is ambiguous. Use a.any() or a.all().")
        289     __nonzero__ = __bool__
    
    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().
    

    好的,这个错误并没有告诉我很多信息(至少没有更多地阅读代码),但显然输入列表存在问题。但请再次阅读csr_matrix 文档!它是否说我们可以给它一个稀疏矩阵列表?

    但是有一个sparse.vstack 函数可以处理矩阵列表(仿照np.vstack):

    In [140]: sparse.vstack(alist)                                                                           
    Out[140]: 
    <2x10 sparse matrix of type '<class 'numpy.float64'>'
        with 0 stored elements in Compressed Sparse Row format>
    

    如果我们选择总和不为零的行,我们会得到更有趣的结果:

    In [141]: alist = [row for row in M if np.sum(row.toarray()[0])!=0]                                      
    In [142]: M1=sparse.vstack(alist)                                                                        
    In [143]: M1                                                                                             
    Out[143]: 
    <8x10 sparse matrix of type '<class 'numpy.float64'>'
        with 10 stored elements in Compressed Sparse Row format>
    

    但我之前展示了我们可以在不迭代的情况下获得行总和。将where 应用于Out[128],我得到了行索引(非零行):

    In [151]: idx=np.where(M.sum(axis=1))                                                                    
    In [152]: idx                                                                                            
    Out[152]: (array([0, 1, 2, 4, 5, 6, 8, 9]), array([0, 0, 0, 0, 0, 0, 0, 0]))
    In [153]: M2=M[idx[0],:]                                                                                 
    In [154]: M2                                                                                             
    Out[154]: 
    <8x10 sparse matrix of type '<class 'numpy.float64'>'
        with 10 stored elements in Compressed Sparse Row format>
    In [155]: np.allclose(M1.A, M2.A)                                                                        
    Out[155]: True
    

    ====

    我怀疑In[137] 是在试图找到输入的nonzero (np.where) 元素或将输入转换为numpy 数组时产生的:

    In [159]: alist = [row for row in M if np.sum(row.toarray()[0])==0]                                      
    In [160]: np.array(alist)                                                                                
    Out[160]: 
    array([<1x10 sparse matrix of type '<class 'numpy.float64'>'
        with 0 stored elements in Compressed Sparse Row format>,
           <1x10 sparse matrix of type '<class 'numpy.float64'>'
        with 0 stored elements in Compressed Sparse Row format>], dtype=object)
    In [161]: np.array(alist).nonzero()                                                                      
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-161-832a25987c15> in <module>
    ----> 1 np.array(alist).nonzero()
    
    /usr/local/lib/python3.6/dist-packages/scipy/sparse/base.py in __bool__(self)
        285             return self.nnz != 0
        286         else:
    --> 287             raise ValueError("The truth value of an array with more than one "
        288                              "element is ambiguous. Use a.any() or a.all().")
        289     __nonzero__ = __bool__
    
    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().
    

    np.array 在稀疏矩阵列表上生成这些矩阵的对象 dtype 数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 2018-01-19
      • 2019-05-06
      • 1970-01-01
      • 1970-01-01
      • 2018-09-26
      相关资源
      最近更新 更多