sklearn linear_models .fit () запускается в многопроцессорном пуле медленнее, чем в одном процессе для цикла - PullRequest
0 голосов
/ 06 мая 2020

Я обнаружил, что LinearRegression.fit() работает медленнее с python многопроцессорной обработкой, чем простой for-l oop, вот мой код:

import multiprocessing as mp
from contextlib import contextmanager
from sklearn.linear_model import LinearRegression, Ridge, Lasso


def generate_random_data():
    n_samples = int(1e4)
    n_features = 100
    X = np.random.normal(size=(n_samples, n_features))
    beta = np.random.uniform(size=n_features)
    y = X @ beta + np.random.normal(size=n_samples)
    return X, y

@contextmanager
def timeit(tag, container=None):
    t0 = time.perf_counter()
    yield
    t1 = time.perf_counter()
    if container is None:
        print('[{}] : {:.2f} seconds'.format(tag, t1 - t0))
    else:
        container[tag] = t1 - t0

def test(i):
    X, y = generate_random_data()
    m = LinearRegression()    # Ridge, Lasso produce similar results
    with timeit('OLS.fit {}'.format(i)):
        m.fit(X, y)

print('===================== MultiProcessing =====================')
with mp.Pool(10) as pool:
    pool.map(test, range(10))

print('===================== For Loop =====================')
for i in range(10):
    test(i)

вывод:

===================== MultiProcessing =====================
[OLS.fit 5] : 0.76 seconds
[OLS.fit 9] : 0.98 seconds
[OLS.fit 7] : 1.54 seconds
[OLS.fit 0] : 1.58 seconds
[OLS.fit 4] : 1.67 seconds
[OLS.fit 1] : 1.75 seconds
[OLS.fit 8] : 1.80 seconds
[OLS.fit 2] : 1.96 seconds
[OLS.fit 6] : 2.02 seconds
[OLS.fit 3] : 2.09 seconds
===================== For Loop =====================
[OLS.fit 0] : 0.02 seconds
[OLS.fit 1] : 0.02 seconds
[OLS.fit 2] : 0.02 seconds
[OLS.fit 3] : 0.02 seconds
[OLS.fit 4] : 0.02 seconds
[OLS.fit 5] : 0.02 seconds
[OLS.fit 6] : 0.02 seconds
[OLS.fit 7] : 0.02 seconds
[OLS.fit 8] : 0.02 seconds
[OLS.fit 9] : 0.02 seconds

Если я изменю модель с LinearRegression на Lasso, Ridge, результат будет почти таким же. Но если перейти к другим моделям, например DecisionTreeRegressor, многопроцессорная версия почти потребляет то же время, что и простая для-l oop

моя системная версия: - Ubuntu 18.04 - python 3.7 (Anaconda)

  1. Почему это происходит?
  2. Есть ли что-нибудь неправильное в моем использовании sklearn и / или многопроцессорности?

1 Ответ

0 голосов
/ 07 мая 2020

Решается с помощью https://github.com/scikit-learn/scikit-learn/issues/17139

Это может быть потому, что LinearRegression вызывает BLAS, выполняя вычисления линейной алгебры, которые по умолчанию используют все потоки ЦП, делая процесс n из многопроцессорной обработки. Пул приведет к Превышение лимита ЦП.

Следует использовать joblib

Parallel(10, prefer='processes')(delayed(test)(i) for i in range(10))
...