scikit-learn-intelex 2024.0.1__py311-none-manylinux1_x86_64.whl → 2024.2.0__py311-none-manylinux1_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of scikit-learn-intelex might be problematic. Click here for more details.
- {scikit_learn_intelex-2024.0.1.dist-info → scikit_learn_intelex-2024.2.0.dist-info}/METADATA +2 -2
- scikit_learn_intelex-2024.2.0.dist-info/RECORD +101 -0
- sklearnex/__init__.py +3 -1
- sklearnex/__main__.py +0 -1
- sklearnex/_utils.py +15 -1
- sklearnex/basic_statistics/__init__.py +0 -1
- sklearnex/cluster/__init__.py +0 -1
- sklearnex/cluster/dbscan.py +2 -1
- sklearnex/cluster/k_means.py +0 -1
- sklearnex/cluster/tests/test_dbscan.py +0 -1
- sklearnex/cluster/tests/test_kmeans.py +0 -1
- sklearnex/covariance/__init__.py +19 -0
- sklearnex/covariance/incremental_covariance.py +130 -0
- sklearnex/covariance/tests/test_incremental_covariance.py +143 -0
- sklearnex/decomposition/__init__.py +0 -1
- sklearnex/decomposition/pca.py +0 -1
- sklearnex/decomposition/tests/test_pca.py +0 -1
- sklearnex/dispatcher.py +35 -1
- sklearnex/ensemble/__init__.py +0 -1
- sklearnex/ensemble/_forest.py +17 -2
- sklearnex/ensemble/tests/test_forest.py +0 -1
- sklearnex/glob/__main__.py +0 -1
- sklearnex/glob/dispatcher.py +0 -1
- sklearnex/linear_model/__init__.py +1 -3
- sklearnex/linear_model/coordinate_descent.py +0 -1
- sklearnex/linear_model/linear.py +9 -1
- sklearnex/linear_model/logistic_path.py +0 -1
- sklearnex/linear_model/logistic_regression.py +333 -0
- sklearnex/linear_model/ridge.py +0 -1
- sklearnex/linear_model/tests/test_linear.py +8 -3
- sklearnex/linear_model/tests/test_logreg.py +70 -6
- sklearnex/manifold/__init__.py +0 -1
- sklearnex/manifold/t_sne.py +0 -1
- sklearnex/manifold/tests/test_tsne.py +0 -1
- sklearnex/metrics/__init__.py +0 -1
- sklearnex/metrics/pairwise.py +0 -1
- sklearnex/metrics/ranking.py +0 -1
- sklearnex/metrics/tests/test_metrics.py +0 -1
- sklearnex/model_selection/__init__.py +0 -1
- sklearnex/model_selection/split.py +0 -1
- sklearnex/model_selection/tests/test_model_selection.py +0 -1
- sklearnex/neighbors/__init__.py +1 -2
- sklearnex/neighbors/_lof.py +167 -0
- sklearnex/neighbors/common.py +1 -2
- sklearnex/neighbors/knn_classification.py +5 -4
- sklearnex/neighbors/knn_regression.py +5 -4
- sklearnex/neighbors/knn_unsupervised.py +4 -3
- sklearnex/neighbors/tests/test_neighbors.py +12 -12
- sklearnex/preview/__init__.py +1 -2
- sklearnex/preview/cluster/__init__.py +0 -1
- sklearnex/preview/cluster/k_means.py +2 -1
- sklearnex/preview/covariance/__init__.py +19 -0
- sklearnex/preview/covariance/covariance.py +132 -0
- sklearnex/preview/covariance/tests/test_covariance.py +53 -0
- sklearnex/preview/decomposition/__init__.py +0 -1
- sklearnex/preview/decomposition/pca.py +43 -45
- sklearnex/preview/decomposition/tests/test_preview_pca.py +7 -3
- sklearnex/spmd/__init__.py +1 -0
- sklearnex/spmd/covariance/__init__.py +19 -0
- sklearnex/spmd/covariance/covariance.py +21 -0
- sklearnex/spmd/linear_model/__init__.py +2 -1
- sklearnex/spmd/linear_model/logistic_regression.py +21 -0
- sklearnex/svm/__init__.py +0 -1
- sklearnex/svm/nusvc.py +4 -0
- sklearnex/svm/nusvr.py +2 -0
- sklearnex/svm/svc.py +5 -1
- sklearnex/svm/svr.py +2 -0
- sklearnex/svm/tests/test_svm.py +0 -1
- sklearnex/tests/test_memory_usage.py +1 -4
- sklearnex/tests/test_monkeypatch.py +46 -16
- sklearnex/tests/test_n_jobs_support.py +93 -0
- sklearnex/tests/test_patching.py +19 -5
- sklearnex/utils/validation.py +0 -1
- scikit_learn_intelex-2024.0.1.dist-info/RECORD +0 -90
- sklearnex/neighbors/lof.py +0 -437
- {scikit_learn_intelex-2024.0.1.dist-info → scikit_learn_intelex-2024.2.0.dist-info}/LICENSE.txt +0 -0
- {scikit_learn_intelex-2024.0.1.dist-info → scikit_learn_intelex-2024.2.0.dist-info}/WHEEL +0 -0
- {scikit_learn_intelex-2024.0.1.dist-info → scikit_learn_intelex-2024.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
1
|
# ===============================================================================
|
|
3
2
|
# Copyright 2023 Intel Corporation
|
|
4
3
|
#
|
|
@@ -24,11 +23,12 @@ from sklearn.base import BaseEstimator
|
|
|
24
23
|
from sklearn.utils.extmath import stable_cumsum
|
|
25
24
|
from sklearn.utils.validation import check_array, check_is_fitted
|
|
26
25
|
|
|
26
|
+
from daal4py.sklearn._n_jobs_support import control_n_jobs
|
|
27
27
|
from daal4py.sklearn._utils import sklearn_check_version
|
|
28
28
|
from onedal.utils import _check_array
|
|
29
29
|
|
|
30
30
|
from ..._device_offload import dispatch
|
|
31
|
-
from ..._utils import PatchingConditionsChain
|
|
31
|
+
from ..._utils import PatchingConditionsChain, register_hyperparameters
|
|
32
32
|
|
|
33
33
|
if sklearn_check_version("1.1") and not sklearn_check_version("1.2"):
|
|
34
34
|
from sklearn.utils import check_scalar
|
|
@@ -39,10 +39,15 @@ else:
|
|
|
39
39
|
|
|
40
40
|
from sklearn.decomposition import PCA as sklearn_PCA
|
|
41
41
|
|
|
42
|
+
from onedal.common.hyperparameters import get_hyperparameters
|
|
42
43
|
from onedal.decomposition import PCA as onedal_PCA
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
@register_hyperparameters({"fit": get_hyperparameters("covariance", "compute")})
|
|
47
|
+
@control_n_jobs(decorated_methods=["fit", "transform"])
|
|
45
48
|
class PCA(sklearn_PCA):
|
|
49
|
+
__doc__ = sklearn_PCA.__doc__
|
|
50
|
+
|
|
46
51
|
if sklearn_check_version("1.2"):
|
|
47
52
|
_parameter_constraints: dict = {**sklearn_PCA._parameter_constraints}
|
|
48
53
|
|
|
@@ -99,23 +104,22 @@ class PCA(sklearn_PCA):
|
|
|
99
104
|
min_val=1,
|
|
100
105
|
target_type=numbers.Integral,
|
|
101
106
|
)
|
|
102
|
-
self._fit(X)
|
|
103
|
-
return self
|
|
104
|
-
|
|
105
|
-
def _fit(self, X):
|
|
106
|
-
if issparse(X):
|
|
107
|
-
raise TypeError(
|
|
108
|
-
"PCA does not support sparse input. See "
|
|
109
|
-
"TruncatedSVD for a possible alternative."
|
|
110
|
-
)
|
|
111
107
|
|
|
112
108
|
if sklearn_check_version("0.23"):
|
|
113
109
|
X = self._validate_data(
|
|
114
|
-
X,
|
|
110
|
+
X,
|
|
111
|
+
dtype=[np.float64, np.float32],
|
|
112
|
+
ensure_2d=True,
|
|
113
|
+
copy=False,
|
|
114
|
+
accept_sparse=True,
|
|
115
115
|
)
|
|
116
116
|
else:
|
|
117
117
|
X = _check_array(
|
|
118
|
-
X,
|
|
118
|
+
X,
|
|
119
|
+
dtype=[np.float64, np.float32],
|
|
120
|
+
ensure_2d=True,
|
|
121
|
+
copy=False,
|
|
122
|
+
accept_sparse=True,
|
|
119
123
|
)
|
|
120
124
|
|
|
121
125
|
n_samples, n_features = X.shape
|
|
@@ -132,7 +136,7 @@ class PCA(sklearn_PCA):
|
|
|
132
136
|
self._validate_n_components(n_components, n_samples, n_features, n_sf_min)
|
|
133
137
|
|
|
134
138
|
self._fit_svd_solver = self.svd_solver
|
|
135
|
-
|
|
139
|
+
|
|
136
140
|
if self._fit_svd_solver == "auto":
|
|
137
141
|
if sklearn_check_version("1.1"):
|
|
138
142
|
if max(X.shape) <= 500 or n_components == "mle":
|
|
@@ -164,37 +168,21 @@ class PCA(sklearn_PCA):
|
|
|
164
168
|
else:
|
|
165
169
|
self._fit_svd_solver = "full"
|
|
166
170
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
"fit",
|
|
178
|
-
{
|
|
179
|
-
"onedal": self.__class__._onedal_fit,
|
|
180
|
-
"sklearn": sklearn_PCA._fit_full,
|
|
181
|
-
},
|
|
182
|
-
X,
|
|
183
|
-
)
|
|
184
|
-
elif not shape_good_for_daal and self._fit_svd_solver == "full":
|
|
185
|
-
return sklearn_PCA._fit_full(self, X, n_components)
|
|
186
|
-
elif self._fit_svd_solver in ["arpack", "randomized"]:
|
|
187
|
-
return sklearn_PCA._fit_truncated(
|
|
188
|
-
self,
|
|
189
|
-
X,
|
|
190
|
-
n_components,
|
|
191
|
-
self._fit_svd_solver,
|
|
192
|
-
)
|
|
193
|
-
else:
|
|
194
|
-
raise ValueError("Unrecognized svd_solver='{0}'".format(self._fit_svd_solver))
|
|
171
|
+
dispatch(
|
|
172
|
+
self,
|
|
173
|
+
"fit",
|
|
174
|
+
{
|
|
175
|
+
"onedal": self.__class__._onedal_fit,
|
|
176
|
+
"sklearn": sklearn_PCA.fit,
|
|
177
|
+
},
|
|
178
|
+
X,
|
|
179
|
+
)
|
|
180
|
+
return self
|
|
195
181
|
|
|
196
182
|
def _onedal_supported(self, method_name, *data):
|
|
197
183
|
class_name = self.__class__.__name__
|
|
184
|
+
X = data[0]
|
|
185
|
+
|
|
198
186
|
if method_name == "fit":
|
|
199
187
|
patching_status = PatchingConditionsChain(
|
|
200
188
|
f"sklearn.decomposition.{class_name}.{method_name}"
|
|
@@ -206,6 +194,12 @@ class PCA(sklearn_PCA):
|
|
|
206
194
|
f"'{self._fit_svd_solver}' SVD solver is not supported. "
|
|
207
195
|
"Only 'full' solver is supported.",
|
|
208
196
|
),
|
|
197
|
+
(not issparse(X), "oneDAL PCA does not support sparse inputs"),
|
|
198
|
+
(
|
|
199
|
+
X.shape[1] / X.shape[0] < 2,
|
|
200
|
+
"The shape of X does not satisfy oneDAL requirements: "
|
|
201
|
+
"number of features / number of samples >= 2",
|
|
202
|
+
),
|
|
209
203
|
]
|
|
210
204
|
)
|
|
211
205
|
return patching_status
|
|
@@ -290,7 +284,7 @@ class PCA(sklearn_PCA):
|
|
|
290
284
|
if self.whiten:
|
|
291
285
|
X_new /= np.sqrt(self.explained_variance_)
|
|
292
286
|
else:
|
|
293
|
-
return
|
|
287
|
+
return super().transform(X)
|
|
294
288
|
return X_new
|
|
295
289
|
|
|
296
290
|
def fit_transform(self, X, y=None):
|
|
@@ -308,7 +302,7 @@ class PCA(sklearn_PCA):
|
|
|
308
302
|
Transformed values of X.
|
|
309
303
|
"""
|
|
310
304
|
if self.svd_solver in ["randomized", "arpack"]:
|
|
311
|
-
return
|
|
305
|
+
return super().fit_transform(X)
|
|
312
306
|
else:
|
|
313
307
|
self.fit(X)
|
|
314
308
|
if hasattr(self, "_onedal_estimator"):
|
|
@@ -317,7 +311,11 @@ class PCA(sklearn_PCA):
|
|
|
317
311
|
X_new /= np.sqrt(self.explained_variance_)
|
|
318
312
|
return X_new
|
|
319
313
|
else:
|
|
320
|
-
return
|
|
314
|
+
return super().transform(X)
|
|
315
|
+
|
|
316
|
+
fit.__doc__ = sklearn_PCA.fit.__doc__
|
|
317
|
+
transform.__doc__ = sklearn_PCA.transform.__doc__
|
|
318
|
+
fit_transform.__doc__ = sklearn_PCA.fit_transform.__doc__
|
|
321
319
|
|
|
322
320
|
def _save_attributes(self):
|
|
323
321
|
self.n_samples_ = self._onedal_estimator.n_samples_
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
1
|
# ===============================================================================
|
|
3
2
|
# Copyright 2023 Intel Corporation
|
|
4
3
|
#
|
|
@@ -19,6 +18,7 @@ import numpy as np
|
|
|
19
18
|
import pytest
|
|
20
19
|
from numpy.testing import assert_allclose
|
|
21
20
|
|
|
21
|
+
from daal4py.sklearn._utils import daal_check_version
|
|
22
22
|
from onedal.tests.utils._dataframes_support import (
|
|
23
23
|
_as_numpy,
|
|
24
24
|
_convert_to_dataframe,
|
|
@@ -27,12 +27,16 @@ from onedal.tests.utils._dataframes_support import (
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues())
|
|
30
|
-
|
|
30
|
+
@pytest.mark.parametrize("macro_block", [None, 1024])
|
|
31
|
+
def test_sklearnex_import(dataframe, queue, macro_block):
|
|
31
32
|
from sklearnex.preview.decomposition import PCA
|
|
32
33
|
|
|
33
34
|
X = [[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]]
|
|
34
35
|
X = _convert_to_dataframe(X, sycl_queue=queue, target_df=dataframe)
|
|
35
|
-
pca = PCA(n_components=2, svd_solver="full")
|
|
36
|
+
pca = PCA(n_components=2, svd_solver="full")
|
|
37
|
+
if daal_check_version((2024, "P", 0)) and macro_block is not None:
|
|
38
|
+
pca.get_hyperparameters("fit").cpu_macro_block = macro_block
|
|
39
|
+
pca.fit(X)
|
|
36
40
|
assert "sklearnex" in pca.__module__
|
|
37
41
|
assert hasattr(pca, "_onedal_estimator")
|
|
38
42
|
assert_allclose(_as_numpy(pca.singular_values_), [6.30061232, 0.54980396])
|
sklearnex/spmd/__init__.py
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright 2024 Intel Corporation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
# ==============================================================================
|
|
16
|
+
|
|
17
|
+
from .covariance import EmpiricalCovariance
|
|
18
|
+
|
|
19
|
+
__all__ = ["EmpiricalCovariance"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright 2024 Intel Corporation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
# ==============================================================================
|
|
16
|
+
|
|
17
|
+
from onedal.spmd.covariance import EmpiricalCovariance
|
|
18
|
+
|
|
19
|
+
# TODO:
|
|
20
|
+
# Currently it uses `onedal` module interface.
|
|
21
|
+
# Add sklearnex dispatching.
|
|
@@ -15,5 +15,6 @@
|
|
|
15
15
|
# ==============================================================================
|
|
16
16
|
|
|
17
17
|
from .linear_model import LinearRegression
|
|
18
|
+
from .logistic_regression import LogisticRegression
|
|
18
19
|
|
|
19
|
-
__all__ = ["LinearRegression"]
|
|
20
|
+
__all__ = ["LinearRegression", "LogisticRegression"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright 2024 Intel Corporation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
# ==============================================================================
|
|
16
|
+
|
|
17
|
+
from onedal.spmd.linear_model import LogisticRegression
|
|
18
|
+
|
|
19
|
+
# TODO:
|
|
20
|
+
# Currently it uses `onedal` module interface.
|
|
21
|
+
# Add sklearnex dispatching.
|
sklearnex/svm/__init__.py
CHANGED
sklearnex/svm/nusvc.py
CHANGED
|
@@ -18,6 +18,7 @@ from sklearn.exceptions import NotFittedError
|
|
|
18
18
|
from sklearn.svm import NuSVC as sklearn_NuSVC
|
|
19
19
|
from sklearn.utils.validation import _deprecate_positional_args
|
|
20
20
|
|
|
21
|
+
from daal4py.sklearn._n_jobs_support import control_n_jobs
|
|
21
22
|
from daal4py.sklearn._utils import sklearn_check_version
|
|
22
23
|
|
|
23
24
|
from .._device_offload import dispatch, wrap_output_data
|
|
@@ -29,6 +30,9 @@ if sklearn_check_version("1.0"):
|
|
|
29
30
|
from onedal.svm import NuSVC as onedal_NuSVC
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
@control_n_jobs(
|
|
34
|
+
decorated_methods=["fit", "predict", "_predict_proba", "decision_function"]
|
|
35
|
+
)
|
|
32
36
|
class NuSVC(sklearn_NuSVC, BaseSVC):
|
|
33
37
|
__doc__ = sklearn_NuSVC.__doc__
|
|
34
38
|
|
sklearnex/svm/nusvr.py
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
from sklearn.svm import NuSVR as sklearn_NuSVR
|
|
18
18
|
from sklearn.utils.validation import _deprecate_positional_args
|
|
19
19
|
|
|
20
|
+
from daal4py.sklearn._n_jobs_support import control_n_jobs
|
|
20
21
|
from daal4py.sklearn._utils import sklearn_check_version
|
|
21
22
|
from onedal.svm import NuSVR as onedal_NuSVR
|
|
22
23
|
|
|
@@ -24,6 +25,7 @@ from .._device_offload import dispatch, wrap_output_data
|
|
|
24
25
|
from ._common import BaseSVR
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
@control_n_jobs(decorated_methods=["fit", "predict"])
|
|
27
29
|
class NuSVR(sklearn_NuSVR, BaseSVR):
|
|
28
30
|
__doc__ = sklearn_NuSVR.__doc__
|
|
29
31
|
|
sklearnex/svm/svc.py
CHANGED
|
@@ -20,6 +20,7 @@ from sklearn.exceptions import NotFittedError
|
|
|
20
20
|
from sklearn.svm import SVC as sklearn_SVC
|
|
21
21
|
from sklearn.utils.validation import _deprecate_positional_args
|
|
22
22
|
|
|
23
|
+
from daal4py.sklearn._n_jobs_support import control_n_jobs
|
|
23
24
|
from daal4py.sklearn._utils import sklearn_check_version
|
|
24
25
|
|
|
25
26
|
from .._device_offload import dispatch, wrap_output_data
|
|
@@ -32,6 +33,9 @@ if sklearn_check_version("1.0"):
|
|
|
32
33
|
from onedal.svm import SVC as onedal_SVC
|
|
33
34
|
|
|
34
35
|
|
|
36
|
+
@control_n_jobs(
|
|
37
|
+
decorated_methods=["fit", "predict", "_predict_proba", "decision_function"]
|
|
38
|
+
)
|
|
35
39
|
class SVC(sklearn_SVC, BaseSVC):
|
|
36
40
|
__doc__ = sklearn_SVC.__doc__
|
|
37
41
|
|
|
@@ -235,7 +239,7 @@ class SVC(sklearn_SVC, BaseSVC):
|
|
|
235
239
|
)
|
|
236
240
|
if len(data) > 1:
|
|
237
241
|
self._class_count = len(np.unique(data[1]))
|
|
238
|
-
self._is_sparse = sp.
|
|
242
|
+
self._is_sparse = sp.issparse(data[0])
|
|
239
243
|
conditions = [
|
|
240
244
|
(
|
|
241
245
|
self.kernel in ["linear", "rbf"],
|
sklearnex/svm/svr.py
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
from sklearn.svm import SVR as sklearn_SVR
|
|
18
18
|
from sklearn.utils.validation import _deprecate_positional_args
|
|
19
19
|
|
|
20
|
+
from daal4py.sklearn._n_jobs_support import control_n_jobs
|
|
20
21
|
from daal4py.sklearn._utils import sklearn_check_version
|
|
21
22
|
from onedal.svm import SVR as onedal_SVR
|
|
22
23
|
|
|
@@ -24,6 +25,7 @@ from .._device_offload import dispatch, wrap_output_data
|
|
|
24
25
|
from ._common import BaseSVR
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
@control_n_jobs(decorated_methods=["fit", "predict"])
|
|
27
29
|
class SVR(sklearn_SVR, BaseSVR):
|
|
28
30
|
__doc__ = sklearn_SVR.__doc__
|
|
29
31
|
|
sklearnex/svm/tests/test_svm.py
CHANGED
|
@@ -94,10 +94,7 @@ def remove_duplicated_estimators(estimators_list):
|
|
|
94
94
|
return estimators_map.values()
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
BANNED_ESTIMATORS = (
|
|
98
|
-
"LocalOutlierFactor", # fails on ndarray_c for sklearn > 1.0
|
|
99
|
-
"TSNE", # too slow for using in testing on common data size
|
|
100
|
-
)
|
|
97
|
+
BANNED_ESTIMATORS = ("TSNE",) # too slow for using in testing on common data size
|
|
101
98
|
estimators = [
|
|
102
99
|
PreviewPCA,
|
|
103
100
|
TrainTestSplitEstimator,
|
|
@@ -45,8 +45,12 @@ def test_monkey_patching():
|
|
|
45
45
|
n = _classes[i][1]
|
|
46
46
|
|
|
47
47
|
sklearnex.unpatch_sklearn(t)
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
sklearn_class = getattr(p, n, None)
|
|
49
|
+
if sklearn_class is not None:
|
|
50
|
+
sklearn_class = sklearn_class.__module__
|
|
51
|
+
assert sklearn_class is None or sklearn_class.startswith(
|
|
52
|
+
"sklearn"
|
|
53
|
+
), "Unpatching has completed with error."
|
|
50
54
|
|
|
51
55
|
sklearnex.unpatch_sklearn()
|
|
52
56
|
|
|
@@ -55,8 +59,12 @@ def test_monkey_patching():
|
|
|
55
59
|
p = _classes[i][0]
|
|
56
60
|
n = _classes[i][1]
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
sklearn_class = getattr(p, n, None)
|
|
63
|
+
if sklearn_class is not None:
|
|
64
|
+
sklearn_class = sklearn_class.__module__
|
|
65
|
+
assert sklearn_class is None or sklearn_class.startswith(
|
|
66
|
+
"sklearn"
|
|
67
|
+
), "Unpatching has completed with error."
|
|
60
68
|
|
|
61
69
|
sklearnex.unpatch_sklearn()
|
|
62
70
|
|
|
@@ -85,7 +93,10 @@ def test_patch_by_list_simple():
|
|
|
85
93
|
|
|
86
94
|
assert RandomForestRegressor.__module__.startswith("sklearn")
|
|
87
95
|
assert KNeighborsRegressor.__module__.startswith("sklearn")
|
|
88
|
-
|
|
96
|
+
if daal_check_version((2024, "P", 1)):
|
|
97
|
+
assert LogisticRegression.__module__.startswith("sklearnex")
|
|
98
|
+
else:
|
|
99
|
+
assert LogisticRegression.__module__.startswith("daal4py")
|
|
89
100
|
assert SVC.__module__.startswith("sklearn")
|
|
90
101
|
|
|
91
102
|
sklearnex.unpatch_sklearn()
|
|
@@ -101,7 +112,10 @@ def test_patch_by_list_many_estimators():
|
|
|
101
112
|
|
|
102
113
|
assert RandomForestRegressor.__module__.startswith("sklearn")
|
|
103
114
|
assert KNeighborsRegressor.__module__.startswith("sklearn")
|
|
104
|
-
|
|
115
|
+
if daal_check_version((2024, "P", 1)):
|
|
116
|
+
assert LogisticRegression.__module__.startswith("sklearnex")
|
|
117
|
+
else:
|
|
118
|
+
assert LogisticRegression.__module__.startswith("daal4py")
|
|
105
119
|
assert SVC.__module__.startswith("daal4py") or SVC.__module__.startswith("sklearnex")
|
|
106
120
|
|
|
107
121
|
sklearnex.unpatch_sklearn()
|
|
@@ -119,7 +133,10 @@ def test_unpatch_by_list_many_estimators():
|
|
|
119
133
|
assert KNeighborsRegressor.__module__.startswith(
|
|
120
134
|
"daal4py"
|
|
121
135
|
) or KNeighborsRegressor.__module__.startswith("sklearnex")
|
|
122
|
-
|
|
136
|
+
if daal_check_version((2024, "P", 1)):
|
|
137
|
+
assert LogisticRegression.__module__.startswith("sklearnex")
|
|
138
|
+
else:
|
|
139
|
+
assert LogisticRegression.__module__.startswith("daal4py")
|
|
123
140
|
assert SVC.__module__.startswith("daal4py") or SVC.__module__.startswith("sklearnex")
|
|
124
141
|
|
|
125
142
|
sklearnex.unpatch_sklearn(["KNeighborsRegressor", "RandomForestRegressor"])
|
|
@@ -131,7 +148,11 @@ def test_unpatch_by_list_many_estimators():
|
|
|
131
148
|
|
|
132
149
|
assert RandomForestRegressor.__module__.startswith("sklearn")
|
|
133
150
|
assert KNeighborsRegressor.__module__.startswith("sklearn")
|
|
134
|
-
|
|
151
|
+
if daal_check_version((2024, "P", 1)):
|
|
152
|
+
assert LogisticRegression.__module__.startswith("sklearnex")
|
|
153
|
+
else:
|
|
154
|
+
assert LogisticRegression.__module__.startswith("daal4py")
|
|
155
|
+
|
|
135
156
|
assert SVC.__module__.startswith("daal4py") or SVC.__module__.startswith("sklearnex")
|
|
136
157
|
|
|
137
158
|
|
|
@@ -164,14 +185,22 @@ def test_preview_namespace():
|
|
|
164
185
|
from sklearn.linear_model import LinearRegression
|
|
165
186
|
from sklearn.svm import SVC
|
|
166
187
|
|
|
167
|
-
return
|
|
188
|
+
return (
|
|
189
|
+
LinearRegression(),
|
|
190
|
+
PCA(),
|
|
191
|
+
DBSCAN(),
|
|
192
|
+
SVC(),
|
|
193
|
+
RandomForestClassifier(),
|
|
194
|
+
)
|
|
168
195
|
|
|
169
196
|
# BUG: previous patching tests force PCA to be patched with daal4py.
|
|
170
197
|
# This unpatching returns behavior to expected
|
|
171
198
|
sklearnex.unpatch_sklearn()
|
|
172
199
|
# behavior with enabled preview
|
|
173
200
|
sklearnex.patch_sklearn(preview=True)
|
|
174
|
-
|
|
201
|
+
from sklearnex.dispatcher import _is_preview_enabled
|
|
202
|
+
|
|
203
|
+
assert _is_preview_enabled()
|
|
175
204
|
|
|
176
205
|
lr, pca, dbscan, svc, rfc = get_estimators()
|
|
177
206
|
assert "sklearnex" in rfc.__module__
|
|
@@ -188,21 +217,22 @@ def test_preview_namespace():
|
|
|
188
217
|
|
|
189
218
|
# no patching behavior
|
|
190
219
|
lr, pca, dbscan, svc, rfc = get_estimators()
|
|
191
|
-
assert "sklearn." in lr.__module__
|
|
192
|
-
assert "sklearn." in pca.__module__
|
|
193
|
-
assert "sklearn." in dbscan.__module__
|
|
194
|
-
assert "sklearn." in svc.__module__
|
|
195
|
-
assert "sklearn." in rfc.__module__
|
|
220
|
+
assert "sklearn." in lr.__module__ and "daal4py" not in lr.__module__
|
|
221
|
+
assert "sklearn." in pca.__module__ and "daal4py" not in pca.__module__
|
|
222
|
+
assert "sklearn." in dbscan.__module__ and "daal4py" not in dbscan.__module__
|
|
223
|
+
assert "sklearn." in svc.__module__ and "daal4py" not in svc.__module__
|
|
224
|
+
assert "sklearn." in rfc.__module__ and "daal4py" not in rfc.__module__
|
|
196
225
|
|
|
197
226
|
# default patching behavior
|
|
198
227
|
sklearnex.patch_sklearn()
|
|
199
|
-
assert not
|
|
228
|
+
assert not _is_preview_enabled()
|
|
200
229
|
|
|
201
230
|
lr, pca, dbscan, svc, rfc = get_estimators()
|
|
202
231
|
if daal_check_version((2023, "P", 100)):
|
|
203
232
|
assert "sklearnex" in lr.__module__
|
|
204
233
|
else:
|
|
205
234
|
assert "daal4py" in lr.__module__
|
|
235
|
+
|
|
206
236
|
assert "daal4py" in pca.__module__
|
|
207
237
|
assert "sklearnex" in rfc.__module__
|
|
208
238
|
assert "sklearnex" in dbscan.__module__
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Copyright 2023 Intel Corporation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
# ==============================================================================
|
|
16
|
+
|
|
17
|
+
import inspect
|
|
18
|
+
import logging
|
|
19
|
+
from multiprocessing import cpu_count
|
|
20
|
+
|
|
21
|
+
import pytest
|
|
22
|
+
from sklearn.base import BaseEstimator
|
|
23
|
+
from sklearn.datasets import make_classification
|
|
24
|
+
|
|
25
|
+
from sklearnex.dispatcher import get_patch_map
|
|
26
|
+
from sklearnex.svm import SVC, NuSVC
|
|
27
|
+
|
|
28
|
+
ESTIMATORS = set(
|
|
29
|
+
filter(
|
|
30
|
+
lambda x: inspect.isclass(x) and issubclass(x, BaseEstimator),
|
|
31
|
+
[value[0][0][2] for value in get_patch_map().values()],
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
X, Y = make_classification(n_samples=40, n_features=4, random_state=42)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.parametrize("estimator_class", ESTIMATORS)
|
|
39
|
+
@pytest.mark.parametrize("n_jobs", [None, -1, 1, 2])
|
|
40
|
+
def test_n_jobs_support(caplog, estimator_class, n_jobs):
|
|
41
|
+
def check_estimator_doc(estimator):
|
|
42
|
+
if estimator.__doc__ is not None:
|
|
43
|
+
assert "n_jobs" in estimator.__doc__
|
|
44
|
+
|
|
45
|
+
def check_n_jobs_entry_in_logs(caplog, function_name, n_jobs):
|
|
46
|
+
for rec in caplog.records:
|
|
47
|
+
if function_name in rec.message and "threads" in rec.message:
|
|
48
|
+
expected_n_jobs = n_jobs if n_jobs > 0 else cpu_count() + 1 + n_jobs
|
|
49
|
+
logging.info(f"{function_name}: setting {expected_n_jobs} threads")
|
|
50
|
+
if f"{function_name}: setting {expected_n_jobs} threads" in rec.message:
|
|
51
|
+
return True
|
|
52
|
+
# False if n_jobs is set and not found in logs
|
|
53
|
+
return n_jobs is None
|
|
54
|
+
|
|
55
|
+
def check_method(*args, method, caplog):
|
|
56
|
+
method(*args)
|
|
57
|
+
assert check_n_jobs_entry_in_logs(caplog, method.__name__, n_jobs)
|
|
58
|
+
|
|
59
|
+
def check_methods_decoration(estimator):
|
|
60
|
+
funcs = {
|
|
61
|
+
i: getattr(estimator, i)
|
|
62
|
+
for i in dir(estimator)
|
|
63
|
+
if hasattr(estimator, i) and callable(getattr(estimator, i))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for func_name, func in funcs.items():
|
|
67
|
+
assert hasattr(func, "__onedal_n_jobs_decorated__") == (
|
|
68
|
+
func_name in estimator._n_jobs_supported_onedal_methods
|
|
69
|
+
), f"{estimator}.{func_name} n_jobs decoration does not match {estimator} n_jobs supported methods"
|
|
70
|
+
|
|
71
|
+
caplog.set_level(logging.DEBUG, logger="sklearnex")
|
|
72
|
+
estimator_kwargs = {"n_jobs": n_jobs}
|
|
73
|
+
# by default, [Nu]SVC.predict_proba is restricted by @available_if decorator
|
|
74
|
+
if estimator_class in [SVC, NuSVC]:
|
|
75
|
+
estimator_kwargs["probability"] = True
|
|
76
|
+
estimator_instance = estimator_class(**estimator_kwargs)
|
|
77
|
+
# check `n_jobs` parameter doc entry
|
|
78
|
+
check_estimator_doc(estimator_class)
|
|
79
|
+
check_estimator_doc(estimator_instance)
|
|
80
|
+
# check `n_jobs` log entry for supported methods
|
|
81
|
+
# `fit` call is required before other methods
|
|
82
|
+
check_method(X, Y, method=estimator_instance.fit, caplog=caplog)
|
|
83
|
+
for method_name in estimator_instance._n_jobs_supported_onedal_methods:
|
|
84
|
+
if method_name == "fit":
|
|
85
|
+
continue
|
|
86
|
+
method = getattr(estimator_instance, method_name)
|
|
87
|
+
if len(inspect.signature(method).parameters) == 0:
|
|
88
|
+
check_method(method=method, caplog=caplog)
|
|
89
|
+
else:
|
|
90
|
+
check_method(X, method=method, caplog=caplog)
|
|
91
|
+
# check if correct methods were decorated
|
|
92
|
+
check_methods_decoration(estimator_class)
|
|
93
|
+
check_methods_decoration(estimator_instance)
|
sklearnex/tests/test_patching.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
# ==============================================================================
|
|
16
16
|
|
|
17
|
+
import inspect
|
|
17
18
|
import os
|
|
18
19
|
import pathlib
|
|
19
20
|
import re
|
|
@@ -96,15 +97,15 @@ def _load_all_models(patched):
|
|
|
96
97
|
if patched:
|
|
97
98
|
patch_sklearn()
|
|
98
99
|
|
|
99
|
-
models =
|
|
100
|
+
models = {}
|
|
100
101
|
for patch_infos in get_patch_map().values():
|
|
101
|
-
maybe_class = getattr(patch_infos[0][0][0], patch_infos[0][0][1])
|
|
102
|
+
maybe_class = getattr(patch_infos[0][0][0], patch_infos[0][0][1], None)
|
|
102
103
|
if (
|
|
103
104
|
maybe_class is not None
|
|
104
105
|
and isclass(maybe_class)
|
|
105
106
|
and issubclass(maybe_class, BaseEstimator)
|
|
106
107
|
):
|
|
107
|
-
models
|
|
108
|
+
models[patch_infos[0][0][1]] = maybe_class
|
|
108
109
|
|
|
109
110
|
if patched:
|
|
110
111
|
unpatch_sklearn()
|
|
@@ -116,7 +117,20 @@ PATCHED_MODELS = _load_all_models(patched=True)
|
|
|
116
117
|
UNPATCHED_MODELS = _load_all_models(patched=False)
|
|
117
118
|
|
|
118
119
|
|
|
119
|
-
@pytest.mark.parametrize(
|
|
120
|
-
def test_is_patched_instance(
|
|
120
|
+
@pytest.mark.parametrize("estimator", UNPATCHED_MODELS.keys())
|
|
121
|
+
def test_is_patched_instance(estimator):
|
|
122
|
+
patched = PATCHED_MODELS[estimator]
|
|
123
|
+
unpatched = UNPATCHED_MODELS[estimator]
|
|
121
124
|
assert is_patched_instance(patched), f"{patched} is a patched instance"
|
|
122
125
|
assert not is_patched_instance(unpatched), f"{unpatched} is an unpatched instance"
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@pytest.mark.parametrize("member", ["_onedal_cpu_supported", "_onedal_gpu_supported"])
|
|
129
|
+
@pytest.mark.parametrize(
|
|
130
|
+
"name",
|
|
131
|
+
[i for i in PATCHED_MODELS.keys() if "sklearnex" in PATCHED_MODELS[i].__module__],
|
|
132
|
+
)
|
|
133
|
+
def test_onedal_supported_member(name, member):
|
|
134
|
+
patched = PATCHED_MODELS[name]
|
|
135
|
+
sig = str(inspect.signature(getattr(patched, member)))
|
|
136
|
+
assert "(self, method_name, *data)" == sig
|
sklearnex/utils/validation.py
CHANGED