Вычислить матрицу попарного расстояния: доступен ли масштабируемый подход с большими данными в Python?

У меня есть файл CSV, содержащий значения объектов для элементов: каждая строка представляет собой тройку (id_item, id_feature, value), представляющую значение конкретного объекта для конкретного элемента. Данные очень скудные.

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

на данный момент я реализовал решение в памяти, и я делаю что-то вроде этого:

import numpy as np
from numpy import genfromtxt
from scipy.sparse import coo_matrix
from scipy.sparse import csr_matrix
from scipy.stats.stats import pearsonr
import sklearn.metrics.pairwise
import scipy.spatial.distance as ds
import scipy.sparse as sp

# read the data
my_data = genfromtxt('file.csv', delimiter=',')
i,j,value=my_data.T

# create a sparse matrix
m=coo_matrix( (value,(i,j)) )

# convert in a numpy array
m = np.array(m.todense())

# create the distance matrix using pdist
d = ds.pdist(m.T, 'correlation')

d= ds.squareform(d)

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

каков наилучший подход?

1) Sklearn pairwise_distances имеет параметр n_jobs, который позволяет использовать преимущества параллельных вычислений (http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.pairwise_distances.html) но, насколько я знаю, он поддерживает несколько ядер на одной машине, а не кластерные вычисления. Это вопрос простой способ использовать параллельные опции scikit-learn функции на HPC но я не получил, что является лучшим решением в моем конкретном случае, и если у Joblib действительно есть проблемы.

кроме того, часть, которая читает в памяти CSV, все равно будет узкое место: я могу хранить CSV в HDFS и читать его, делая что-то вроде:

import subprocess
cat = subprocess.Popen(["hadoop", "fs", "-cat", "data.csv"], stdout=subprocess.PIPE)

а затем петля через cat.стандартный вывод:

for line in cat.stdout:
    ....

но я не уверен, что это хорошее решение.

2) храните данные в HDFS, реализуйте вычисления в map reduce fashion и запускайте задание через mrjob

3) храните данные в HDFS, реализуйте вычисления SQL-подобным образом (я не знаю, легко ли это и возможно, я должен подумать об этом) и запустите его с помощью PyHive

конечно, я хотел бы сохранить как можно больше текущего кода, поэтому вариант Решение 1) является лучшим для меня.

1 ответов


прототип:

Я предлагаю вам использовать Pyro4 и реализовать это с divide and conquer парадигма, главный узел и несколько подчиненных узлов.

если у вас n элементов n(n-1)/2 пары, вы используете попарные расстояния sklearn с максимумом заданий (параметр n_jobs) на каждом узле.

вы разделите свой набор пар в a задачи и выполнить это на b узлы и перегруппировать результат на вашем хозяине узел.

для производства:

я советую вам PySpark 2.1.1. Map Reduce становится устаревшим.