scm2cpp-lasso 0.13.1__tar.gz → 0.14.0__tar.gz
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.
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/PKG-INFO +59 -6
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/README.md +58 -5
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/pyproject.toml +1 -1
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/setup.py +19 -4
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/__init__.py +472 -248
- scm2cpp_lasso-0.14.0/src/scm2cpp_lasso/_compat.py +283 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso.egg-info/PKG-INFO +59 -6
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso.egg-info/SOURCES.txt +1 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/setup.cfg +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/__init__.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_accel_cublas.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_classifiers.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_derived_blas.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_derived_cublas.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_derived_loops.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_gpu_cuda.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_gramops_blas.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_gramops_loops.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_nmf_blas.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_nmf_cublas.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/_loader_nmf_loops.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/classifiers.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/classifiers.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/classifiers_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/lasso_cov.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/lasso_cov.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/lasso_cov_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd_capi.cpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/scm2cpp-blas.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/scm2cpp-cublas.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/scm2cpp-cuda.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_generated/scm2cpp.hpp +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/_libfind.py +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso/batch_capi.cu +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso.egg-info/dependency_links.txt +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso.egg-info/requires.txt +0 -0
- {scm2cpp_lasso-0.13.1 → scm2cpp_lasso-0.14.0}/src/scm2cpp_lasso.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scm2cpp-lasso
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: scikit-learn estimators (lasso, elastic net, ridge, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver and CUDA kernels included
|
|
5
5
|
Author: Hirotaka Niitsuma
|
|
6
6
|
License: MIT
|
|
@@ -18,6 +18,8 @@ Requires-Dist: numpy>=1.17
|
|
|
18
18
|
|
|
19
19
|
# scm2cpp-lasso
|
|
20
20
|
|
|
21
|
+
[](https://colab.research.google.com/github/niitsuma/scm2cpp/blob/master/notebooks/compare-sklearn.ipynb)
|
|
22
|
+
|
|
21
23
|
*[Japanese (README.ja.md)](README.ja.md)*
|
|
22
24
|
|
|
23
25
|
Lasso by coordinate descent over a Gram matrix, with an optional GPU
|
|
@@ -28,8 +30,9 @@ path. The solver is Scheme, translated to C++ by
|
|
|
28
30
|
$ pip install scm2cpp-lasso
|
|
29
31
|
```
|
|
30
32
|
|
|
31
|
-
On Linux x86_64
|
|
32
|
-
|
|
33
|
+
On Linux x86_64, macOS arm64 (macOS 14 or later) and Windows AMD64
|
|
34
|
+
this installs a wheel: compiled, nothing to build (with OpenBLAS
|
|
35
|
+
inside on Linux and macOS; Windows has the loop variants). Elsewhere pip builds the sdist,
|
|
33
36
|
which needs a C++17 compiler and nothing else. The wheels carry no
|
|
34
37
|
GPU code (a wheel cannot know the device); for the GPU builds, install
|
|
35
38
|
from the sdist on a machine with `nvcc` on the path:
|
|
@@ -99,6 +102,55 @@ at zero, and `lambda_grid()` walks down from it -- the construction
|
|
|
99
102
|
scikit-learn uses. If your columns differ wildly in scale, standardize
|
|
100
103
|
them first; this solver does not do it for you.
|
|
101
104
|
|
|
105
|
+
## scikit-learn compatibility
|
|
106
|
+
|
|
107
|
+
From 0.14.0 every estimator with a `fit(X, y)` (or `fit(X)`) derives
|
|
108
|
+
from scikit-learn's `BaseEstimator` and the matching mixin, so `clone`,
|
|
109
|
+
`get_params` / `set_params`, `GridSearchCV`, `Pipeline` and
|
|
110
|
+
`cross_val_score` take them, and all 39 pass
|
|
111
|
+
`sklearn.utils.estimator_checks.check_estimator` (`check-sklearn.py`
|
|
112
|
+
runs it; the one expected failure is `LBFGSLogisticRegressionCV`'s
|
|
113
|
+
`n_iter_` of 0 for a C whose warm start is already converged, which
|
|
114
|
+
scikit-learn's own `LogisticRegressionCV` reports on the same data).
|
|
115
|
+
scikit-learn stays optional: without it a numpy-only stand-in gives
|
|
116
|
+
`get_params`, `set_params`, `score` and the same input checks.
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from sklearn.model_selection import GridSearchCV
|
|
120
|
+
from scm2cpp_lasso import GramLasso
|
|
121
|
+
|
|
122
|
+
GridSearchCV(GramLasso(), {"alpha": [0.01, 0.1, 1.0]}, cv=5).fit(X, y)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`GramLasso`, `GramElasticNet` and `GramRidge` are the `fit(X, y)`
|
|
126
|
+
forms, with the intercept, over the Gram-matrix solvers; `CovLasso`,
|
|
127
|
+
`CovRidge`, `DerivedLasso`, `CovLogistic`, `CovGroupLasso` and
|
|
128
|
+
`CovMultiTaskLasso` keep their data-in-the-constructor interface,
|
|
129
|
+
which solves a whole path at once.
|
|
130
|
+
|
|
131
|
+
What it costs is the input checks: X must be a finite 2-D float64
|
|
132
|
+
array with the feature count of the fit. A plain C-ordered float64
|
|
133
|
+
ndarray is checked directly (one sum for finiteness); anything else (a
|
|
134
|
+
list, a DataFrame, another dtype) goes through scikit-learn's
|
|
135
|
+
`validate_data`, which raises the errors scikit-learn raises. The
|
|
136
|
+
checks alone, per call (`bench/sklearn-compat-overhead.py --checks`):
|
|
137
|
+
|
|
138
|
+
| X | fit | predict | predict, 50 rows | validate_data |
|
|
139
|
+
|---|---|---|---|---|
|
|
140
|
+
| 200 x 10 | 13 us | 7 us | 9 us | 173 us |
|
|
141
|
+
| 2000 x 50 | 47 us | 36 us | 9 us | 224 us |
|
|
142
|
+
| 20000 x 200 | 2.7 ms | 3.2 ms | 13 us | 3.2 ms |
|
|
143
|
+
|
|
144
|
+
The finiteness sum is the size-dependent part; under
|
|
145
|
+
`sklearn.set_config(assume_finite=True)` every row is about 3 us.
|
|
146
|
+
Whole calls, before and after (`bench/sklearn-compat-overhead.py`, 30
|
|
147
|
+
estimators, three shapes, the two packages alternating on one core of
|
|
148
|
+
a loaded machine): fits of a millisecond or more are unchanged within
|
|
149
|
+
the run-to-run spread (about 10%); fits of about 0.1 ms take 10 to
|
|
150
|
+
30% (10 to 40 us) longer; predict on 20000 x 200 takes about twice as
|
|
151
|
+
long (3 ms to 6 ms, the finiteness sum costing as much as the product
|
|
152
|
+
itself), and on small inputs 5 to 10 us longer.
|
|
153
|
+
|
|
102
154
|
## Estimators at a glance
|
|
103
155
|
|
|
104
156
|
Every estimator, the scikit-learn estimator it reproduces, the Scheme
|
|
@@ -107,12 +159,13 @@ it runs on, and whether Intel's sklearnex accelerates the scikit-learn
|
|
|
107
159
|
side. Builds: *loops* is the plain translation, *BLAS* / *cuBLAS* the
|
|
108
160
|
products handed to (cu)BLAS, *--cuda* the translator's GPU kernels
|
|
109
161
|
(`gpu_cuda/`), *GPU batch* the hand-written CUDA batch solver; the
|
|
110
|
-
package picks the fastest one present.
|
|
111
|
-
from scikit-learn's `BaseEstimator` yet, so `clone`, `GridSearchCV`
|
|
112
|
-
and `check_estimator` do not apply to them.
|
|
162
|
+
package picks the fastest one present.
|
|
113
163
|
|
|
114
164
|
| class | scikit-learn | Scheme kernel | builds | sklearnex accelerates |
|
|
115
165
|
|---|---|---|---|---|
|
|
166
|
+
| `GramLasso` | Lasso(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
167
|
+
| `GramElasticNet` | ElasticNet(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
168
|
+
| `GramRidge` | Ridge, fit(X, y) with the intercept, one or many targets | numpy (Cholesky) | CPU | Ridge |
|
|
116
169
|
| `CovLasso` | Lasso, ElasticNet, lasso_path(precompute=True) | `lasso-cov.scm` | CPU; GPU batch (fit_path_batch, bootstrap) | no |
|
|
117
170
|
| `CovLassoCV` | LassoCV, ElasticNetCV | `lasso-cov.scm` | CPU; GPU batch | no |
|
|
118
171
|
| `DerivedLasso` | lasso_path, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# scm2cpp-lasso
|
|
2
2
|
|
|
3
|
+
[](https://colab.research.google.com/github/niitsuma/scm2cpp/blob/master/notebooks/compare-sklearn.ipynb)
|
|
4
|
+
|
|
3
5
|
*[Japanese (README.ja.md)](README.ja.md)*
|
|
4
6
|
|
|
5
7
|
Lasso by coordinate descent over a Gram matrix, with an optional GPU
|
|
@@ -10,8 +12,9 @@ path. The solver is Scheme, translated to C++ by
|
|
|
10
12
|
$ pip install scm2cpp-lasso
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
On Linux x86_64
|
|
14
|
-
|
|
15
|
+
On Linux x86_64, macOS arm64 (macOS 14 or later) and Windows AMD64
|
|
16
|
+
this installs a wheel: compiled, nothing to build (with OpenBLAS
|
|
17
|
+
inside on Linux and macOS; Windows has the loop variants). Elsewhere pip builds the sdist,
|
|
15
18
|
which needs a C++17 compiler and nothing else. The wheels carry no
|
|
16
19
|
GPU code (a wheel cannot know the device); for the GPU builds, install
|
|
17
20
|
from the sdist on a machine with `nvcc` on the path:
|
|
@@ -81,6 +84,55 @@ at zero, and `lambda_grid()` walks down from it -- the construction
|
|
|
81
84
|
scikit-learn uses. If your columns differ wildly in scale, standardize
|
|
82
85
|
them first; this solver does not do it for you.
|
|
83
86
|
|
|
87
|
+
## scikit-learn compatibility
|
|
88
|
+
|
|
89
|
+
From 0.14.0 every estimator with a `fit(X, y)` (or `fit(X)`) derives
|
|
90
|
+
from scikit-learn's `BaseEstimator` and the matching mixin, so `clone`,
|
|
91
|
+
`get_params` / `set_params`, `GridSearchCV`, `Pipeline` and
|
|
92
|
+
`cross_val_score` take them, and all 39 pass
|
|
93
|
+
`sklearn.utils.estimator_checks.check_estimator` (`check-sklearn.py`
|
|
94
|
+
runs it; the one expected failure is `LBFGSLogisticRegressionCV`'s
|
|
95
|
+
`n_iter_` of 0 for a C whose warm start is already converged, which
|
|
96
|
+
scikit-learn's own `LogisticRegressionCV` reports on the same data).
|
|
97
|
+
scikit-learn stays optional: without it a numpy-only stand-in gives
|
|
98
|
+
`get_params`, `set_params`, `score` and the same input checks.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from sklearn.model_selection import GridSearchCV
|
|
102
|
+
from scm2cpp_lasso import GramLasso
|
|
103
|
+
|
|
104
|
+
GridSearchCV(GramLasso(), {"alpha": [0.01, 0.1, 1.0]}, cv=5).fit(X, y)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`GramLasso`, `GramElasticNet` and `GramRidge` are the `fit(X, y)`
|
|
108
|
+
forms, with the intercept, over the Gram-matrix solvers; `CovLasso`,
|
|
109
|
+
`CovRidge`, `DerivedLasso`, `CovLogistic`, `CovGroupLasso` and
|
|
110
|
+
`CovMultiTaskLasso` keep their data-in-the-constructor interface,
|
|
111
|
+
which solves a whole path at once.
|
|
112
|
+
|
|
113
|
+
What it costs is the input checks: X must be a finite 2-D float64
|
|
114
|
+
array with the feature count of the fit. A plain C-ordered float64
|
|
115
|
+
ndarray is checked directly (one sum for finiteness); anything else (a
|
|
116
|
+
list, a DataFrame, another dtype) goes through scikit-learn's
|
|
117
|
+
`validate_data`, which raises the errors scikit-learn raises. The
|
|
118
|
+
checks alone, per call (`bench/sklearn-compat-overhead.py --checks`):
|
|
119
|
+
|
|
120
|
+
| X | fit | predict | predict, 50 rows | validate_data |
|
|
121
|
+
|---|---|---|---|---|
|
|
122
|
+
| 200 x 10 | 13 us | 7 us | 9 us | 173 us |
|
|
123
|
+
| 2000 x 50 | 47 us | 36 us | 9 us | 224 us |
|
|
124
|
+
| 20000 x 200 | 2.7 ms | 3.2 ms | 13 us | 3.2 ms |
|
|
125
|
+
|
|
126
|
+
The finiteness sum is the size-dependent part; under
|
|
127
|
+
`sklearn.set_config(assume_finite=True)` every row is about 3 us.
|
|
128
|
+
Whole calls, before and after (`bench/sklearn-compat-overhead.py`, 30
|
|
129
|
+
estimators, three shapes, the two packages alternating on one core of
|
|
130
|
+
a loaded machine): fits of a millisecond or more are unchanged within
|
|
131
|
+
the run-to-run spread (about 10%); fits of about 0.1 ms take 10 to
|
|
132
|
+
30% (10 to 40 us) longer; predict on 20000 x 200 takes about twice as
|
|
133
|
+
long (3 ms to 6 ms, the finiteness sum costing as much as the product
|
|
134
|
+
itself), and on small inputs 5 to 10 us longer.
|
|
135
|
+
|
|
84
136
|
## Estimators at a glance
|
|
85
137
|
|
|
86
138
|
Every estimator, the scikit-learn estimator it reproduces, the Scheme
|
|
@@ -89,12 +141,13 @@ it runs on, and whether Intel's sklearnex accelerates the scikit-learn
|
|
|
89
141
|
side. Builds: *loops* is the plain translation, *BLAS* / *cuBLAS* the
|
|
90
142
|
products handed to (cu)BLAS, *--cuda* the translator's GPU kernels
|
|
91
143
|
(`gpu_cuda/`), *GPU batch* the hand-written CUDA batch solver; the
|
|
92
|
-
package picks the fastest one present.
|
|
93
|
-
from scikit-learn's `BaseEstimator` yet, so `clone`, `GridSearchCV`
|
|
94
|
-
and `check_estimator` do not apply to them.
|
|
144
|
+
package picks the fastest one present.
|
|
95
145
|
|
|
96
146
|
| class | scikit-learn | Scheme kernel | builds | sklearnex accelerates |
|
|
97
147
|
|---|---|---|---|---|
|
|
148
|
+
| `GramLasso` | Lasso(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
149
|
+
| `GramElasticNet` | ElasticNet(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
150
|
+
| `GramRidge` | Ridge, fit(X, y) with the intercept, one or many targets | numpy (Cholesky) | CPU | Ridge |
|
|
98
151
|
| `CovLasso` | Lasso, ElasticNet, lasso_path(precompute=True) | `lasso-cov.scm` | CPU; GPU batch (fit_path_batch, bootstrap) | no |
|
|
99
152
|
| `CovLassoCV` | LassoCV, ElasticNetCV | `lasso-cov.scm` | CPU; GPU batch | no |
|
|
100
153
|
| `DerivedLasso` | lasso_path, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scm2cpp-lasso"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.14.0"
|
|
8
8
|
description = "scikit-learn estimators (lasso, elastic net, ridge, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver and CUDA kernels included"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -12,6 +12,7 @@ device, or a failed nvcc all leave a working CPU package behind, and
|
|
|
12
12
|
the batch path notices at import and falls back.
|
|
13
13
|
"""
|
|
14
14
|
import os
|
|
15
|
+
import re
|
|
15
16
|
import shutil
|
|
16
17
|
import subprocess
|
|
17
18
|
import sys
|
|
@@ -28,7 +29,9 @@ GEN_REL = PKG_REL + "/_generated"
|
|
|
28
29
|
PKG = HERE / "src" / "scm2cpp_lasso"
|
|
29
30
|
GEN = PKG / "_generated"
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
# MSVC: /EHsc for C++ exceptions, /bigobj for the large generated files
|
|
33
|
+
MSVC = ["/O2", "/std:c++17", "/EHsc", "/bigobj"]
|
|
34
|
+
CXXFLAGS = ["-O2", "-std=c++17"] if os.name != "nt" else MSVC
|
|
32
35
|
|
|
33
36
|
kernel = Extension(
|
|
34
37
|
"scm2cpp_lasso._lasso_cov",
|
|
@@ -92,12 +95,24 @@ else:
|
|
|
92
95
|
"scm2cpp_lasso._lasso_derived_loops",
|
|
93
96
|
sources=[GEN_REL + "/derived_loops/lasso_design_capi.cpp"],
|
|
94
97
|
include_dirs=[GEN_REL + "/derived_loops", GEN_REL],
|
|
95
|
-
extra_compile_args=(["-O3", "-std=c++17"] if os.name != "nt"
|
|
96
|
-
else ["/O2", "/std:c++17"]),
|
|
98
|
+
extra_compile_args=(["-O3", "-std=c++17"] if os.name != "nt" else MSVC),
|
|
97
99
|
)
|
|
98
100
|
|
|
99
101
|
|
|
100
102
|
class BuildWithCuda(build_ext):
|
|
103
|
+
def get_export_symbols(self, ext):
|
|
104
|
+
# The extensions are plain shared libraries the package loads
|
|
105
|
+
# through ctypes, not Python modules: no PyInit_ entry point,
|
|
106
|
+
# and on Windows a DLL shows ctypes only what it exports, so the
|
|
107
|
+
# exports are the extern "C" wrappers of the -M C API. (Unix
|
|
108
|
+
# linkers export everything and ignore this list.)
|
|
109
|
+
names = []
|
|
110
|
+
for src in ext.sources:
|
|
111
|
+
if src.endswith("_capi.cpp"):
|
|
112
|
+
text = (HERE / src).read_text()
|
|
113
|
+
names += re.findall(r'extern "C"[^(\n]*?\b(scm2cpp_\w+)\(', text)
|
|
114
|
+
return names
|
|
115
|
+
|
|
101
116
|
def build_extensions(self):
|
|
102
117
|
# the kernel is C++ compiled through the usual machinery, so
|
|
103
118
|
# wheels and cross-compilation behave as they always do
|
|
@@ -165,7 +180,7 @@ def cuda_home():
|
|
|
165
180
|
# flags carry: with signed overflow defined the compiler cannot treat
|
|
166
181
|
# the flat index i*p + j as an induction variable, and the linear SVM's
|
|
167
182
|
# sweep runs 25% slower.
|
|
168
|
-
_cls_flags = ["-O3", "-std=c++17", "-fstrict-overflow"] if os.name != "nt" else
|
|
183
|
+
_cls_flags = ["-O3", "-std=c++17", "-fstrict-overflow"] if os.name != "nt" else MSVC
|
|
169
184
|
classifiers = Extension(
|
|
170
185
|
"scm2cpp_lasso._classifiers",
|
|
171
186
|
sources=[GEN_REL + "/classifiers_capi.cpp"],
|