Каков правильный формат разреженной матрицы SciPy для добавочного суммирования

В моем коде я сейчас повторяю и создаю три списка:

data, row, col

Существует большое количество повторений (row, col) пар, и в моей окончательной разреженной матрице M я хотел бы, чтобы значение M[row, col] было суммой всех соответствующих элементов в data. Из документации следует, что coo_matrix кажется идеальным, и для небольших примеров он отлично работает.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я увеличиваю размер своей задачи, похоже, что промежуточные списки data, row, col используют все мои (8 ГБ) памяти и пространство подкачки, и мой скрипт автоматически уничтожается.

Итак, мой вопрос:

Есть ли подходящий формат или эффективный способ постепенного построения моей суммированной матрицы, поэтому мне не нужно хранить полные промежуточные списки/массивы numpy?

Моя программа зацикливается на сетке, создавая local_data, local_row, local_col списков в каждой точке, элементы которых затем добавляются к data, row, col, поэтому возможность обновлять разреженную матрицу списками в соответствии с конструкторами разреженной матрицы была бы идеальным случаем.


person YXD    schedule 23.09.2013    source источник


Ответы (1)


Есть две вещи, которые могут убить вас: дубликаты или накладные расходы списка по сравнению с массивом. В любом случае, вероятно, правильно будет увеличить свой список до определенного размера, прежде чем сбрасывать его в coo_matrix и добавлять к общей сумме. Взял пару таймингов:

rows = list(np.random.randint(100, size=(10000,)))
cols = list(np.random.randint(100, size=(10000,)))
values = list(np.random.rand(10000))

%timeit sps.coo_matrix((values, (rows, cols)))
100 loops, best of 3: 4.03 ms per loop

%timeit (sps.coo_matrix((values[:5000], (rows[:5000], cols[:5000]))) +
         sps.coo_matrix((values[5000:], (rows[5000:], cols[5000:]))))
100 loops, best of 3: 5.24 ms per loop

%timeit sps.coo_matrix((values[:5000], (rows[:5000], cols[:5000])))
100 loops, best of 3: 2.16 ms per loop

Таким образом, при разделении списков на два, преобразовании каждого из них в coo_matrix и последующем сложении их вместе возникает около 25% накладных расходов. И это не так уж плохо, если вы сделаете больше шпагатов:

%timeit (sps.coo_matrix((values[:2500], (rows[:2500], cols[:2500]))) +   
         sps.coo_matrix((values[2500:5000], (rows[2500:5000], cols[2500:5000]))) +  
         sps.coo_matrix((values[5000:7500], (rows[5000:7500], cols[5000:7500]))) + 
         sps.coo_matrix((values[7500:], (rows[7500:], cols[7500:]))))
100 loops, best of 3: 5.76 ms per loop
person Jaime    schedule 23.09.2013
comment
Хайме - еще раз спасибо. Теперь я использую только такой большой подход к расширению списка, и (по крайней мере, эта часть) мой код работает в разумные сроки без сбоев. - person YXD; 23.09.2013