sklearn LogisticRegression: использует ли он несколько фоновых потоков? - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть код, который использует sklearn.linear_model.LogisticRegression и sklearn.ensemble.RandomForestClassifier .Все остальное остается неизменным в коде, запуск кода с использованием многопроцессорного пула запускает сотни потоков в пути логистической регрессии, что полностью снижает производительность - снимки экрана htop для 36 процессоров:

В режиме ожидания:

enter image description here

Леса (один процессор остается бездействующим, как и ожидалось):

enter image description here

Логистика (всепроцессоры на 100%):

enter image description here

Так ли порождает фоновые потоки логистической регрессии (да) и если да, есть ли способ предотвратить это?

$ python3.6
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
>>> sklearn.__version__
'0.20.1'

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Предполагая, что это происходит, когда вы подгоняете модель, проверьте эту часть исходного кода метода fit () модели ( ссылка ):

    # The SAG solver releases the GIL so it's more efficient to use
    # threads for this solver.
    if solver in ['sag', 'saga']:
        prefer = 'threads'
    else:
        prefer = 'processes'
    fold_coefs_ = Parallel(n_jobs=self.n_jobs, verbose=self.verbose,
                           **_joblib_parallel_args(prefer=prefer))(
        path_func(X, y, pos_class=class_, Cs=[self.C],
                  fit_intercept=self.fit_intercept, tol=self.tol,
                  verbose=self.verbose, solver=solver,
                  multi_class=multi_class, max_iter=self.max_iter,
                  class_weight=self.class_weight, check_input=False,
                  random_state=self.random_state, coef=warm_start_coef_,
                  penalty=self.penalty,
                  max_squared_sum=max_squared_sum,
                  sample_weight=sample_weight)
        for class_, warm_start_coef_ in zip(classes_, warm_start_coef))

точно ситуация

prefer = 'threads'
**_joblib_parallel_args(prefer=prefer)

Похоже, что если вы используете решатели sag или saga, вы можете столкнуться с проблемами многопоточности.Но решатель по умолчанию - liblinear.

Кроме того, из источника для Parallel (), использованного выше ( link ), sklearn может сказать о возможном обходном пути для проблем с многопоточностью:

'threading' is a low-overhead alternative that is most efficient for
functions that release the Global Interpreter Lock: e.g. I/O-bound code or
CPU-bound code in a few calls to native code that explicitly releases the
GIL.
In addition, if the `dask` and `distributed` Python packages are installed,
it is possible to use the 'dask' backend for better scheduling of nested
parallel calls without over-subscription and potentially distribute
parallel calls over a networked cluster of several hosts.

Насколько я понимаю, что-то вроде следующего может уменьшить многопоточность:

from dask.distributed import Client
from sklearn.externals import joblib
from sklearn.linear_model import LogisticRegression


...
# create local cluster
client = Client(processes=False)             
model = LogisticRegression()
with joblib.parallel_backend('dask'):
    model.fit(...)
...

Использование Dask Joblib , как предлагается.

0 голосов
/ 12 декабря 2018

При создании экземпляра sklearn.linear_model.LogisticRegression вы всегда можете передать количество потоков для использования через n_jobs=N, где N - желаемое количество потоков.Я бы проверил, если запуск с n_jobs=1 не помогает.В противном случае Python может неправильно истолковывать количество доступных потоков в вашей среде.Чтобы убедиться в этом, я бы проверил.

import multiprocessing
print(multiprocessing.cpu_count())

Под капотом LogisticRegression используется sklearn.externals.joblib.Parallel, который выполняет резьбу.Его логика довольно сложна, поэтому без сложных знаний о настройке вашей среды было бы трудно сказать, что именно она делает.

...