Как выбрать несколько строк из разреженной матрицы, а затем использовать их для формирования новой разреженной матрицы - PullRequest
0 голосов
/ 27 мая 2019

У меня очень большая разреженная матрица (100000 столбцов и 100000 строк).Я хочу выделить несколько строк этой разреженной матрицы, а затем использовать их для формирования новой разреженной матрицы.Я попытался сделать это, сначала преобразовав их в плотную матрицу, а затем снова преобразовать их в разреженную матрицу.Но когда я делаю этот питон, возникает ошибка памяти.Затем я попробовал другой метод, который состоит в том, что я выбираю строки разреженной матрицы и затем помещаю их в массив, но когда я пытаюсь преобразовать этот массив в разреженную матрицу, он говорит: «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().'

1 Ответ

0 голосов
/ 05 июня 2019

Я добавил несколько тегов, которые помогли бы мне быстрее увидеть ваш вопрос.

Когда вы спрашиваете об ошибке, рекомендуется предоставить некоторые или все данные трассировки, чтобы мы могли видеть, где происходит ошибка. Информация о входных данных для вызова функции проблемы также может помочь.

К счастью, я могу воссоздать проблему довольно легко - и на примере разумного размера. Не нужно делать матрицу 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) элементов ввода или ввода, приведенного в виде массива:

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 объектов этих матриц.

...