Вычислить матрицу попарного расстояния: доступен ли масштабируемый подход с большими данными в 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 становится устаревшим.