scm2cpp-lasso 0.11.0__tar.gz → 0.13.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.
Files changed (66) hide show
  1. {scm2cpp_lasso-0.11.0/src/scm2cpp_lasso.egg-info → scm2cpp_lasso-0.13.0}/PKG-INFO +37 -2
  2. scm2cpp_lasso-0.11.0/PKG-INFO → scm2cpp_lasso-0.13.0/README.md +35 -18
  3. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/pyproject.toml +3 -3
  4. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/setup.py +31 -0
  5. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/__init__.py +226 -15
  6. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/_loader_accel_cublas.py +140 -0
  7. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/_loader_gpu_cuda.py +294 -0
  8. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_gramops_blas.py +95 -6
  9. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_gramops_loops.py +95 -6
  10. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/accel_cublas/accel.cpp +20 -0
  11. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/accel_cublas/accel.hpp +1023 -0
  12. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/accel_cublas/accel_capi.cpp +64 -0
  13. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/gpu_cuda/gpu.cpp +35 -0
  14. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/gpu_cuda/gpu.hpp +3715 -0
  15. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/gpu_cuda/gpu_capi.cpp +289 -0
  16. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.cpp +12 -0
  17. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops.hpp +727 -22
  18. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/gramops_blas/gramops_capi.cpp +38 -2
  19. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.cpp +12 -0
  20. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops.hpp +877 -102
  21. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/gramops_loops/gramops_capi.cpp +38 -2
  22. scm2cpp_lasso-0.13.0/src/scm2cpp_lasso/_generated/scm2cpp-cuda.hpp +285 -0
  23. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/scm2cpp.hpp +18 -7
  24. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_libfind.py +24 -0
  25. scm2cpp_lasso-0.11.0/README.md → scm2cpp_lasso-0.13.0/src/scm2cpp_lasso.egg-info/PKG-INFO +53 -0
  26. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso.egg-info/SOURCES.txt +9 -0
  27. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/setup.cfg +0 -0
  28. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/__init__.py +0 -0
  29. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader.py +0 -0
  30. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_classifiers.py +0 -0
  31. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_derived_blas.py +0 -0
  32. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_derived_cublas.py +0 -0
  33. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_derived_loops.py +0 -0
  34. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_nmf_blas.py +0 -0
  35. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_nmf_cublas.py +0 -0
  36. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/_loader_nmf_loops.py +0 -0
  37. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/classifiers.cpp +0 -0
  38. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/classifiers.hpp +0 -0
  39. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/classifiers_capi.cpp +0 -0
  40. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design.cpp +0 -0
  41. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design.hpp +0 -0
  42. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_blas/lasso_design_capi.cpp +0 -0
  43. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design.cpp +0 -0
  44. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design.hpp +0 -0
  45. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_cublas/lasso_design_capi.cpp +0 -0
  46. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design.cpp +0 -0
  47. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design.hpp +0 -0
  48. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/derived_loops/lasso_design_capi.cpp +0 -0
  49. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/lasso_cov.cpp +0 -0
  50. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/lasso_cov.hpp +0 -0
  51. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/lasso_cov_capi.cpp +0 -0
  52. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.cpp +0 -0
  53. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd.hpp +0 -0
  54. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_blas/nmf_cd_capi.cpp +0 -0
  55. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.cpp +0 -0
  56. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd.hpp +0 -0
  57. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_cublas/nmf_cd_capi.cpp +0 -0
  58. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.cpp +0 -0
  59. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd.hpp +0 -0
  60. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/nmf_loops/nmf_cd_capi.cpp +0 -0
  61. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/scm2cpp-blas.hpp +0 -0
  62. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/_generated/scm2cpp-cublas.hpp +0 -0
  63. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso/batch_capi.cu +0 -0
  64. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso.egg-info/dependency_links.txt +0 -0
  65. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso.egg-info/requires.txt +0 -0
  66. {scm2cpp_lasso-0.11.0 → scm2cpp_lasso-0.13.0}/src/scm2cpp_lasso.egg-info/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scm2cpp-lasso
3
- Version: 0.11.0
4
- Summary: scikit-learn estimators (lasso, elastic net, ridge, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, NMF, Gaussian mixture, FastICA, PCA, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver included
3
+ Version: 0.13.0
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
7
7
  Project-URL: Homepage, https://github.com/niitsuma/scm2cpp
@@ -712,6 +712,41 @@ GramLassoLarsCV().fit(X, y).alpha_
712
712
  Speed, from the repository README's table: the GLMs 1.1-6x, the CV
713
713
  estimators 1.6-6.6x, Theil-Sen 1.3-1.8x (its subset drawing dominates).
714
714
 
715
+ ## Feature selection: `f_regression`, `f_classif`, `SelectKBest`, `SelectPercentile`, `GramRFE`
716
+
717
+ scikit-learn's univariate F statistics and its selectors over them,
718
+ and `RFE` around `Ridge` / `LinearRegression`, translated.
719
+ `f_regression` also takes an n x q array of targets: the q results in
720
+ one product, on the device when one answers.
721
+
722
+ ```python
723
+ from scm2cpp_lasso import SelectKBest, GramRFE, f_regression
724
+ SelectKBest("f_regression", k=20).fit(X, y).get_support()
725
+ GramRFE(alpha=1.0, n_features_to_select=10).fit(X, y).ranking_
726
+ F, p = f_regression(X, Y) # Y: n x q, every target at once
727
+ ```
728
+
729
+ The same scores, ranking and features as scikit-learn. RFE is 80-1,000x
730
+ faster (one Gram and one Cholesky factor, downdated, instead of a refit
731
+ per round), and f_regression over many targets 30-50x. The Gram-route
732
+ estimators (`GramLassoLarsIC`, `GramLarsCV`, `GramLassoLarsCV`,
733
+ `GramLars`, `GramLassoLars`, `CovPCA`) form a large X'X on the device
734
+ when one answers. `SCM2CPP_NO_DEVICE=1` keeps everything on the CPU.
735
+
736
+ ## The GPU build
737
+
738
+ Where the CUDA toolkit is at install time, `ParallelFastICA`,
739
+ `EMGaussianMixture`, `LBFGSLogisticRegression`,
740
+ `LBFGSLogisticRegressionCV`, `LBFGSHuberRegressor` and the `LBFGS*`
741
+ GLMs also get the same Scheme translated with `--cuda`
742
+ (`libscm2cpp_gpu.so`). Its loops are CUDA kernels and its products
743
+ cuBLAS, on arrays that stay on the device. The classes take it when a
744
+ device answers and the data has a million entries or more, and give
745
+ the CPU build's iterations and results to the last digits. Measured
746
+ against scikit-learn: 10-22x for the L-BFGS fits, 6.7x FastICA, 3x the
747
+ mixture and LogisticRegressionCV (the repository README's table).
748
+ `SCM2CPP_NO_DEVICE=1` keeps everything on the CPU.
749
+
715
750
  ## Logistic regression with L1
716
751
 
717
752
  `CovLogistic` solves L1-penalized logistic regression by
@@ -1,21 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: scm2cpp-lasso
3
- Version: 0.11.0
4
- Summary: scikit-learn estimators (lasso, elastic net, ridge, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, NMF, Gaussian mixture, FastICA, PCA, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver included
5
- Author: Hirotaka Niitsuma
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/niitsuma/scm2cpp
8
- Project-URL: Source, https://github.com/niitsuma/scm2cpp/tree/master/python/scm2cpp-lasso
9
- Keywords: lasso,elastic-net,ridge,svm,logistic-regression,coordinate-descent,cuda,compiler
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: C++
13
- Classifier: Topic :: Scientific/Engineering :: Mathematics
14
- Classifier: Intended Audience :: Science/Research
15
- Requires-Python: >=3.8
16
- Description-Content-Type: text/markdown
17
- Requires-Dist: numpy>=1.17
18
-
19
1
  # scm2cpp-lasso
20
2
 
21
3
  *[Japanese (README.ja.md)](README.ja.md)*
@@ -712,6 +694,41 @@ GramLassoLarsCV().fit(X, y).alpha_
712
694
  Speed, from the repository README's table: the GLMs 1.1-6x, the CV
713
695
  estimators 1.6-6.6x, Theil-Sen 1.3-1.8x (its subset drawing dominates).
714
696
 
697
+ ## Feature selection: `f_regression`, `f_classif`, `SelectKBest`, `SelectPercentile`, `GramRFE`
698
+
699
+ scikit-learn's univariate F statistics and its selectors over them,
700
+ and `RFE` around `Ridge` / `LinearRegression`, translated.
701
+ `f_regression` also takes an n x q array of targets: the q results in
702
+ one product, on the device when one answers.
703
+
704
+ ```python
705
+ from scm2cpp_lasso import SelectKBest, GramRFE, f_regression
706
+ SelectKBest("f_regression", k=20).fit(X, y).get_support()
707
+ GramRFE(alpha=1.0, n_features_to_select=10).fit(X, y).ranking_
708
+ F, p = f_regression(X, Y) # Y: n x q, every target at once
709
+ ```
710
+
711
+ The same scores, ranking and features as scikit-learn. RFE is 80-1,000x
712
+ faster (one Gram and one Cholesky factor, downdated, instead of a refit
713
+ per round), and f_regression over many targets 30-50x. The Gram-route
714
+ estimators (`GramLassoLarsIC`, `GramLarsCV`, `GramLassoLarsCV`,
715
+ `GramLars`, `GramLassoLars`, `CovPCA`) form a large X'X on the device
716
+ when one answers. `SCM2CPP_NO_DEVICE=1` keeps everything on the CPU.
717
+
718
+ ## The GPU build
719
+
720
+ Where the CUDA toolkit is at install time, `ParallelFastICA`,
721
+ `EMGaussianMixture`, `LBFGSLogisticRegression`,
722
+ `LBFGSLogisticRegressionCV`, `LBFGSHuberRegressor` and the `LBFGS*`
723
+ GLMs also get the same Scheme translated with `--cuda`
724
+ (`libscm2cpp_gpu.so`). Its loops are CUDA kernels and its products
725
+ cuBLAS, on arrays that stay on the device. The classes take it when a
726
+ device answers and the data has a million entries or more, and give
727
+ the CPU build's iterations and results to the last digits. Measured
728
+ against scikit-learn: 10-22x for the L-BFGS fits, 6.7x FastICA, 3x the
729
+ mixture and LogisticRegressionCV (the repository README's table).
730
+ `SCM2CPP_NO_DEVICE=1` keeps everything on the CPU.
731
+
715
732
  ## Logistic regression with L1
716
733
 
717
734
  `CovLogistic` solves L1-penalized logistic regression by
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "scm2cpp-lasso"
7
- version = "0.11.0"
8
- description = "scikit-learn estimators (lasso, elastic net, ridge, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, NMF, Gaussian mixture, FastICA, PCA, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver included"
7
+ version = "0.13.0"
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"
11
11
  license = {text = "MIT"}
@@ -31,4 +31,4 @@ package-dir = {"" = "src"}
31
31
  where = ["src"]
32
32
 
33
33
  [tool.setuptools.package-data]
34
- scm2cpp_lasso = ["_generated/*.hpp", "_generated/*.cpp", "_generated/derived_*/*.hpp", "_generated/derived_*/*.cpp", "_generated/nmf_*/*.hpp", "_generated/nmf_*/*.cpp", "_generated/gramops_*/*.hpp", "_generated/gramops_*/*.cpp", "*.cu"]
34
+ scm2cpp_lasso = ["_generated/*.hpp", "_generated/*.cpp", "_generated/derived_*/*.hpp", "_generated/derived_*/*.cpp", "_generated/nmf_*/*.hpp", "_generated/nmf_*/*.cpp", "_generated/gramops_*/*.hpp", "_generated/gramops_*/*.cpp", "_generated/accel_*/*.hpp", "_generated/accel_*/*.cpp", "_generated/gpu_*/*.hpp", "_generated/gpu_*/*.cpp", "*.cu"]
@@ -120,6 +120,28 @@ class BuildWithCuda(build_ext):
120
120
  except (subprocess.CalledProcessError, OSError) as exc:
121
121
  print(f"scm2cpp_lasso: no CUDA batch path ({exc}); "
122
122
  "the CPU solver is unaffected", file=sys.stderr)
123
+ # the --cuda translation (kernels + device-resident cuBLAS):
124
+ # FastICA, the mixture, the L-BFGS fits
125
+ gpu = GEN / "gpu_cuda" / "gpu_capi.cpp"
126
+ if gpu.exists():
127
+ out2 = Path(self.build_lib) / "scm2cpp_lasso" / "libscm2cpp_gpu.so"
128
+ # the installed device's architecture when one answers
129
+ arch = []
130
+ try:
131
+ if subprocess.run(["nvidia-smi"], capture_output=True).returncode == 0:
132
+ arch = ["-arch=native"]
133
+ except OSError:
134
+ pass
135
+ cmd2 = [nvcc, "-O3", "-std=c++17", "-shared", "-x", "cu", *arch,
136
+ "-Xcompiler", "-fPIC", "-I", str(GEN / "gpu_cuda"), "-I", str(GEN),
137
+ str(gpu), "-o", str(out2), "-lcublas",
138
+ "-Wno-deprecated-gpu-targets", "-diag-suppress", "174,177,550"]
139
+ try:
140
+ subprocess.run(cmd2, check=True)
141
+ print("scm2cpp_lasso: built the --cuda estimators")
142
+ except (subprocess.CalledProcessError, OSError) as exc:
143
+ print(f"scm2cpp_lasso: no --cuda estimators ({exc}); "
144
+ "the CPU paths are unaffected", file=sys.stderr)
123
145
 
124
146
 
125
147
  # The cuBLAS variant of the derived kernel: host C++ against the CUDA
@@ -211,4 +233,13 @@ if _cuda is not None:
211
233
  extra_compile_args=CXXFLAGS + ["-O3", "-fstrict-overflow"],
212
234
  ))
213
235
 
236
+ extensions.append(Extension(
237
+ "scm2cpp_lasso._accel_cublas",
238
+ sources=[GEN_REL + "/accel_cublas/accel_capi.cpp"],
239
+ include_dirs=[GEN_REL + "/accel_cublas", GEN_REL, str(_cuda / "include")],
240
+ library_dirs=[str(_cuda / "lib64"), str(_cuda / "lib")],
241
+ libraries=["cublas", "cudart"],
242
+ extra_compile_args=CXXFLAGS + ["-O3", "-fstrict-overflow"],
243
+ ))
244
+
214
245
  setup(ext_modules=extensions, cmdclass={"build_ext": BuildWithCuda})
@@ -47,10 +47,11 @@ __all__ = ["CovLasso", "CovRidge", "CovBayesianRidge", "CovLogistic", "CovGroupL
47
47
  "LBFGSPoissonRegressor", "LBFGSGammaRegressor", "LBFGSTweedieRegressor",
48
48
  "GramLarsCV", "GramLassoLarsCV", "GramOMPCV",
49
49
  "EMGaussianMixture", "CovPCA", "ParallelFastICA", "CovARDRegression",
50
- "L1LinearSVM", "WeiszfeldTheilSen",
50
+ "L1LinearSVM", "WeiszfeldTheilSen", "f_regression", "f_classif", "SelectKBest",
51
+ "SelectPercentile", "GramRFE",
51
52
  "CovMultiTaskLasso", "CovMultiTaskLassoCV", "DerivedLasso",
52
53
  "cuda_available", "derived_backend", "kernel"]
53
- __version__ = "0.11.0"
54
+ __version__ = "0.13.0"
54
55
 
55
56
  _BATCH = load_batch_lib()
56
57
  _DP = ctypes.POINTER(ctypes.c_double)
@@ -1349,7 +1350,7 @@ class LBFGSLogisticRegression:
1349
1350
  k = nc if multi else 1
1350
1351
  coef = np.zeros(k * (p + 1))
1351
1352
  out = np.zeros(2)
1352
- it = _gramops_kernels().logistic_lbfgs(
1353
+ it = _gpu_or_cpu(n * p, getattr(self, "backend", None)).logistic_lbfgs(
1353
1354
  X, yi.astype(np.float64), coef, out, float(self.C), int(self.max_iter),
1354
1355
  float(self.tol), multi, 1 if self.fit_intercept else 0, n, p, k)
1355
1356
  self.coef_ = coef[:k * p].reshape(k, p).copy()
@@ -1417,7 +1418,7 @@ class _LBFGSGLM:
1417
1418
  coef = np.zeros(p + 1)
1418
1419
  out = np.zeros(2)
1419
1420
  fam, power = self._family_power()
1420
- it = _gramops_kernels().glm(X, y, coef, out, fam, float(power), float(self.alpha),
1421
+ it = _gpu_or_cpu(n * p, getattr(self, "backend", None)).glm(X, y, coef, out, fam, float(power), float(self.alpha),
1421
1422
  int(self.max_iter), float(self.tol),
1422
1423
  1 if self.fit_intercept else 0, n, p)
1423
1424
  self.coef_, self.intercept_ = coef[:p].copy(), float(coef[p])
@@ -1498,7 +1499,7 @@ class LBFGSLogisticRegressionCV:
1498
1499
 
1499
1500
  def _path(self, X, yi, Cs, coef, multi, k):
1500
1501
  n, p = X.shape
1501
- lib = _gramops_kernels()
1502
+ lib = _gpu_or_cpu(n * p, getattr(self, "backend", None))
1502
1503
  coefs, iters = [], []
1503
1504
  out = np.zeros(2)
1504
1505
  for C in Cs:
@@ -1581,7 +1582,7 @@ class LBFGSHuberRegressor:
1581
1582
  coef = np.zeros(p + 2)
1582
1583
  coef[-1] = 1.0
1583
1584
  out = np.zeros(2)
1584
- it = _gramops_kernels().huber(
1585
+ it = _gpu_or_cpu(n * p, getattr(self, "backend", None)).huber(
1585
1586
  X, y, coef, out, float(self.epsilon), float(self.alpha), int(self.max_iter),
1586
1587
  float(self.tol), 1 if self.fit_intercept else 0, n, p)
1587
1588
  self.coef_ = coef[:p].copy()
@@ -1642,7 +1643,7 @@ class EMGaussianMixture:
1642
1643
  self.precisions_cholesky_ = np.zeros((k, p, p))
1643
1644
  labels = np.zeros(n)
1644
1645
  out = np.zeros(2)
1645
- it = _gramops_kernels().gmm(X, resp, self.weights_, self.means_,
1646
+ it = _gpu_or_cpu(n * p, getattr(self, "backend", None)).gmm(X, resp, self.weights_, self.means_,
1646
1647
  self.precisions_cholesky_, labels, out,
1647
1648
  int(self.max_iter), float(self.tol),
1648
1649
  float(self.reg_covar), n, p, k)
@@ -1689,14 +1690,15 @@ class CovPCA:
1689
1690
  n_components_.
1690
1691
  """
1691
1692
 
1692
- def __init__(self, n_components=None):
1693
- self.n_components = n_components
1693
+ def __init__(self, n_components=None, *, backend=None):
1694
+ self.n_components, self.backend = n_components, backend
1694
1695
 
1695
1696
  def fit(self, X, y=None):
1696
1697
  X = np.ascontiguousarray(X, dtype=np.float64)
1697
1698
  n, p = X.shape
1698
1699
  comps = np.zeros((p, p)); ev = np.zeros(p); sv = np.zeros(p); mean = np.zeros(p)
1699
- _gramops_kernels().pca(X, comps, ev, sv, mean, n, p)
1700
+ lib = _accel(float(n) * p * p) if self.backend in (None, "cublas") else None
1701
+ (lib or _gramops_kernels()).pca(X, comps, ev, sv, mean, n, p)
1700
1702
  k = min(n, p) if self.n_components is None else int(self.n_components)
1701
1703
  self.n_components_ = k
1702
1704
  self.mean_ = mean
@@ -1742,7 +1744,7 @@ class ParallelFastICA:
1742
1744
  w0 = np.ascontiguousarray(w0)
1743
1745
  self.components_ = np.zeros((k, p)); self.whitening_ = np.zeros((k, p))
1744
1746
  self._unmixing = np.zeros((k, k)); self.mean_ = np.zeros(p)
1745
- self.n_iter_ = _gramops_kernels().fastica(
1747
+ self.n_iter_ = _gpu_or_cpu(n * p, getattr(self, "backend", None)).fastica(
1746
1748
  X, w0, self.components_, self.whitening_, self._unmixing, self.mean_,
1747
1749
  int(self.max_iter), float(self.tol), n, p, k)
1748
1750
  self.mixing_ = np.linalg.pinv(self.components_)
@@ -1801,11 +1803,220 @@ class CovARDRegression:
1801
1803
  return np.ascontiguousarray(X, dtype=np.float64) @ self.coef_ + self.intercept_
1802
1804
 
1803
1805
 
1806
+ def _gpu_or_cpu(size, backend=None):
1807
+ """The --cuda translation (kernels and device-resident cuBLAS) when it
1808
+ was built, a device answers, the backend allows it and the problem has
1809
+ at least a million entries; the CPU library otherwise."""
1810
+ import os
1811
+ from ._libfind import gpu_built
1812
+ if (backend in (None, "cuda") and size >= 1e6 and not os.environ.get("SCM2CPP_NO_DEVICE")
1813
+ and gpu_built() and cuda_available()):
1814
+ import importlib
1815
+ return importlib.import_module(f"{__name__}._generated._loader_gpu_cuda")
1816
+ return _gramops_kernels()
1817
+
1818
+
1819
+ def _accel(work):
1820
+ """The --cublas build of the selection and Gram products, when it was
1821
+ built, a device answers, and WORK (flops) is large enough to pay for
1822
+ the transfer; else None."""
1823
+ import os
1824
+ from ._libfind import accel_built
1825
+ if (work < 2e9 or os.environ.get("SCM2CPP_NO_DEVICE") or not accel_built()
1826
+ or not cuda_available()):
1827
+ return None
1828
+ import importlib
1829
+ return importlib.import_module(f"{__name__}._generated._loader_accel_cublas")
1830
+
1831
+
1832
+ def _gram(Xc, backend=None):
1833
+ """X'X: on the device for a large product when one answers, else numpy."""
1834
+ n, p = Xc.shape
1835
+ lib = _accel(float(n) * p * p) if backend in (None, "cublas") else None
1836
+ if lib is None:
1837
+ return np.ascontiguousarray(Xc.T @ Xc)
1838
+ G = np.zeros((p, p))
1839
+ lib.gram_xx(np.ascontiguousarray(Xc), G, n, p)
1840
+ return G
1841
+
1842
+
1843
+ def _cpu_select_lib():
1844
+ return _gramops_kernels()
1845
+
1846
+
1847
+ def f_regression(X, y, *, center=True, backend=None):
1848
+ """scikit-learn's ``f_regression`` translated (``fscore.scm``): F and
1849
+ p-values of each feature against y. ``y`` may also be n x q, the q
1850
+ targets in one call (one product X'Y, on the device when one answers
1851
+ and the product is large) -- what a loop of scikit-learn's calls
1852
+ gives, column by column. Infinite F (perfect correlation) becomes
1853
+ the largest double and NaN F zero with p-value 1, as
1854
+ force_finite=True has it. p-values need scipy (else None)."""
1855
+ X = np.ascontiguousarray(X, dtype=np.float64)
1856
+ Y = np.asarray(y, dtype=np.float64)
1857
+ one = Y.ndim == 1
1858
+ Y = np.ascontiguousarray(Y.reshape(len(Y), -1))
1859
+ n, p = X.shape
1860
+ q = Y.shape[1]
1861
+ lib = _accel(float(n) * p * q) if backend in (None, "cublas") else None
1862
+ if lib is None:
1863
+ lib = _cpu_select_lib()
1864
+ r = np.zeros((p, q))
1865
+ F = np.zeros((p, q))
1866
+ with np.errstate(divide="ignore", invalid="ignore"):
1867
+ lib.f_regression(X, Y, r, F, 1 if center else 0, n, p, q)
1868
+ dof = n - (2 if center else 1)
1869
+ try:
1870
+ from scipy import stats
1871
+ pv = stats.f.sf(F, 1, dof)
1872
+ except ImportError:
1873
+ pv = None
1874
+ inf = np.isinf(F)
1875
+ F[inf] = np.finfo(np.float64).max
1876
+ nan = np.isnan(F)
1877
+ F[nan] = 0.0
1878
+ if pv is not None:
1879
+ pv[nan] = 1.0
1880
+ if one:
1881
+ return F[:, 0], (None if pv is None else pv[:, 0])
1882
+ return F, pv
1883
+
1884
+
1885
+ def f_classif(X, y):
1886
+ """scikit-learn's ``f_classif`` translated (``fscore.scm``: f_oneway's
1887
+ sums of squares, the class sums one product). p-values need scipy."""
1888
+ X = np.ascontiguousarray(X, dtype=np.float64)
1889
+ classes, lab = np.unique(np.asarray(y), return_inverse=True)
1890
+ n, p = X.shape
1891
+ k = len(classes)
1892
+ F = np.zeros(p)
1893
+ with np.errstate(divide="ignore", invalid="ignore"):
1894
+ _cpu_select_lib().f_classif(X, lab.astype(np.int32), F, n, p, k)
1895
+ try:
1896
+ from scipy import special
1897
+ pv = special.fdtrc(k - 1, n - k, F)
1898
+ except ImportError:
1899
+ pv = None
1900
+ return F, pv
1901
+
1902
+
1903
+ def _clean_nans(scores):
1904
+ scores = np.array(scores, dtype=np.float64, copy=True)
1905
+ scores[np.isnan(scores)] = np.finfo(np.float64).min
1906
+ return scores
1907
+
1908
+
1909
+ class _SelectBase:
1910
+ def fit(self, X, y):
1911
+ sf = self.score_func
1912
+ fn = {"f_classif": f_classif, "f_regression": f_regression}.get(sf, sf)
1913
+ self.scores_, self.pvalues_ = fn(X, y)
1914
+ return self
1915
+
1916
+ def transform(self, X):
1917
+ return np.asarray(X)[:, self.get_support()]
1918
+
1919
+ def fit_transform(self, X, y):
1920
+ return self.fit(X, y).transform(X)
1921
+
1922
+
1923
+ class SelectKBest(_SelectBase):
1924
+ """scikit-learn's ``SelectKBest`` over the translated F statistics
1925
+ (``score_func`` "f_classif", "f_regression", or one of this module's
1926
+ functions): the k best scores by a stable sort, NaN scores last.
1927
+
1928
+ Attributes after fit: scores_, pvalues_.
1929
+ """
1930
+
1931
+ def __init__(self, score_func="f_classif", *, k=10):
1932
+ self.score_func, self.k = score_func, k
1933
+
1934
+ def get_support(self):
1935
+ if self.k == "all":
1936
+ return np.ones(len(self.scores_), dtype=bool)
1937
+ mask = np.zeros(len(self.scores_), dtype=bool)
1938
+ if self.k == 0:
1939
+ return mask
1940
+ mask[np.argsort(_clean_nans(self.scores_), kind="mergesort")[-self.k:]] = True
1941
+ return mask
1942
+
1943
+
1944
+ class SelectPercentile(_SelectBase):
1945
+ """scikit-learn's ``SelectPercentile`` over the translated F
1946
+ statistics: scores above the (100 - percentile)th percentile, ties
1947
+ at it kept in order up to the percentile's count.
1948
+
1949
+ Attributes after fit: scores_, pvalues_.
1950
+ """
1951
+
1952
+ def __init__(self, score_func="f_classif", *, percentile=10):
1953
+ self.score_func, self.percentile = score_func, percentile
1954
+
1955
+ def get_support(self):
1956
+ if self.percentile == 100:
1957
+ return np.ones(len(self.scores_), dtype=bool)
1958
+ if self.percentile == 0:
1959
+ return np.zeros(len(self.scores_), dtype=bool)
1960
+ scores = _clean_nans(self.scores_)
1961
+ threshold = np.percentile(scores, 100 - self.percentile)
1962
+ mask = scores > threshold
1963
+ ties = np.where(scores == threshold)[0]
1964
+ if len(ties):
1965
+ max_feats = int(len(scores) * self.percentile / 100)
1966
+ mask[ties[: max_feats - mask.sum()]] = True
1967
+ return mask
1968
+
1969
+
1970
+ class GramRFE:
1971
+ """scikit-learn's ``RFE`` around ``Ridge(alpha)`` (``alpha=0``:
1972
+ ``LinearRegression()``) translated whole (``rfe.scm``): the centred
1973
+ Gram formed once (on the device for a large one when one answers),
1974
+ each round's fit from its Cholesky factor with the dropped features
1975
+ taken out by plane rotations, the features ranked by coef^2 in a
1976
+ stable order. scikit-learn refits from X every round; the ranking
1977
+ and the final coefficients are the same to rounding.
1978
+
1979
+ Attributes after fit: support_, ranking_, n_features_, coef_,
1980
+ intercept_.
1981
+ """
1982
+
1983
+ def __init__(self, alpha=1.0, *, n_features_to_select=None, step=1, backend=None):
1984
+ self.alpha, self.n_features_to_select, self.step = alpha, n_features_to_select, step
1985
+ self.backend = backend
1986
+
1987
+ def fit(self, X, y):
1988
+ X = np.ascontiguousarray(X, dtype=np.float64)
1989
+ y = np.ascontiguousarray(y, dtype=np.float64)
1990
+ n, p = X.shape
1991
+ k = self.n_features_to_select
1992
+ nsel = p // 2 if k is None else (int(k) if isinstance(k, (int, np.integer)) else int(p * k))
1993
+ step = int(max(1, self.step * p)) if 0.0 < self.step < 1.0 else int(self.step)
1994
+ lib = _accel(float(n) * p * p) if self.backend in (None, "cublas") else None
1995
+ if lib is None:
1996
+ lib = _cpu_select_lib()
1997
+ coef = np.zeros(p)
1998
+ support = np.zeros(p, dtype=np.int32)
1999
+ ranking = np.zeros(p, dtype=np.int32)
2000
+ lib.rfe(X, y, coef, support, ranking, float(self.alpha), nsel, step, n, p)
2001
+ self.support_ = support.astype(bool)
2002
+ self.ranking_ = ranking.astype(int)
2003
+ self.n_features_ = int(self.support_.sum())
2004
+ self.coef_ = coef[self.support_].copy()
2005
+ self.intercept_ = float(y.mean() - X.mean(axis=0)[self.support_] @ self.coef_)
2006
+ return self
2007
+
2008
+ def transform(self, X):
2009
+ return np.asarray(X)[:, self.support_]
2010
+
2011
+ def predict(self, X):
2012
+ return self.transform(np.asarray(X, dtype=np.float64)) @ self.coef_ + self.intercept_
2013
+
2014
+
1804
2015
  class _GramLarsBase:
1805
2016
  def _fit_lars(self, X, y, method, alpha, max_iter):
1806
2017
  Xc, yc, xm, ym = _center(X, y, self.fit_intercept)
1807
2018
  n, p = Xc.shape
1808
- G = np.ascontiguousarray(Xc.T @ Xc)
2019
+ G = _gram(Xc)
1809
2020
  cov = Xc.T @ yc
1810
2021
  self.coef_ = np.zeros(p)
1811
2022
  self.n_iter_ = _classifier_kernels().lars(
@@ -1868,7 +2079,7 @@ class _GramLarsCVBase:
1868
2079
 
1869
2080
  def _lars(self, Xc, yc, alpha_min, rec):
1870
2081
  n, p = Xc.shape
1871
- G = np.ascontiguousarray(Xc.T @ Xc)
2082
+ G = _gram(Xc)
1872
2083
  cov = Xc.T @ yc
1873
2084
  coef = np.zeros(p)
1874
2085
  path = np.zeros((self.max_iter + 1, p)) if rec else np.zeros(1)
@@ -1889,7 +2100,7 @@ class _GramLarsCVBase:
1889
2100
  xm, ym = Xtr.mean(axis=0), ytr.mean()
1890
2101
  Xtr, Xte, ytr, yte = Xtr - xm, Xte - xm, ytr - ym, yte - ym
1891
2102
  _, _, path, alphas = self._lars(np.ascontiguousarray(Xtr), ytr, 0.0, True)
1892
- folds.append((alphas, path, Xte.T @ Xte, Xte.T @ yte, float(yte @ yte), len(test)))
2103
+ folds.append((alphas, path, _gram(Xte), Xte.T @ yte, float(yte @ yte), len(test)))
1893
2104
  all_alphas = np.unique(np.concatenate([f[0] for f in folds]))
1894
2105
  stride = int(max(1, int(len(all_alphas) / float(self.max_n_alphas))))
1895
2106
  all_alphas = all_alphas[::stride]
@@ -1998,7 +2209,7 @@ class GramLassoLarsIC:
1998
2209
  def fit(self, X, y):
1999
2210
  Xc, yc, xm, ym = _center(X, y, self.fit_intercept)
2000
2211
  n, p = Xc.shape
2001
- G0 = np.ascontiguousarray(Xc.T @ Xc)
2212
+ G0 = _gram(Xc)
2002
2213
  cov0 = Xc.T @ yc
2003
2214
  yy = float(yc @ yc)
2004
2215
  path = np.zeros((self.max_iter + 1, p))
@@ -0,0 +1,140 @@
1
+ # ctypes loader for libaccel.so, generated alongside it.
2
+ # Arrays are numpy arrays of the declared dtype; they are made
3
+ # contiguous on the way in and mutated in place where the translated
4
+ # function mutates them.
5
+ import ctypes
6
+ import numpy as np
7
+ from pathlib import Path
8
+
9
+ from .._libfind import load_accel_lib as _load_accel_lib
10
+
11
+ _lib = _load_accel_lib()
12
+
13
+ _lib.scm2cpp_f_regression.restype = ctypes.c_int
14
+ _lib.scm2cpp_f_regression.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
15
+ def f_regression(x, y, r, f, center, n, p, q):
16
+ x = np.ascontiguousarray(x, dtype=np.float64)
17
+ y = np.ascontiguousarray(y, dtype=np.float64)
18
+ r = np.ascontiguousarray(r, dtype=np.float64)
19
+ f = np.ascontiguousarray(f, dtype=np.float64)
20
+ return _lib.scm2cpp_f_regression(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), y.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), r.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), f.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), center, n, p, q)
21
+
22
+ _lib.scm2cpp_f_classif.restype = ctypes.c_int
23
+ _lib.scm2cpp_f_classif.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int]
24
+ def f_classif(x, lab, f, n, p, k):
25
+ x = np.ascontiguousarray(x, dtype=np.float64)
26
+ lab = np.ascontiguousarray(lab, dtype=np.int32)
27
+ f = np.ascontiguousarray(f, dtype=np.float64)
28
+ return _lib.scm2cpp_f_classif(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), lab.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), f.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, p, k)
29
+
30
+ _lib.scm2cpp_min_pos.restype = ctypes.c_double
31
+ _lib.scm2cpp_min_pos.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int]
32
+ def min_pos(v, m):
33
+ v = np.ascontiguousarray(v, dtype=np.float64)
34
+ return _lib.scm2cpp_min_pos(v.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m)
35
+
36
+ _lib.scm2cpp_round_even.restype = ctypes.c_double
37
+ _lib.scm2cpp_round_even.argtypes = [ctypes.c_double]
38
+ def round_even(y):
39
+ return _lib.scm2cpp_round_even(y)
40
+
41
+ _lib.scm2cpp_cholesky_delete.restype = ctypes.c_int
42
+ _lib.scm2cpp_cholesky_delete.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int]
43
+ def cholesky_delete(l, go, n, k):
44
+ l = np.ascontiguousarray(l, dtype=np.float64)
45
+ return _lib.scm2cpp_cholesky_delete(l.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), go, n, k)
46
+
47
+ _lib.scm2cpp_swap_rc.restype = ctypes.c_int
48
+ _lib.scm2cpp_swap_rc.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int]
49
+ def swap_rc(g, a, b, p):
50
+ g = np.ascontiguousarray(g, dtype=np.float64)
51
+ return _lib.scm2cpp_swap_rc(g.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), a, b, p)
52
+
53
+ _lib.scm2cpp_lars.restype = ctypes.c_int
54
+ _lib.scm2cpp_lars.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_double, ctypes.c_double, ctypes.c_int, ctypes.c_int, ctypes.c_double, ctypes.c_int]
55
+ def lars(g, cov, coef, path, alphas, rec, nsamples, alphamin, method, maxiter, eps, p):
56
+ g = np.ascontiguousarray(g, dtype=np.float64)
57
+ cov = np.ascontiguousarray(cov, dtype=np.float64)
58
+ coef = np.ascontiguousarray(coef, dtype=np.float64)
59
+ path = np.ascontiguousarray(path, dtype=np.float64)
60
+ alphas = np.ascontiguousarray(alphas, dtype=np.float64)
61
+ return _lib.scm2cpp_lars(g.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), cov.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), coef.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), path.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), alphas.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), rec, nsamples, alphamin, method, maxiter, eps, p)
62
+
63
+ _lib.scm2cpp_rfe_chol.restype = ctypes.c_int
64
+ _lib.scm2cpp_rfe_chol.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_double), ctypes.c_double, ctypes.c_int, ctypes.c_int]
65
+ def rfe_chol(g, idx, l, alpha, k, p):
66
+ g = np.ascontiguousarray(g, dtype=np.float64)
67
+ idx = np.ascontiguousarray(idx, dtype=np.int32)
68
+ l = np.ascontiguousarray(l, dtype=np.float64)
69
+ return _lib.scm2cpp_rfe_chol(g.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), idx.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), l.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), alpha, k, p)
70
+
71
+ _lib.scm2cpp_rfe_solve.restype = ctypes.c_int
72
+ _lib.scm2cpp_rfe_solve.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
73
+ def rfe_solve(c, idx, w, l, k, p):
74
+ c = np.ascontiguousarray(c, dtype=np.float64)
75
+ idx = np.ascontiguousarray(idx, dtype=np.int32)
76
+ w = np.ascontiguousarray(w, dtype=np.float64)
77
+ l = np.ascontiguousarray(l, dtype=np.float64)
78
+ return _lib.scm2cpp_rfe_solve(c.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), idx.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), w.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), l.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), k, p)
79
+
80
+ _lib.scm2cpp_rfe.restype = ctypes.c_int
81
+ _lib.scm2cpp_rfe.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.c_double, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
82
+ def rfe(x, y, coef, support, ranking, alpha, nsel, step, n, p):
83
+ x = np.ascontiguousarray(x, dtype=np.float64)
84
+ y = np.ascontiguousarray(y, dtype=np.float64)
85
+ coef = np.ascontiguousarray(coef, dtype=np.float64)
86
+ support = np.ascontiguousarray(support, dtype=np.int32)
87
+ ranking = np.ascontiguousarray(ranking, dtype=np.int32)
88
+ return _lib.scm2cpp_rfe(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), y.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), coef.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), support.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), ranking.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), alpha, nsel, step, n, p)
89
+
90
+ _lib.scm2cpp_eig_hypot.restype = ctypes.c_double
91
+ _lib.scm2cpp_eig_hypot.argtypes = [ctypes.c_double, ctypes.c_double]
92
+ def eig_hypot(a, b):
93
+ return _lib.scm2cpp_eig_hypot(a, b)
94
+
95
+ _lib.scm2cpp_sym_eigen.restype = ctypes.c_int
96
+ _lib.scm2cpp_sym_eigen.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int]
97
+ def sym_eigen(a, v, ev, e, m):
98
+ a = np.ascontiguousarray(a, dtype=np.float64)
99
+ v = np.ascontiguousarray(v, dtype=np.float64)
100
+ ev = np.ascontiguousarray(ev, dtype=np.float64)
101
+ e = np.ascontiguousarray(e, dtype=np.float64)
102
+ return _lib.scm2cpp_sym_eigen(a.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), v.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), ev.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), e.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m)
103
+
104
+ _lib.scm2cpp_eig_abs.restype = ctypes.c_double
105
+ _lib.scm2cpp_eig_abs.argtypes = [ctypes.c_double]
106
+ def eig_abs(a):
107
+ return _lib.scm2cpp_eig_abs(a)
108
+
109
+ _lib.scm2cpp_eig_order.restype = ctypes.c_int
110
+ _lib.scm2cpp_eig_order.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int), ctypes.c_int]
111
+ def eig_order(ev, ord, m):
112
+ ev = np.ascontiguousarray(ev, dtype=np.float64)
113
+ ord = np.ascontiguousarray(ord, dtype=np.int32)
114
+ return _lib.scm2cpp_eig_order(ev.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), ord.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), m)
115
+
116
+ _lib.scm2cpp_pca.restype = ctypes.c_int
117
+ _lib.scm2cpp_pca.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
118
+ def pca(x, comps, ev, sv, mean, n, p):
119
+ x = np.ascontiguousarray(x, dtype=np.float64)
120
+ comps = np.ascontiguousarray(comps, dtype=np.float64)
121
+ ev = np.ascontiguousarray(ev, dtype=np.float64)
122
+ sv = np.ascontiguousarray(sv, dtype=np.float64)
123
+ mean = np.ascontiguousarray(mean, dtype=np.float64)
124
+ return _lib.scm2cpp_pca(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), comps.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), ev.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), sv.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), mean.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, p)
125
+
126
+ _lib.scm2cpp_gram_xx.restype = ctypes.c_int
127
+ _lib.scm2cpp_gram_xx.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
128
+ def gram_xx(x, g, n, p):
129
+ x = np.ascontiguousarray(x, dtype=np.float64)
130
+ g = np.ascontiguousarray(g, dtype=np.float64)
131
+ return _lib.scm2cpp_gram_xx(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), g.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, p)
132
+
133
+ _lib.scm2cpp_gram_xy.restype = ctypes.c_int
134
+ _lib.scm2cpp_gram_xy.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int]
135
+ def gram_xy(x, y, c, n, p, q):
136
+ x = np.ascontiguousarray(x, dtype=np.float64)
137
+ y = np.ascontiguousarray(y, dtype=np.float64)
138
+ c = np.ascontiguousarray(c, dtype=np.float64)
139
+ return _lib.scm2cpp_gram_xy(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), y.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), c.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, p, q)
140
+