Использование joblib для распараллеливания Предиката () с конвейером scikit-learn - PullRequest
0 голосов
/ 06 июля 2018

Каков рекомендуемый способ распараллеливания метода predict() конвейера scikit-learn?

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

from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline
from sklearn.externals.joblib import Parallel, delayed
from sklearn import datasets

# Load Iris data
iris = datasets.load_iris()
# Create a pipeline with 2 steps: scaler and SVM; train
pipe = make_pipeline(StandardScaler(), SVC()).fit(X=iris.data, y=iris.target)

# Split data array in 5 chunks
n_chunks = 5
n_samples = iris.data.shape[0]
slices = [(int(n_samples*i/n_chunks), int(n_samples*(i+1)/n_chunks)) for i in range(n_chunks)]
data_chunks = [iris.data[i[0]:i[1]] for i in slices]

# Setup 5 parallel jobs 
jobs = (delayed(pipe.predict)(array) for array in data_chunks)
parallel = Parallel(n_jobs=n_chunks)

# Run jobs: fails
results = parallel(jobs)

Этот код не работает с:

PicklingError: Can't pickle <function Pipeline.predict at 0x000000001746B730>: it's not the same object as sklearn.pipeline.Pipeline.predict 

Однако применение распараллеливания к классификатору SVM напрямую, а не к конвейеру, работает:

# Load Iris data
iris = datasets.load_iris()
# Create SVM classifier, train
svc = SVC().fit(X=iris.data, y=iris.target)

# Split data array in 5 chunks
n_chunks = 5
n_samples = iris.data.shape[0]
slices = [(int(n_samples*i/n_chunks), int(n_samples*(i+1)/n_chunks)) for i in range(n_chunks)]
data_chunks = [iris.data[i[0]:i[1]] for i in slices]

# Setup 5 parallel jobs 
jobs = (delayed(svc.predict)(array) for array in data_chunks)
parallel = Parallel(n_jobs=n_chunks)

# Run jobs: works
results = parallel(jobs)

Я могу обойти эту проблему, по существу разобрав конвейер: сначала применив масштабирование ко всему массиву, затем разделив его на куски и распараллелив svc.predict(), как описано выше. Однако это неудобно и, как правило, аннулирует преимущества, предлагаемые конвейерами: например, Я должен отслеживать промежуточные результаты, и код должен будет измениться, если в конвейер будут добавлены дополнительные шаги преобразователя.

Есть ли способ распараллеливания с использованием конвейеров напрямую?

Большое спасибо,

Алексей

...