scm2cpp-lasso 0.14.0__tar.gz → 0.15.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.14.0 → scm2cpp_lasso-0.15.0}/PKG-INFO +41 -8
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/README.md +40 -7
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/pyproject.toml +1 -1
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/__init__.py +216 -9
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_compat.py +2 -1
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso.egg-info/PKG-INFO +41 -8
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/setup.cfg +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/setup.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/__init__.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_accel_cublas.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_classifiers.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_derived_blas.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_derived_cublas.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_derived_loops.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_gpu_cuda.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_gramops_blas.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_gramops_loops.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_nmf_blas.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_nmf_cublas.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_nmf_loops.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/classifiers.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/classifiers.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/classifiers_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/lasso_cov.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/lasso_cov.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/lasso_cov_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd_capi.cpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/scm2cpp-blas.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/scm2cpp-cublas.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/scm2cpp-cuda.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/scm2cpp.hpp +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_libfind.py +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/batch_capi.cu +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso.egg-info/SOURCES.txt +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso.egg-info/dependency_links.txt +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso.egg-info/requires.txt +0 -0
- {scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.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.15.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
|
|
@@ -107,9 +107,11 @@ them first; this solver does not do it for you.
|
|
|
107
107
|
From 0.14.0 every estimator with a `fit(X, y)` (or `fit(X)`) derives
|
|
108
108
|
from scikit-learn's `BaseEstimator` and the matching mixin, so `clone`,
|
|
109
109
|
`get_params` / `set_params`, `GridSearchCV`, `Pipeline` and
|
|
110
|
-
`cross_val_score` take them, and all
|
|
110
|
+
`cross_val_score` take them, and all 44 pass
|
|
111
111
|
`sklearn.utils.estimator_checks.check_estimator` (`check-sklearn.py`
|
|
112
|
-
runs it; the
|
|
112
|
+
runs it; the expected failures are `DesignLasso`'s missing `n_iter_`,
|
|
113
|
+
since the derived kernel does not count its sweeps, and
|
|
114
|
+
`LBFGSLogisticRegressionCV`'s
|
|
113
115
|
`n_iter_` of 0 for a C whose warm start is already converged, which
|
|
114
116
|
scikit-learn's own `LogisticRegressionCV` reports on the same data).
|
|
115
117
|
scikit-learn stays optional: without it a numpy-only stand-in gives
|
|
@@ -122,11 +124,37 @@ from scm2cpp_lasso import GramLasso
|
|
|
122
124
|
GridSearchCV(GramLasso(), {"alpha": [0.01, 0.1, 1.0]}, cv=5).fit(X, y)
|
|
123
125
|
```
|
|
124
126
|
|
|
125
|
-
`
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
`
|
|
129
|
-
|
|
127
|
+
`CovLasso`, `CovRidge`, `DerivedLasso`, `CovLogistic`,
|
|
128
|
+
`CovGroupLasso` and `CovMultiTaskLasso` keep their
|
|
129
|
+
data-in-the-constructor interface, which solves a whole path at once;
|
|
130
|
+
each has a `fit(X, y)` form with the intercept beside it (0.15.0):
|
|
131
|
+
|
|
132
|
+
| data in the constructor | `fit(X, y)` | scikit-learn |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `CovLasso` | `GramLasso`, `GramElasticNet` | Lasso, ElasticNet |
|
|
135
|
+
| `CovRidge` | `GramRidge` | Ridge |
|
|
136
|
+
| `DerivedLasso` | `DesignLasso` | Lasso |
|
|
137
|
+
| `CovLogistic` | `GramLogisticRegression` | LogisticRegression(l1_ratio=1, solver="liblinear") |
|
|
138
|
+
| `CovGroupLasso` | `GramGroupLasso` (`groups=None`: the lasso) | (none) |
|
|
139
|
+
| `CovMultiTaskLasso` | `GramMultiTaskLasso`, `GramMultiTaskElasticNet` | MultiTaskLasso, MultiTaskElasticNet |
|
|
140
|
+
|
|
141
|
+
Against scikit-learn on 400 x 30 with an intercept: `DesignLasso` and
|
|
142
|
+
`GramGroupLasso(groups=None)` agree with `Lasso` to 1.5e-10, the
|
|
143
|
+
multi-task pair with `MultiTaskLasso` / `MultiTaskElasticNet` to
|
|
144
|
+
5e-14, and `GramLogisticRegression` reaches liblinear's objective to
|
|
145
|
+
eight digits with the same predictions.
|
|
146
|
+
|
|
147
|
+
Against the class each one wraps (one alpha, one core), which fits no
|
|
148
|
+
intercept and is unchanged: with `fit_intercept=False` the input checks
|
|
149
|
+
add 15 to 30 us a call (up to +50% on a 0.06 ms fit) and the finiteness
|
|
150
|
+
sum 8 to 14% on 20000 x 200 (none under `assume_finite`); with the
|
|
151
|
+
intercept, the column means add 20 to 30% on 20000 x 200 for the
|
|
152
|
+
Gram-matrix ones, which correct X'X
|
|
153
|
+
for the means rather than copy X to centre it, and about 55% for
|
|
154
|
+
`DesignLasso`, whose kernel needs the centred X itself.
|
|
155
|
+
`GramLogisticRegression` is slower than liblinear by its algorithm, 2.5x
|
|
156
|
+
at 20000 x 200 and more on small problems; `L1LogisticRegression` is
|
|
157
|
+
the fast one for that problem.
|
|
130
158
|
|
|
131
159
|
What it costs is the input checks: X must be a finite 2-D float64
|
|
132
160
|
array with the feature count of the fit. A plain C-ordered float64
|
|
@@ -166,6 +194,11 @@ package picks the fastest one present.
|
|
|
166
194
|
| `GramLasso` | Lasso(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
167
195
|
| `GramElasticNet` | ElasticNet(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
168
196
|
| `GramRidge` | Ridge, fit(X, y) with the intercept, one or many targets | numpy (Cholesky) | CPU | Ridge |
|
|
197
|
+
| `GramMultiTaskLasso` | MultiTaskLasso, fit(X, Y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
198
|
+
| `GramMultiTaskElasticNet` | MultiTaskElasticNet, fit(X, Y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
199
|
+
| `GramGroupLasso` | (none; skglm GroupLasso), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | - |
|
|
200
|
+
| `GramLogisticRegression` | LogisticRegression(l1_ratio=1, solver='liblinear'), by majorization | `lasso-cov.scm` | CPU | no |
|
|
201
|
+
| `DesignLasso` | Lasso, fit(X, y) with the intercept, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
169
202
|
| `CovLasso` | Lasso, ElasticNet, lasso_path(precompute=True) | `lasso-cov.scm` | CPU; GPU batch (fit_path_batch, bootstrap) | no |
|
|
170
203
|
| `CovLassoCV` | LassoCV, ElasticNetCV | `lasso-cov.scm` | CPU; GPU batch | no |
|
|
171
204
|
| `DerivedLasso` | lasso_path, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
@@ -89,9 +89,11 @@ them first; this solver does not do it for you.
|
|
|
89
89
|
From 0.14.0 every estimator with a `fit(X, y)` (or `fit(X)`) derives
|
|
90
90
|
from scikit-learn's `BaseEstimator` and the matching mixin, so `clone`,
|
|
91
91
|
`get_params` / `set_params`, `GridSearchCV`, `Pipeline` and
|
|
92
|
-
`cross_val_score` take them, and all
|
|
92
|
+
`cross_val_score` take them, and all 44 pass
|
|
93
93
|
`sklearn.utils.estimator_checks.check_estimator` (`check-sklearn.py`
|
|
94
|
-
runs it; the
|
|
94
|
+
runs it; the expected failures are `DesignLasso`'s missing `n_iter_`,
|
|
95
|
+
since the derived kernel does not count its sweeps, and
|
|
96
|
+
`LBFGSLogisticRegressionCV`'s
|
|
95
97
|
`n_iter_` of 0 for a C whose warm start is already converged, which
|
|
96
98
|
scikit-learn's own `LogisticRegressionCV` reports on the same data).
|
|
97
99
|
scikit-learn stays optional: without it a numpy-only stand-in gives
|
|
@@ -104,11 +106,37 @@ from scm2cpp_lasso import GramLasso
|
|
|
104
106
|
GridSearchCV(GramLasso(), {"alpha": [0.01, 0.1, 1.0]}, cv=5).fit(X, y)
|
|
105
107
|
```
|
|
106
108
|
|
|
107
|
-
`
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
`
|
|
111
|
-
|
|
109
|
+
`CovLasso`, `CovRidge`, `DerivedLasso`, `CovLogistic`,
|
|
110
|
+
`CovGroupLasso` and `CovMultiTaskLasso` keep their
|
|
111
|
+
data-in-the-constructor interface, which solves a whole path at once;
|
|
112
|
+
each has a `fit(X, y)` form with the intercept beside it (0.15.0):
|
|
113
|
+
|
|
114
|
+
| data in the constructor | `fit(X, y)` | scikit-learn |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `CovLasso` | `GramLasso`, `GramElasticNet` | Lasso, ElasticNet |
|
|
117
|
+
| `CovRidge` | `GramRidge` | Ridge |
|
|
118
|
+
| `DerivedLasso` | `DesignLasso` | Lasso |
|
|
119
|
+
| `CovLogistic` | `GramLogisticRegression` | LogisticRegression(l1_ratio=1, solver="liblinear") |
|
|
120
|
+
| `CovGroupLasso` | `GramGroupLasso` (`groups=None`: the lasso) | (none) |
|
|
121
|
+
| `CovMultiTaskLasso` | `GramMultiTaskLasso`, `GramMultiTaskElasticNet` | MultiTaskLasso, MultiTaskElasticNet |
|
|
122
|
+
|
|
123
|
+
Against scikit-learn on 400 x 30 with an intercept: `DesignLasso` and
|
|
124
|
+
`GramGroupLasso(groups=None)` agree with `Lasso` to 1.5e-10, the
|
|
125
|
+
multi-task pair with `MultiTaskLasso` / `MultiTaskElasticNet` to
|
|
126
|
+
5e-14, and `GramLogisticRegression` reaches liblinear's objective to
|
|
127
|
+
eight digits with the same predictions.
|
|
128
|
+
|
|
129
|
+
Against the class each one wraps (one alpha, one core), which fits no
|
|
130
|
+
intercept and is unchanged: with `fit_intercept=False` the input checks
|
|
131
|
+
add 15 to 30 us a call (up to +50% on a 0.06 ms fit) and the finiteness
|
|
132
|
+
sum 8 to 14% on 20000 x 200 (none under `assume_finite`); with the
|
|
133
|
+
intercept, the column means add 20 to 30% on 20000 x 200 for the
|
|
134
|
+
Gram-matrix ones, which correct X'X
|
|
135
|
+
for the means rather than copy X to centre it, and about 55% for
|
|
136
|
+
`DesignLasso`, whose kernel needs the centred X itself.
|
|
137
|
+
`GramLogisticRegression` is slower than liblinear by its algorithm, 2.5x
|
|
138
|
+
at 20000 x 200 and more on small problems; `L1LogisticRegression` is
|
|
139
|
+
the fast one for that problem.
|
|
112
140
|
|
|
113
141
|
What it costs is the input checks: X must be a finite 2-D float64
|
|
114
142
|
array with the feature count of the fit. A plain C-ordered float64
|
|
@@ -148,6 +176,11 @@ package picks the fastest one present.
|
|
|
148
176
|
| `GramLasso` | Lasso(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
149
177
|
| `GramElasticNet` | ElasticNet(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
150
178
|
| `GramRidge` | Ridge, fit(X, y) with the intercept, one or many targets | numpy (Cholesky) | CPU | Ridge |
|
|
179
|
+
| `GramMultiTaskLasso` | MultiTaskLasso, fit(X, Y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
180
|
+
| `GramMultiTaskElasticNet` | MultiTaskElasticNet, fit(X, Y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
181
|
+
| `GramGroupLasso` | (none; skglm GroupLasso), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | - |
|
|
182
|
+
| `GramLogisticRegression` | LogisticRegression(l1_ratio=1, solver='liblinear'), by majorization | `lasso-cov.scm` | CPU | no |
|
|
183
|
+
| `DesignLasso` | Lasso, fit(X, y) with the intercept, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
151
184
|
| `CovLasso` | Lasso, ElasticNet, lasso_path(precompute=True) | `lasso-cov.scm` | CPU; GPU batch (fit_path_batch, bootstrap) | no |
|
|
152
185
|
| `CovLassoCV` | LassoCV, ElasticNetCV | `lasso-cov.scm` | CPU; GPU batch | no |
|
|
153
186
|
| `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.15.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"
|
|
@@ -53,8 +53,10 @@ __all__ = ["GramLasso", "GramElasticNet", "GramRidge", "CovLasso", "CovRidge", "
|
|
|
53
53
|
"L1LinearSVM", "WeiszfeldTheilSen", "f_regression", "f_classif", "SelectKBest",
|
|
54
54
|
"SelectPercentile", "GramRFE",
|
|
55
55
|
"CovMultiTaskLasso", "CovMultiTaskLassoCV", "DerivedLasso",
|
|
56
|
+
"GramLogisticRegression", "GramGroupLasso", "GramMultiTaskLasso",
|
|
57
|
+
"GramMultiTaskElasticNet", "DesignLasso",
|
|
56
58
|
"cuda_available", "derived_backend", "kernel"]
|
|
57
|
-
__version__ = "0.
|
|
59
|
+
__version__ = "0.15.0"
|
|
58
60
|
|
|
59
61
|
_BATCH = load_batch_lib()
|
|
60
62
|
_DP = ctypes.POINTER(ctypes.c_double)
|
|
@@ -374,6 +376,35 @@ class DerivedLasso:
|
|
|
374
376
|
return betas.reshape(lams.size, self.p)
|
|
375
377
|
|
|
376
378
|
|
|
379
|
+
class DesignLasso(Tagged, RegressorMixin, BaseEstimator):
|
|
380
|
+
"""scikit-learn's ``Lasso`` interface over DerivedLasso: fit(X, y)
|
|
381
|
+
centres the data when ``fit_intercept`` and runs the derived kernel
|
|
382
|
+
at one penalty ``alpha``, same objective as GramLasso. ``tol`` is
|
|
383
|
+
the kernel's (the largest absolute move of one coefficient in a
|
|
384
|
+
sweep), ``max_iter`` its sweep cap and ``backend`` DerivedLasso's.
|
|
385
|
+
The kernel does not report how many sweeps it ran, so there is no
|
|
386
|
+
n_iter_.
|
|
387
|
+
|
|
388
|
+
Attributes after fit: coef_, intercept_, n_features_in_.
|
|
389
|
+
"""
|
|
390
|
+
|
|
391
|
+
def __init__(self, alpha=1.0, *, fit_intercept=True, tol=1e-8, max_iter=100000,
|
|
392
|
+
backend=None):
|
|
393
|
+
self.alpha, self.fit_intercept, self.tol, self.max_iter = alpha, fit_intercept, tol, max_iter
|
|
394
|
+
self.backend = backend
|
|
395
|
+
|
|
396
|
+
def fit(self, X, y):
|
|
397
|
+
X, y = fit_xy(self, X, y)
|
|
398
|
+
Xc, yc, xm, ym = _centered(X, y, self.fit_intercept)
|
|
399
|
+
m = DerivedLasso(Xc, yc, backend=self.backend)
|
|
400
|
+
self.coef_ = m.fit(float(self.alpha), tol=float(self.tol), max_sweeps=int(self.max_iter))
|
|
401
|
+
self.intercept_ = float(ym - xm @ self.coef_)
|
|
402
|
+
return self
|
|
403
|
+
|
|
404
|
+
def predict(self, X):
|
|
405
|
+
return pred_x(self, X) @ self.coef_ + self.intercept_
|
|
406
|
+
|
|
407
|
+
|
|
377
408
|
def derived_backend():
|
|
378
409
|
"""The derived kernel variant DerivedLasso takes by default: 'cublas'
|
|
379
410
|
when built and a device answers, else 'blas', else 'loops'; None
|
|
@@ -669,6 +700,28 @@ def _centered(X, y, fit_intercept):
|
|
|
669
700
|
return np.ascontiguousarray(X - xm), y - ym, xm, ym
|
|
670
701
|
|
|
671
702
|
|
|
703
|
+
def _centered_gram(X, y, fit_intercept):
|
|
704
|
+
"""(Xc'Xc, Xc'yc, xm, ym) for the centred data Xc, yc, without
|
|
705
|
+
forming Xc: X'X - n xm xm' and X'y - n xm ym, which saves the copy
|
|
706
|
+
of X (as long as the Gram product itself on 20000 x 200 rows, where
|
|
707
|
+
it took the intercept from free to twice the fit). The correction
|
|
708
|
+
cancels digits when a column's mean is large against its spread,
|
|
709
|
+
about (mean / sd)^2 ulps, so a column with mean over 100 sd (or no
|
|
710
|
+
spread at all) sends the whole fit through the centred copy."""
|
|
711
|
+
n = X.shape[0]
|
|
712
|
+
G, c = X.T @ X, X.T @ y
|
|
713
|
+
if not fit_intercept:
|
|
714
|
+
return G, c, np.zeros(X.shape[1]), np.zeros(y.shape[1:]) if y.ndim > 1 else 0.0
|
|
715
|
+
xm, ym = X.mean(axis=0), y.mean(axis=0)
|
|
716
|
+
nm2 = n * xm * xm
|
|
717
|
+
if np.all(np.diagonal(G) - nm2 > 1e-4 * nm2):
|
|
718
|
+
G -= np.outer(xm, n * xm)
|
|
719
|
+
c -= np.multiply.outer(n * xm, ym)
|
|
720
|
+
return G, c, xm, ym
|
|
721
|
+
Xc, yc = np.ascontiguousarray(X - xm), y - ym
|
|
722
|
+
return Xc.T @ Xc, Xc.T @ yc, xm, ym
|
|
723
|
+
|
|
724
|
+
|
|
672
725
|
class GramElasticNet(Tagged, RegressorMixin, BaseEstimator):
|
|
673
726
|
"""scikit-learn's ``ElasticNet(precompute=True)`` interface over
|
|
674
727
|
CovLasso: fit(X, y) centres the data when ``fit_intercept``, forms
|
|
@@ -692,10 +745,10 @@ class GramElasticNet(Tagged, RegressorMixin, BaseEstimator):
|
|
|
692
745
|
|
|
693
746
|
def fit(self, X, y):
|
|
694
747
|
X, y = fit_xy(self, X, y)
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
g = np.ascontiguousarray(
|
|
698
|
-
c = np.ascontiguousarray(
|
|
748
|
+
n, p = X.shape
|
|
749
|
+
G, c, xm, ym = _centered_gram(X, y, self.fit_intercept)
|
|
750
|
+
g = np.ascontiguousarray(G.ravel())
|
|
751
|
+
c = np.ascontiguousarray(c)
|
|
699
752
|
lam, r = float(self.alpha), float(self.l1_ratio)
|
|
700
753
|
tol, cap = float(self.tol), int(self.max_iter)
|
|
701
754
|
beta, prev = np.zeros(p), np.empty(p)
|
|
@@ -747,11 +800,9 @@ class GramRidge(Tagged, RegressorMixin, BaseEstimator):
|
|
|
747
800
|
|
|
748
801
|
def fit(self, X, y):
|
|
749
802
|
X, y = fit_xy(self, X, y, multi_output=True)
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
A = Xc.T @ Xc
|
|
803
|
+
p = X.shape[1]
|
|
804
|
+
A, b, xm, ym = _centered_gram(X, y, self.fit_intercept)
|
|
753
805
|
A.flat[::p + 1] += float(self.alpha)
|
|
754
|
-
b = Xc.T @ yc
|
|
755
806
|
try:
|
|
756
807
|
coef = np.linalg.solve(A, b)
|
|
757
808
|
except np.linalg.LinAlgError:
|
|
@@ -2686,7 +2737,9 @@ class CovLogistic:
|
|
|
2686
2737
|
|
|
2687
2738
|
def _fit_one(self, beta, lam, tol, inner_sweeps, max_rounds):
|
|
2688
2739
|
beta = beta.copy()
|
|
2740
|
+
self._rounds = 0
|
|
2689
2741
|
for _ in range(max_rounds):
|
|
2742
|
+
self._rounds += 1
|
|
2690
2743
|
prev = beta.copy()
|
|
2691
2744
|
# the majorizer at beta: quadratic G/4, working
|
|
2692
2745
|
# correlations exactly X'(y - mu)
|
|
@@ -2699,6 +2752,58 @@ class CovLogistic:
|
|
|
2699
2752
|
return beta
|
|
2700
2753
|
|
|
2701
2754
|
|
|
2755
|
+
class GramLogisticRegression(Tagged, ClassifierMixin, BaseEstimator):
|
|
2756
|
+
"""scikit-learn's ``LogisticRegression(l1_ratio=1, solver="liblinear")``
|
|
2757
|
+
interface over CovLogistic: the same problem,
|
|
2758
|
+
|
|
2759
|
+
min_w ||w||_1 + C sum_i log(1 + exp(-y_i (w.x_i + b))),
|
|
2760
|
+
|
|
2761
|
+
solved by majorization over the Gram matrix instead of liblinear's
|
|
2762
|
+
Newton steps. As in liblinear the intercept is the weight of a
|
|
2763
|
+
constant column of value ``intercept_scaling`` and is penalized
|
|
2764
|
+
with the rest. ``tol`` is CovLogistic's (the largest coefficient
|
|
2765
|
+
move in a round, relative to their size) and ``max_iter`` caps the
|
|
2766
|
+
rounds. Two classes.
|
|
2767
|
+
|
|
2768
|
+
Attributes after fit: classes_, coef_, intercept_, n_iter_.
|
|
2769
|
+
"""
|
|
2770
|
+
|
|
2771
|
+
_binary_only = True
|
|
2772
|
+
|
|
2773
|
+
def __init__(self, C=1.0, *, fit_intercept=True, intercept_scaling=1.0, tol=1e-7,
|
|
2774
|
+
max_iter=500):
|
|
2775
|
+
self.C, self.fit_intercept, self.intercept_scaling = C, fit_intercept, intercept_scaling
|
|
2776
|
+
self.tol, self.max_iter = tol, max_iter
|
|
2777
|
+
|
|
2778
|
+
def fit(self, X, y):
|
|
2779
|
+
X, y = fit_xy(self, X, y, classifier=True)
|
|
2780
|
+
n = X.shape[0]
|
|
2781
|
+
self.classes_, ys = _binary_labels(y)
|
|
2782
|
+
s = float(self.intercept_scaling)
|
|
2783
|
+
if self.fit_intercept:
|
|
2784
|
+
X = np.column_stack([X, np.full(n, s)])
|
|
2785
|
+
m = CovLogistic(X, (ys > 0).astype(np.float64))
|
|
2786
|
+
lam = 1.0 / (n * float(self.C))
|
|
2787
|
+
beta = m._fit_one(np.zeros(m.p), lam, float(self.tol), 200, int(self.max_iter))
|
|
2788
|
+
self.n_iter_ = m._rounds
|
|
2789
|
+
if self.fit_intercept:
|
|
2790
|
+
self.coef_, self.intercept_ = beta[:-1].copy(), float(beta[-1]) * s
|
|
2791
|
+
else:
|
|
2792
|
+
self.coef_, self.intercept_ = beta, 0.0
|
|
2793
|
+
return self
|
|
2794
|
+
|
|
2795
|
+
def decision_function(self, X):
|
|
2796
|
+
return pred_x(self, X) @ self.coef_ + self.intercept_
|
|
2797
|
+
|
|
2798
|
+
def predict_proba(self, X):
|
|
2799
|
+
p1 = 1.0 / (1.0 + np.exp(-self.decision_function(X)))
|
|
2800
|
+
return np.column_stack([1.0 - p1, p1])
|
|
2801
|
+
|
|
2802
|
+
def predict(self, X):
|
|
2803
|
+
z = self.decision_function(X)
|
|
2804
|
+
return self.classes_[(z > 0).astype(int)]
|
|
2805
|
+
|
|
2806
|
+
|
|
2702
2807
|
class CovGroupLasso:
|
|
2703
2808
|
"""Group lasso over a design given by its Gram matrix.
|
|
2704
2809
|
|
|
@@ -2778,9 +2883,13 @@ class CovGroupLasso:
|
|
|
2778
2883
|
|
|
2779
2884
|
def _fit_one(self, beta, c, lam, tol, max_sweeps):
|
|
2780
2885
|
thr = lam * self.nobs
|
|
2886
|
+
self._sweeps = 0
|
|
2781
2887
|
for _ in range(max_sweeps):
|
|
2888
|
+
self._sweeps += 1
|
|
2782
2889
|
moved = 0.0
|
|
2783
2890
|
for g, w, L in zip(self.groups, self.wg, self.Lg):
|
|
2891
|
+
if L <= 0.0: # all-zero columns: the group stays at zero
|
|
2892
|
+
continue
|
|
2784
2893
|
bg = beta[g]
|
|
2785
2894
|
z = bg + c[g] / L
|
|
2786
2895
|
nz = float(np.linalg.norm(z))
|
|
@@ -2809,6 +2918,41 @@ class CovGroupLasso:
|
|
|
2809
2918
|
return quad / self.nobs + lam * pen
|
|
2810
2919
|
|
|
2811
2920
|
|
|
2921
|
+
class GramGroupLasso(Tagged, RegressorMixin, BaseEstimator):
|
|
2922
|
+
"""A ``Lasso``-style interface over CovGroupLasso: fit(X, y) centres
|
|
2923
|
+
the data when ``fit_intercept`` and runs the block descent at
|
|
2924
|
+
``alpha``,
|
|
2925
|
+
|
|
2926
|
+
(1 / 2 n) ||y - X b - b0||^2 + alpha sum_g sqrt(|g|) ||b_g||_2.
|
|
2927
|
+
|
|
2928
|
+
``groups`` is a list of index arrays partitioning the columns, or
|
|
2929
|
+
None for one group per column (the lasso). ``tol`` is
|
|
2930
|
+
CovGroupLasso's and ``max_iter`` its sweep cap.
|
|
2931
|
+
|
|
2932
|
+
Attributes after fit: coef_, intercept_, n_iter_, n_features_in_.
|
|
2933
|
+
"""
|
|
2934
|
+
|
|
2935
|
+
def __init__(self, alpha=1.0, *, groups=None, fit_intercept=True, tol=1e-8,
|
|
2936
|
+
max_iter=10000):
|
|
2937
|
+
self.alpha, self.groups, self.fit_intercept = alpha, groups, fit_intercept
|
|
2938
|
+
self.tol, self.max_iter = tol, max_iter
|
|
2939
|
+
|
|
2940
|
+
def fit(self, X, y):
|
|
2941
|
+
X, y = fit_xy(self, X, y)
|
|
2942
|
+
n, p = X.shape
|
|
2943
|
+
G, c, xm, ym = _centered_gram(X, y, self.fit_intercept)
|
|
2944
|
+
groups = [[j] for j in range(p)] if self.groups is None else self.groups
|
|
2945
|
+
m = CovGroupLasso(gram=G, corr=c, nobs=n, groups=groups)
|
|
2946
|
+
beta, _ = m._fit_one(np.zeros(p), m.c0.copy(), float(self.alpha), float(self.tol),
|
|
2947
|
+
int(self.max_iter))
|
|
2948
|
+
self.coef_, self.n_iter_ = beta, m._sweeps
|
|
2949
|
+
self.intercept_ = float(ym - xm @ self.coef_)
|
|
2950
|
+
return self
|
|
2951
|
+
|
|
2952
|
+
def predict(self, X):
|
|
2953
|
+
return pred_x(self, X) @ self.coef_ + self.intercept_
|
|
2954
|
+
|
|
2955
|
+
|
|
2812
2956
|
class CovMultiTaskLasso:
|
|
2813
2957
|
"""Multi-task lasso and elastic net over a design's Gram matrix.
|
|
2814
2958
|
|
|
@@ -2929,6 +3073,69 @@ class CovMultiTaskLasso:
|
|
|
2929
3073
|
return out.reshape(lambdas.size, self.p, self.n_tasks)
|
|
2930
3074
|
|
|
2931
3075
|
|
|
3076
|
+
class GramMultiTaskElasticNet(Tagged, RegressorMixin, BaseEstimator):
|
|
3077
|
+
"""scikit-learn's ``MultiTaskElasticNet`` interface over
|
|
3078
|
+
CovMultiTaskLasso: fit(X, Y) centres the data when
|
|
3079
|
+
``fit_intercept``, forms the Gram matrix once and runs the row-block
|
|
3080
|
+
sweep at ``alpha``. Y is (n, n_tasks); coef_ is (n_tasks, p) as
|
|
3081
|
+
scikit-learn has it. ``tol`` is CovMultiTaskLasso's and
|
|
3082
|
+
``max_iter`` its sweep cap.
|
|
3083
|
+
|
|
3084
|
+
Attributes after fit: coef_, intercept_, n_iter_, n_features_in_.
|
|
3085
|
+
"""
|
|
3086
|
+
|
|
3087
|
+
_multi_output = "only"
|
|
3088
|
+
|
|
3089
|
+
def __init__(self, alpha=1.0, *, l1_ratio=0.5, fit_intercept=True, tol=1e-8,
|
|
3090
|
+
max_iter=100000):
|
|
3091
|
+
self.alpha, self.l1_ratio, self.fit_intercept = alpha, l1_ratio, fit_intercept
|
|
3092
|
+
self.tol, self.max_iter = tol, max_iter
|
|
3093
|
+
|
|
3094
|
+
def fit(self, X, y):
|
|
3095
|
+
X, y = fit_xy(self, X, y, multi_output=True)
|
|
3096
|
+
if y.ndim != 2:
|
|
3097
|
+
raise ValueError("For mono-task outputs, use GramElasticNet or GramLasso; "
|
|
3098
|
+
"y must be (n_samples, n_tasks)")
|
|
3099
|
+
n, p = X.shape
|
|
3100
|
+
t = y.shape[1]
|
|
3101
|
+
G, c, xm, ym = _centered_gram(X, y, self.fit_intercept)
|
|
3102
|
+
g = np.ascontiguousarray(G.ravel())
|
|
3103
|
+
c = np.ascontiguousarray(c.ravel())
|
|
3104
|
+
lam, r = float(self.alpha), float(self.l1_ratio)
|
|
3105
|
+
tol, cap = float(self.tol), int(self.max_iter)
|
|
3106
|
+
W, prev = np.zeros(p * t), np.empty(p * t)
|
|
3107
|
+
swept = 0
|
|
3108
|
+
while swept < cap:
|
|
3109
|
+
chunk = min(20, cap - swept)
|
|
3110
|
+
prev[:] = W
|
|
3111
|
+
kernel.mt_descend(g, c, W, lam * r, lam * (1.0 - r), chunk, float(n), p, t)
|
|
3112
|
+
swept += chunk
|
|
3113
|
+
if np.max(np.abs(W - prev)) < tol * _scale(W):
|
|
3114
|
+
break
|
|
3115
|
+
W = W.reshape(p, t)
|
|
3116
|
+
self.coef_, self.n_iter_ = np.ascontiguousarray(W.T), swept
|
|
3117
|
+
self.intercept_ = ym - xm @ W
|
|
3118
|
+
return self
|
|
3119
|
+
|
|
3120
|
+
def predict(self, X):
|
|
3121
|
+
return pred_x(self, X) @ self.coef_.T + self.intercept_
|
|
3122
|
+
|
|
3123
|
+
|
|
3124
|
+
class GramMultiTaskLasso(GramMultiTaskElasticNet):
|
|
3125
|
+
"""scikit-learn's ``MultiTaskLasso`` interface over CovMultiTaskLasso:
|
|
3126
|
+
GramMultiTaskElasticNet with l1_ratio 1.
|
|
3127
|
+
|
|
3128
|
+
Attributes after fit: coef_, intercept_, n_iter_, n_features_in_.
|
|
3129
|
+
"""
|
|
3130
|
+
|
|
3131
|
+
def __init__(self, alpha=1.0, *, fit_intercept=True, tol=1e-8, max_iter=100000):
|
|
3132
|
+
self.alpha, self.fit_intercept, self.tol, self.max_iter = alpha, fit_intercept, tol, max_iter
|
|
3133
|
+
|
|
3134
|
+
@property
|
|
3135
|
+
def l1_ratio(self):
|
|
3136
|
+
return 1.0
|
|
3137
|
+
|
|
3138
|
+
|
|
2932
3139
|
class CovMultiTaskLassoCV(Tagged, RegressorMixin, BaseEstimator):
|
|
2933
3140
|
"""scikit-learn's ``MultiTaskLassoCV`` (``MultiTaskElasticNetCV``
|
|
2934
3141
|
with ``l1_ratio``) over the covariance machinery.
|
|
@@ -191,7 +191,8 @@ def _reset_names(est):
|
|
|
191
191
|
|
|
192
192
|
def fit_xy(est, X, y, *, y_numeric=True, multi_output=False, classifier=False):
|
|
193
193
|
"""X as a float64 C-ordered 2-D array and y, validated, n_features_in_ set."""
|
|
194
|
-
if (_plain(X) and type(y) is np.ndarray and y.
|
|
194
|
+
if (_plain(X) and type(y) is np.ndarray and y.shape[0:1] == X.shape[0:1]
|
|
195
|
+
and (y.ndim == 1 or (multi_output and y.ndim == 2 and y.shape[1] > 1))
|
|
195
196
|
and _finite(X)):
|
|
196
197
|
if classifier:
|
|
197
198
|
ok = _labels_ok(y)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scm2cpp-lasso
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.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
|
|
@@ -107,9 +107,11 @@ them first; this solver does not do it for you.
|
|
|
107
107
|
From 0.14.0 every estimator with a `fit(X, y)` (or `fit(X)`) derives
|
|
108
108
|
from scikit-learn's `BaseEstimator` and the matching mixin, so `clone`,
|
|
109
109
|
`get_params` / `set_params`, `GridSearchCV`, `Pipeline` and
|
|
110
|
-
`cross_val_score` take them, and all
|
|
110
|
+
`cross_val_score` take them, and all 44 pass
|
|
111
111
|
`sklearn.utils.estimator_checks.check_estimator` (`check-sklearn.py`
|
|
112
|
-
runs it; the
|
|
112
|
+
runs it; the expected failures are `DesignLasso`'s missing `n_iter_`,
|
|
113
|
+
since the derived kernel does not count its sweeps, and
|
|
114
|
+
`LBFGSLogisticRegressionCV`'s
|
|
113
115
|
`n_iter_` of 0 for a C whose warm start is already converged, which
|
|
114
116
|
scikit-learn's own `LogisticRegressionCV` reports on the same data).
|
|
115
117
|
scikit-learn stays optional: without it a numpy-only stand-in gives
|
|
@@ -122,11 +124,37 @@ from scm2cpp_lasso import GramLasso
|
|
|
122
124
|
GridSearchCV(GramLasso(), {"alpha": [0.01, 0.1, 1.0]}, cv=5).fit(X, y)
|
|
123
125
|
```
|
|
124
126
|
|
|
125
|
-
`
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
`
|
|
129
|
-
|
|
127
|
+
`CovLasso`, `CovRidge`, `DerivedLasso`, `CovLogistic`,
|
|
128
|
+
`CovGroupLasso` and `CovMultiTaskLasso` keep their
|
|
129
|
+
data-in-the-constructor interface, which solves a whole path at once;
|
|
130
|
+
each has a `fit(X, y)` form with the intercept beside it (0.15.0):
|
|
131
|
+
|
|
132
|
+
| data in the constructor | `fit(X, y)` | scikit-learn |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `CovLasso` | `GramLasso`, `GramElasticNet` | Lasso, ElasticNet |
|
|
135
|
+
| `CovRidge` | `GramRidge` | Ridge |
|
|
136
|
+
| `DerivedLasso` | `DesignLasso` | Lasso |
|
|
137
|
+
| `CovLogistic` | `GramLogisticRegression` | LogisticRegression(l1_ratio=1, solver="liblinear") |
|
|
138
|
+
| `CovGroupLasso` | `GramGroupLasso` (`groups=None`: the lasso) | (none) |
|
|
139
|
+
| `CovMultiTaskLasso` | `GramMultiTaskLasso`, `GramMultiTaskElasticNet` | MultiTaskLasso, MultiTaskElasticNet |
|
|
140
|
+
|
|
141
|
+
Against scikit-learn on 400 x 30 with an intercept: `DesignLasso` and
|
|
142
|
+
`GramGroupLasso(groups=None)` agree with `Lasso` to 1.5e-10, the
|
|
143
|
+
multi-task pair with `MultiTaskLasso` / `MultiTaskElasticNet` to
|
|
144
|
+
5e-14, and `GramLogisticRegression` reaches liblinear's objective to
|
|
145
|
+
eight digits with the same predictions.
|
|
146
|
+
|
|
147
|
+
Against the class each one wraps (one alpha, one core), which fits no
|
|
148
|
+
intercept and is unchanged: with `fit_intercept=False` the input checks
|
|
149
|
+
add 15 to 30 us a call (up to +50% on a 0.06 ms fit) and the finiteness
|
|
150
|
+
sum 8 to 14% on 20000 x 200 (none under `assume_finite`); with the
|
|
151
|
+
intercept, the column means add 20 to 30% on 20000 x 200 for the
|
|
152
|
+
Gram-matrix ones, which correct X'X
|
|
153
|
+
for the means rather than copy X to centre it, and about 55% for
|
|
154
|
+
`DesignLasso`, whose kernel needs the centred X itself.
|
|
155
|
+
`GramLogisticRegression` is slower than liblinear by its algorithm, 2.5x
|
|
156
|
+
at 20000 x 200 and more on small problems; `L1LogisticRegression` is
|
|
157
|
+
the fast one for that problem.
|
|
130
158
|
|
|
131
159
|
What it costs is the input checks: X must be a finite 2-D float64
|
|
132
160
|
array with the feature count of the fit. A plain C-ordered float64
|
|
@@ -166,6 +194,11 @@ package picks the fastest one present.
|
|
|
166
194
|
| `GramLasso` | Lasso(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
167
195
|
| `GramElasticNet` | ElasticNet(precompute=True), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
168
196
|
| `GramRidge` | Ridge, fit(X, y) with the intercept, one or many targets | numpy (Cholesky) | CPU | Ridge |
|
|
197
|
+
| `GramMultiTaskLasso` | MultiTaskLasso, fit(X, Y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
198
|
+
| `GramMultiTaskElasticNet` | MultiTaskElasticNet, fit(X, Y) with the intercept | `lasso-cov.scm` | CPU | no |
|
|
199
|
+
| `GramGroupLasso` | (none; skglm GroupLasso), fit(X, y) with the intercept | `lasso-cov.scm` | CPU | - |
|
|
200
|
+
| `GramLogisticRegression` | LogisticRegression(l1_ratio=1, solver='liblinear'), by majorization | `lasso-cov.scm` | CPU | no |
|
|
201
|
+
| `DesignLasso` | Lasso, fit(X, y) with the intercept, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
169
202
|
| `CovLasso` | Lasso, ElasticNet, lasso_path(precompute=True) | `lasso-cov.scm` | CPU; GPU batch (fit_path_batch, bootstrap) | no |
|
|
170
203
|
| `CovLassoCV` | LassoCV, ElasticNetCV | `lasso-cov.scm` | CPU; GPU batch | no |
|
|
171
204
|
| `DerivedLasso` | lasso_path, from the design | `lasso-design.scm (--derive)` | loops / BLAS / cuBLAS | no |
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_accel_cublas.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_classifiers.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_derived_blas.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_derived_cublas.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_derived_loops.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_gpu_cuda.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_gramops_blas.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_gramops_loops.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_nmf_blas.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_nmf_cublas.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/_loader_nmf_loops.py
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/accel_cublas/accel.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/classifiers_capi.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gpu_cuda/gpu_capi.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.hpp
RENAMED
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/lasso_cov_capi.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.hpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd_capi.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.hpp
RENAMED
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.cpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.hpp
RENAMED
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd_capi.cpp
RENAMED
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso/_generated/scm2cpp-cublas.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scm2cpp_lasso-0.14.0 → scm2cpp_lasso-0.15.0}/src/scm2cpp_lasso.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|