2016-11-01 6 views
1

У меня есть генератор, который генерирует единый размер numpy.array s такой же длины. Я хотел бы иметь разреженную матрицу, содержащую эти данные. Строки генерируются в том же порядке, который я хотел бы иметь в финальной матрице. csr матрица предпочтительнее над матрицей lil, но я предполагаю, что последнее будет легче построить в описываемом мной сценарии.Создание scipy.lil_matrix с использованием генератора питона эффективно

Предполагает, что row_gen является генератором с заданными numpy.array строками, следующий код работает должным образом.

def row_gen(): 
    yield numpy.array([1, 2, 3]) 
    yield numpy.array([1, 0, 1]) 
    yield numpy.array([1, 0, 0]) 

matrix = scipy.sparse.lil_matrix(list(row_gen())) 

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

def row_gen(): 
    yield numpy.array([1, 2, 3]) 
    yield numpy.array([1, 0, 1]) 
    yield numpy.array([1, 0, 0]) 

matrix = scipy.sparse.lil_matrix(row_gen()) 

Однако это вызывает следующее исключение при запуске:

TypeError: no supported conversion for types: (dtype('O'),) 

Я также заметил след включает в себя следующее:

File "/usr/local/lib/python2.7/site-packages/scipy/sparse/lil.py", line 122, in __init__ 
    A = csr_matrix(A, dtype=dtype).tolil() 

что заставляет меня думать, используя scipy.sparse.lil_matrix в конечном итоге создание csr матрицы и только затем преобразовать, что к lil матрица. В этом случае я предпочел бы просто создать матрицу csr.

Напомним, что мой вопрос: какой самый эффективный способ создать матрицу scipy.sparse из генератора питона или одномерных массивов numpy?

ответ

1

Давайте посмотрим на код для sparse.lil_matrix. Он проверяет первый аргумент:

if isspmatrix(arg1): # is is already a sparse matrix 
    ... 
elif isinstance(arg1,tuple): # is it the shape tuple 
    if isshape(arg1): 
     if shape is not None: 
      raise ValueError('invalid use of shape parameter') 
     M, N = arg1 
     self.shape = (M,N) 
     self.rows = np.empty((M,), dtype=object) 
     self.data = np.empty((M,), dtype=object) 
     for i in range(M): 
      self.rows[i] = [] 
      self.data[i] = [] 
    else: 
     raise TypeError('unrecognized lil_matrix constructor usage') 
else: 
    # assume A is dense 
    try: 
     A = np.asmatrix(arg1) 
    except TypeError: 
     raise TypeError('unsupported matrix type') 
    else: 
     from .csr import csr_matrix 
     A = csr_matrix(A, dtype=dtype).tolil() 

     self.shape = A.shape 
     self.dtype = A.dtype 
     self.rows = A.rows 
     self.data = A.data 

В соответствии с документацией - вы можете построить его из другой разреженной матрицы, от формы, и из плотного массива. Плотный конструктор массива сначала создает матрицу csr, а затем преобразует ее в lil.

версия формы создает пустой lil с данными, такими как:

In [161]: M=sparse.lil_matrix((3,5),dtype=int) 
In [163]: M.data 
Out[163]: array([[], [], []], dtype=object) 
In [164]: M.rows 
Out[164]: array([[], [], []], dtype=object) 

Это должно быть очевидно, что передача генератора не будет работать - это не плотный массив.

Но создав lil матрицу, вы можете заполнить элементы с регулярным назначением массива:

In [167]: M[0,:]=[1,0,2,0,0] 
In [168]: M[1,:]=[0,0,2,0,0] 
In [169]: M[2,3:]=[1,1] 
In [170]: M.data 
Out[170]: array([[1, 2], [2], [1, 1]], dtype=object) 
In [171]: M.rows 
Out[171]: array([[0, 2], [2], [3, 4]], dtype=object) 
In [172]: M.A 
Out[172]: 
array([[1, 0, 2, 0, 0], 
     [0, 0, 2, 0, 0], 
     [0, 0, 0, 1, 1]]) 

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

In [173]: M.data[1]=[1,2,3] 
In [174]: M.rows[1]=[0,2,4] 
In [176]: M.A 
Out[176]: 
array([[1, 0, 2, 0, 0], 
     [1, 0, 2, 0, 3], 
     [0, 0, 0, 1, 1]]) 

Другой подход заключается в инкрементах построить 3 массивы или списки формата coo, а затем сделать coo или csr из них.

sparse.bmat - еще один вариант, и его код является хорошим примером построения входов coo.Я позволю тебе самому разобраться.

+0

Спасибо, но оба из предложенных вами подходов предполагают, что у меня есть форма матрицы. Это не так, и поскольку lil специально построен для линейных дополнений, я ищу способ эффективно увеличить его размер по мере его создания. – NirIzr

+0

Что неизвестно - количество строк или количество столбцов? или оба? Сбор трио массивов 'coo' не требует знания конечного размера, но' редкие' матрицы не предназначены для постепенного роста (а также редких массивов). – hpaulj

Смежные вопросы