Мне нужно создать структуру данных для хранения расстояний от каждой точки до каждой другой точки в очень большом массиве 2d-координат. Это легко реализовать для небольших массивов, но после примерно 50 000 точек я начинаю сталкиваться с проблемами памяти - неудивительно, учитывая, что я создаю матрицу n x n.
Вот простой пример, который отлично работает:
import numpy as np
from scipy.spatial import distance
n = 2000
arr = np.random.rand(n,2)
d = distance.cdist(arr,arr)
cdist
быстро, но неэффективно при хранении, поскольку матрица зеркально отображается по диагонали (например, d[i][j] == d[j][i]
). Я могу использовать np.triu(d)
для преобразования в верхний треугольник, но получающаяся квадратная матрица все еще занимает ту же память. Мне также не нужны расстояния за пределами определенного отрезка, так что это может быть полезным. Следующим шагом является преобразование в разреженную матрицу для экономии памяти:
from scipy import sparse
max_dist = 5
dist = np.array([[0,1,3,6], [1,0,8,7], [3,8,0,4], [6,7,4,0]])
print dist
array([[0, 1, 3, 6],
[1, 0, 8, 7],
[3, 8, 0, 4],
[6, 7, 4, 0]])
dist[dist>=max_dist] = 0
dist = np.triu(dist)
print dist
array([[0, 1, 3, 0],
[0, 0, 0, 0],
[0, 0, 0, 4],
[0, 0, 0, 0]])
sdist = sparse.lil_matrix(dist)
print sdist
(0, 1) 1
(2, 3) 4
(0, 2) 3
Проблема в том, чтобы быстро получить эту разреженную матрицу для очень большого набора данных. Повторим еще раз: создание квадратной матрицы с помощью cdist - самый быстрый из известных мне способов вычисления расстояний между точками, но промежуточной квадратной матрице не хватает памяти. Я мог бы разбить его на более управляемые куски строк, но тогда это сильно замедляет ход событий. Я чувствую, что упускаю какой-то очевидный простой способ перейти непосредственно к разреженной матрице из cdist
.