Skip to content

Commit 106bb9e

Browse files
GaelVaroquauxglemaitre
authored andcommitted
MAINT: option to unvendor joblib (#11166)
1 parent 526aede commit 106bb9e

29 files changed

+277
-169
lines changed

doc/glossary.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ General Concepts
457457
A Python library (http://joblib.readthedocs.io) used in Scikit-learn to
458458
facilite simple parallelism and caching. Joblib is oriented towards
459459
efficiently working with numpy arrays, such as through use of
460-
:term:`memory mapping`.
460+
:term:`memory mapping`. See :ref:`parallelism` for more
461+
information.
461462

462463
label indicator matrix
463464
multilabel indicator matrix

doc/modules/computational_performance.rst renamed to doc/modules/computing.rst

+239-29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,145 @@
1+
============================
2+
Computing with scikit-learn
3+
============================
4+
5+
.. _scaling_strategies:
6+
7+
Strategies to scale computationally: bigger data
8+
=================================================
9+
10+
For some applications the amount of examples, features (or both) and/or the
11+
speed at which they need to be processed are challenging for traditional
12+
approaches. In these cases scikit-learn has a number of options you can
13+
consider to make your system scale.
14+
15+
Scaling with instances using out-of-core learning
16+
--------------------------------------------------
17+
18+
Out-of-core (or "external memory") learning is a technique used to learn from
19+
data that cannot fit in a computer's main memory (RAM).
20+
21+
Here is a sketch of a system designed to achieve this goal:
22+
23+
1. a way to stream instances
24+
2. a way to extract features from instances
25+
3. an incremental algorithm
26+
27+
Streaming instances
28+
....................
29+
30+
Basically, 1. may be a reader that yields instances from files on a
31+
hard drive, a database, from a network stream etc. However,
32+
details on how to achieve this are beyond the scope of this documentation.
33+
34+
Extracting features
35+
...................
36+
37+
\2. could be any relevant way to extract features among the
38+
different :ref:`feature extraction <feature_extraction>` methods supported by
39+
scikit-learn. However, when working with data that needs vectorization and
40+
where the set of features or values is not known in advance one should take
41+
explicit care. A good example is text classification where unknown terms are
42+
likely to be found during training. It is possible to use a stateful
43+
vectorizer if making multiple passes over the data is reasonable from an
44+
application point of view. Otherwise, one can turn up the difficulty by using
45+
a stateless feature extractor. Currently the preferred way to do this is to
46+
use the so-called :ref:`hashing trick<feature_hashing>` as implemented by
47+
:class:`sklearn.feature_extraction.FeatureHasher` for datasets with categorical
48+
variables represented as list of Python dicts or
49+
:class:`sklearn.feature_extraction.text.HashingVectorizer` for text documents.
50+
51+
Incremental learning
52+
.....................
53+
54+
Finally, for 3. we have a number of options inside scikit-learn. Although not
55+
all algorithms can learn incrementally (i.e. without seeing all the instances
56+
at once), all estimators implementing the ``partial_fit`` API are candidates.
57+
Actually, the ability to learn incrementally from a mini-batch of instances
58+
(sometimes called "online learning") is key to out-of-core learning as it
59+
guarantees that at any given time there will be only a small amount of
60+
instances in the main memory. Choosing a good size for the mini-batch that
61+
balances relevancy and memory footprint could involve some tuning [1]_.
62+
63+
Here is a list of incremental estimators for different tasks:
64+
65+
- Classification
66+
+ :class:`sklearn.naive_bayes.MultinomialNB`
67+
+ :class:`sklearn.naive_bayes.BernoulliNB`
68+
+ :class:`sklearn.linear_model.Perceptron`
69+
+ :class:`sklearn.linear_model.SGDClassifier`
70+
+ :class:`sklearn.linear_model.PassiveAggressiveClassifier`
71+
+ :class:`sklearn.neural_network.MLPClassifier`
72+
- Regression
73+
+ :class:`sklearn.linear_model.SGDRegressor`
74+
+ :class:`sklearn.linear_model.PassiveAggressiveRegressor`
75+
+ :class:`sklearn.neural_network.MLPRegressor`
76+
- Clustering
77+
+ :class:`sklearn.cluster.MiniBatchKMeans`
78+
+ :class:`sklearn.cluster.Birch`
79+
- Decomposition / feature Extraction
80+
+ :class:`sklearn.decomposition.MiniBatchDictionaryLearning`
81+
+ :class:`sklearn.decomposition.IncrementalPCA`
82+
+ :class:`sklearn.decomposition.LatentDirichletAllocation`
83+
- Preprocessing
84+
+ :class:`sklearn.preprocessing.StandardScaler`
85+
+ :class:`sklearn.preprocessing.MinMaxScaler`
86+
+ :class:`sklearn.preprocessing.MaxAbsScaler`
87+
88+
For classification, a somewhat important thing to note is that although a
89+
stateless feature extraction routine may be able to cope with new/unseen
90+
attributes, the incremental learner itself may be unable to cope with
91+
new/unseen targets classes. In this case you have to pass all the possible
92+
classes to the first ``partial_fit`` call using the ``classes=`` parameter.
93+
94+
Another aspect to consider when choosing a proper algorithm is that not all of
95+
them put the same importance on each example over time. Namely, the
96+
``Perceptron`` is still sensitive to badly labeled examples even after many
97+
examples whereas the ``SGD*`` and ``PassiveAggressive*`` families are more
98+
robust to this kind of artifacts. Conversely, the latter also tend to give less
99+
importance to remarkably different, yet properly labeled examples when they
100+
come late in the stream as their learning rate decreases over time.
101+
102+
Examples
103+
..........
104+
105+
Finally, we have a full-fledged example of
106+
:ref:`sphx_glr_auto_examples_applications_plot_out_of_core_classification.py`. It is aimed at
107+
providing a starting point for people wanting to build out-of-core learning
108+
systems and demonstrates most of the notions discussed above.
109+
110+
Furthermore, it also shows the evolution of the performance of different
111+
algorithms with the number of processed examples.
112+
113+
.. |accuracy_over_time| image:: ../auto_examples/applications/images/sphx_glr_plot_out_of_core_classification_001.png
114+
:target: ../auto_examples/applications/plot_out_of_core_classification.html
115+
:scale: 80
116+
117+
.. centered:: |accuracy_over_time|
118+
119+
Now looking at the computation time of the different parts, we see that the
120+
vectorization is much more expensive than learning itself. From the different
121+
algorithms, ``MultinomialNB`` is the most expensive, but its overhead can be
122+
mitigated by increasing the size of the mini-batches (exercise: change
123+
``minibatch_size`` to 100 and 10000 in the program and compare).
124+
125+
.. |computation_time| image:: ../auto_examples/applications/images/sphx_glr_plot_out_of_core_classification_003.png
126+
:target: ../auto_examples/applications/plot_out_of_core_classification.html
127+
:scale: 80
128+
129+
.. centered:: |computation_time|
130+
131+
132+
Notes
133+
......
134+
135+
.. [1] Depending on the algorithm the mini-batch size can influence results or
136+
not. SGD*, PassiveAggressive*, and discrete NaiveBayes are truly online
137+
and are not affected by batch size. Conversely, MiniBatchKMeans
138+
convergence rate is affected by the batch size. Also, its memory
139+
footprint can vary dramatically with batch size.
140+
1141
.. _computational_performance:
2142

3-
=========================
4143
Computational Performance
5144
=========================
6145

@@ -27,7 +166,7 @@ non-linear, or with fewer parameters) often run faster but are not always able
27166
to take into account the same exact properties of the data as more complex ones.
28167

29168
Prediction Latency
30-
==================
169+
------------------
31170

32171
One of the most straight-forward concerns one may have when using/choosing a
33172
machine learning toolkit is the latency at which predictions can be made in a
@@ -43,7 +182,7 @@ A last major parameter is also the possibility to do predictions in bulk or
43182
one-at-a-time mode.
44183

45184
Bulk versus Atomic mode
46-
-----------------------
185+
........................
47186

48187
In general doing predictions in bulk (many instances at the same time) is
49188
more efficient for a number of reasons (branching predictability, CPU cache,
@@ -68,27 +207,28 @@ To benchmark different estimators for your case you can simply change the
68207
:ref:`sphx_glr_auto_examples_applications_plot_prediction_latency.py`. This should give
69208
you an estimate of the order of magnitude of the prediction latency.
70209

71-
.. topic:: Configuring Scikit-learn for reduced validation overhead
210+
Configuring Scikit-learn for reduced validation overhead
211+
.........................................................
72212

73-
Scikit-learn does some validation on data that increases the overhead per
74-
call to ``predict`` and similar functions. In particular, checking that
75-
features are finite (not NaN or infinite) involves a full pass over the
76-
data. If you ensure that your data is acceptable, you may suppress
77-
checking for finiteness by setting the environment variable
78-
``SKLEARN_ASSUME_FINITE`` to a non-empty string before importing
79-
scikit-learn, or configure it in Python with :func:`sklearn.set_config`.
80-
For more control than these global settings, a :func:`config_context`
81-
allows you to set this configuration within a specified context::
213+
Scikit-learn does some validation on data that increases the overhead per
214+
call to ``predict`` and similar functions. In particular, checking that
215+
features are finite (not NaN or infinite) involves a full pass over the
216+
data. If you ensure that your data is acceptable, you may suppress
217+
checking for finiteness by setting the environment variable
218+
``SKLEARN_ASSUME_FINITE`` to a non-empty string before importing
219+
scikit-learn, or configure it in Python with :func:`sklearn.set_config`.
220+
For more control than these global settings, a :func:`config_context`
221+
allows you to set this configuration within a specified context::
82222

83-
>>> import sklearn
84-
>>> with sklearn.config_context(assume_finite=True):
85-
... pass # do learning/prediction here with reduced validation
223+
>>> import sklearn
224+
>>> with sklearn.config_context(assume_finite=True):
225+
... pass # do learning/prediction here with reduced validation
86226

87-
Note that this will affect all uses of
88-
:func:`sklearn.utils.assert_all_finite` within the context.
227+
Note that this will affect all uses of
228+
:func:`sklearn.utils.assert_all_finite` within the context.
89229

90230
Influence of the Number of Features
91-
-----------------------------------
231+
....................................
92232

93233
Obviously when the number of features increases so does the memory
94234
consumption of each example. Indeed, for a matrix of :math:`M` instances
@@ -109,7 +249,7 @@ the number of features (non-linear cases can happen depending on the global
109249
memory footprint and estimator).
110250

111251
Influence of the Input Data Representation
112-
------------------------------------------
252+
...........................................
113253

114254
Scipy provides sparse matrix data structures which are optimized for storing
115255
sparse data. The main feature of sparse formats is that you don't store zeros
@@ -142,7 +282,7 @@ for more information on how to build (or convert your data to) sparse matrix
142282
formats. Most of the time the ``CSR`` and ``CSC`` formats work best.
143283

144284
Influence of the Model Complexity
145-
---------------------------------
285+
..................................
146286

147287
Generally speaking, when model complexity increases, predictive power and
148288
latency are supposed to increase. Increasing predictive power is usually
@@ -206,7 +346,7 @@ with a speedy linear model but prediction power will very likely suffer in
206346
the process.
207347

208348
Feature Extraction Latency
209-
--------------------------
349+
..........................
210350

211351
Most scikit-learn models are usually pretty fast as they are implemented
212352
either with compiled Cython extensions or optimized computing libraries.
@@ -229,7 +369,7 @@ feature extraction code as it may be a good place to start optimizing when
229369
your overall latency is too slow for your application.
230370

231371
Prediction Throughput
232-
=====================
372+
----------------------
233373

234374
Another important metric to care about when sizing production systems is the
235375
throughput i.e. the number of predictions you can make in a given amount of
@@ -252,10 +392,10 @@ explanation on how to achieve this is beyond the scope of this documentation
252392
though.
253393

254394
Tips and Tricks
255-
===============
395+
----------------
256396

257397
Linear algebra libraries
258-
------------------------
398+
.........................
259399

260400
As scikit-learn relies heavily on Numpy/Scipy and linear algebra in general it
261401
makes sense to take explicit care of the versions of these libraries.
@@ -311,7 +451,7 @@ Debian / Ubuntu.
311451
.. _working_memory:
312452

313453
Limiting Working Memory
314-
-----------------------
454+
........................
315455

316456
Some calculations when implemented using standard numpy vectorized operations
317457
involve using a large amount of temporary memory. This may potentially exhaust
@@ -330,7 +470,7 @@ An example of a chunked operation adhering to this setting is
330470
row-wise reductions of a pairwise distance matrix.
331471

332472
Model Compression
333-
-----------------
473+
..................
334474

335475
Model compression in scikit-learn only concerns linear models for the moment.
336476
In this context it means that we want to control the model sparsity (i.e. the
@@ -357,7 +497,7 @@ Furthermore, sparsifying can be very useful to reduce the memory usage of
357497
predictive models deployed on production servers.
358498

359499
Model Reshaping
360-
---------------
500+
................
361501

362502
Model reshaping consists in selecting only a portion of the available features
363503
to fit a model. In other words, if a model discards features during the
@@ -376,7 +516,77 @@ In the case of sparse input (particularly in ``CSR`` format), it is generally
376516
sufficient to not generate the relevant features, leaving their columns empty.
377517

378518
Links
379-
-----
519+
......
380520

381521
- `scikit-learn developer performance documentation <../developers/performance.html>`_
382522
- `Scipy sparse matrix formats documentation <http://docs.scipy.org/doc/scipy/reference/sparse.html>`_
523+
524+
Parallelism, resource management, and configuration
525+
=====================================================
526+
527+
.. _parallelism:
528+
529+
Parallel and distributed computing
530+
-----------------------------------
531+
532+
Scikit-learn uses the `joblib <https://joblib.readthedocs.io/en/latest/>`__
533+
library to enable parallel computing inside its estimators. See the
534+
joblib documentation for the switches to control parallel computing.
535+
536+
Note that, by default, scikit-learn uses its embedded (vendored) version
537+
of joblib. A configuration switch (documented below) controls this
538+
behavior.
539+
540+
Configuration switches
541+
-----------------------
542+
543+
Python runtime
544+
..............
545+
546+
:func:`sklearn.set_config` controls the following behaviors:
547+
548+
:assume_finite:
549+
550+
used to skip validation, which enables faster computations but may
551+
lead to segmentation faults if the data contains NaNs.
552+
553+
:working_memory:
554+
555+
the optimal size of temporary arrays used by some algoritms.
556+
557+
.. _environment_variable:
558+
559+
Environment variables
560+
......................
561+
562+
These environment variables should be set before importing scikit-learn.
563+
564+
:SKLEARN_SITE_JOBLIB:
565+
566+
When this environment variable is set to a non zero value,
567+
scikit-learn uses the site joblib rather than its vendored version.
568+
Consequently, joblib must be installed for scikit-learn to run.
569+
Note that using the site joblib is at your own risks: the versions of
570+
scikt-learn and joblib need to be compatible. In addition, dumps from
571+
joblib.Memory might be incompatible, and you might loose some caches
572+
and have to redownload some datasets.
573+
574+
:SKLEARN_ASSUME_FINITE:
575+
576+
Sets the default value for the `assume_finite` argument of
577+
:func:`sklearn.set_config`.
578+
579+
:SKLEARN_WORKING_MEMORY:
580+
581+
Sets the default value for the `working_memory` argument of
582+
:func:`sklearn.set_config`.
583+
584+
:SKLEARN_SEED:
585+
586+
Sets the seed of the global random generator when running the tests,
587+
for reproducibility.
588+
589+
:SKLEARN_SKIP_NETWORK_TESTS:
590+
591+
When this environment variable is set to a non zero value, the tests
592+
that need network access are skipped.

0 commit comments

Comments
 (0)