Разбить разреженную матрицу по строкам - PullRequest
1 голос
/ 21 июня 2019

У меня есть scipy.sparse.csr.csr_matrix (8723, 1741277) размеров.

Как эффективно разделить его на n кусков по строкам?

Лучше, чтобы куски были приблизительно равны с точки зрения количества строк.

Я говорю примерно, потому что это зависит от того, возвращает ли (количество строк) / (количество кусков) какой-либо остаток.

Я думаю, что вы можете легко сделать это с помощью numpy.split для массивов, но это не работает для разреженных матриц.

В частности, я получаю эту ошибку, если выберу число n-порций, которое не делится на 8723:

ValueError: array split does not result in an equal division

и я получаю эту ошибку, если выбираю число n-кусков, которое делится на 8723:

AxisError: axis1: axis 0 is out of bounds for array of dimension 0

Причина, по которой я хочу разделить разреженную матрицу на куски, заключается в том, что я хочу преобразовать свою разреженную матрицу в (плотный) массив, но я не могу сделать это напрямую, поскольку она слишком велика в целом.

1 Ответ

0 голосов
/ 22 июня 2019
In [6]: from scipy import sparse                                                                     
In [7]: M = sparse.random(12,3,.1,'csr')                                                             
In [8]: np.split?                                                                                    
In [9]: np.split(M,3)                                                                                
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
     55     try:
---> 56         return getattr(obj, method)(*args, **kwds)
     57 

/usr/local/lib/python3.6/dist-packages/scipy/sparse/base.py in __getattr__(self, attr)
    687         else:
--> 688             raise AttributeError(attr + " not found")
    689 

AttributeError: swapaxes not found

During handling of the above exception, another exception occurred:

AxisError                                 Traceback (most recent call last)
<ipython-input-9-11a4dcdd89af> in <module>
----> 1 np.split(M,3)

/usr/local/lib/python3.6/dist-packages/numpy/lib/shape_base.py in split(ary, indices_or_sections, axis)
    848             raise ValueError(
    849                 'array split does not result in an equal division')
--> 850     res = array_split(ary, indices_or_sections, axis)
    851     return res
    852 

/usr/local/lib/python3.6/dist-packages/numpy/lib/shape_base.py in array_split(ary, indices_or_sections, axis)
    760 
    761     sub_arys = []
--> 762     sary = _nx.swapaxes(ary, axis, 0)
    763     for i in range(Nsections):
    764         st = div_points[i]

/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in swapaxes(a, axis1, axis2)
    583 
    584     """
--> 585     return _wrapfunc(a, 'swapaxes', axis1, axis2)
    586 
    587 

/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
     64     # a downstream library like 'pandas'.
     65     except (AttributeError, TypeError):
---> 66         return _wrapit(obj, method, *args, **kwds)
     67 
     68 

/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in _wrapit(obj, method, *args, **kwds)
     44     except AttributeError:
     45         wrap = None
---> 46     result = getattr(asarray(obj), method)(*args, **kwds)
     47     if wrap:
     48         if not isinstance(result, mu.ndarray):

AxisError: axis1: axis 0 is out of bounds for array of dimension 0

Если мы применим np.array к M, мы получим массив объектов 0d; просто наивная обертка вокруг редкого объекта.

In [10]: np.array(M)                                                                                 
Out[10]: 
array(<12x3 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in Compressed Sparse Row format>, dtype=object)
In [11]: _.shape                                                                                     
Out[11]: ()

разделить правильный плотный эквивалент:

In [12]: np.split(M.A,3)                                                                             
Out[12]: 
[array([[0.        , 0.61858517, 0.        ],
        [0.        , 0.        , 0.        ],
        [0.        , 0.        , 0.        ],
        [0.        , 0.        , 0.        ]]), array([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]), array([[0.        , 0.89573059, 0.        ],
        [0.        , 0.        , 0.        ],
        [0.        , 0.        , 0.02334738],
        [0.        , 0.        , 0.        ]])]

и прямое разреженное разбиение:

In [13]: [M[i:j,:] for i,j in zip([0,4,8],[4,8,12])]                                                 
Out[13]: 
[<4x3 sparse matrix of type '<class 'numpy.float64'>'
    with 1 stored elements in Compressed Sparse Row format>,
 <4x3 sparse matrix of type '<class 'numpy.float64'>'
    with 0 stored elements in Compressed Sparse Row format>,
 <4x3 sparse matrix of type '<class 'numpy.float64'>'
    with 2 stored elements in Compressed Sparse Row format>]

Подобная нарезка не так эффективна с разреженными матрицами, как с плотными. Плотные кусочки - это взгляды. Редкие должны быть копиями. Единственным исключением является формат lil, который имеет метод get_rowview. Хотя существует множество функций для построения разреженных матриц из кусочков, нет особой необходимости в функциях, которые их разбивают.

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

...