scm2cpp-learn 0.18.0__tar.gz → 0.19.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 (67) hide show
  1. {scm2cpp_learn-0.18.0/src/scm2cpp_learn.egg-info → scm2cpp_learn-0.19.0}/PKG-INFO +45 -2
  2. scm2cpp_learn-0.18.0/PKG-INFO → scm2cpp_learn-0.19.0/README.md +43 -18
  3. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/pyproject.toml +2 -2
  4. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/__init__.py +257 -11
  5. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_gramops_blas.py +84 -4
  6. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_gramops_loops.py +84 -4
  7. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_blas/lasso_design.hpp +12 -12
  8. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_cublas/lasso_design.hpp +13 -13
  9. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_loops/lasso_design.hpp +24 -24
  10. {scm2cpp_learn-0.18.0/src/scm2cpp_learn/_generated/gramops_loops → scm2cpp_learn-0.19.0/src/scm2cpp_learn/_generated/gramops_blas}/gramops.cpp +9 -0
  11. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gramops_blas/gramops.hpp +841 -29
  12. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gramops_blas/gramops_capi.cpp +29 -2
  13. {scm2cpp_learn-0.18.0/src/scm2cpp_learn/_generated/gramops_blas → scm2cpp_learn-0.19.0/src/scm2cpp_learn/_generated/gramops_loops}/gramops.cpp +9 -0
  14. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gramops_loops/gramops.hpp +1108 -224
  15. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gramops_loops/gramops_capi.cpp +29 -2
  16. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_blas/nmf_cd.hpp +13 -13
  17. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_cublas/nmf_cd.hpp +17 -17
  18. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_loops/nmf_cd.hpp +29 -29
  19. scm2cpp_learn-0.18.0/README.md → scm2cpp_learn-0.19.0/src/scm2cpp_learn.egg-info/PKG-INFO +61 -0
  20. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/setup.cfg +0 -0
  21. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/setup.py +0 -0
  22. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_compat.py +0 -0
  23. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/__init__.py +0 -0
  24. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader.py +0 -0
  25. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_accel_cublas.py +0 -0
  26. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_classifiers.py +0 -0
  27. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_derived_blas.py +0 -0
  28. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_derived_cublas.py +0 -0
  29. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_derived_loops.py +0 -0
  30. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_gpu_cuda.py +0 -0
  31. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_nmf_blas.py +0 -0
  32. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_nmf_cublas.py +0 -0
  33. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/_loader_nmf_loops.py +0 -0
  34. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/accel_cublas/accel.cpp +0 -0
  35. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/accel_cublas/accel.hpp +0 -0
  36. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/accel_cublas/accel_capi.cpp +0 -0
  37. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/classifiers.cpp +0 -0
  38. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/classifiers.hpp +0 -0
  39. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/classifiers_capi.cpp +0 -0
  40. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_blas/lasso_design.cpp +0 -0
  41. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_blas/lasso_design_capi.cpp +0 -0
  42. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_cublas/lasso_design.cpp +0 -0
  43. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_cublas/lasso_design_capi.cpp +0 -0
  44. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_loops/lasso_design.cpp +0 -0
  45. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/derived_loops/lasso_design_capi.cpp +0 -0
  46. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gpu_cuda/gpu.cpp +0 -0
  47. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gpu_cuda/gpu.hpp +0 -0
  48. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/gpu_cuda/gpu_capi.cpp +0 -0
  49. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/lasso_cov.cpp +0 -0
  50. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/lasso_cov.hpp +0 -0
  51. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/lasso_cov_capi.cpp +0 -0
  52. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_blas/nmf_cd.cpp +0 -0
  53. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_blas/nmf_cd_capi.cpp +0 -0
  54. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_cublas/nmf_cd.cpp +0 -0
  55. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_cublas/nmf_cd_capi.cpp +0 -0
  56. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_loops/nmf_cd.cpp +0 -0
  57. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/nmf_loops/nmf_cd_capi.cpp +0 -0
  58. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/scm2cpp-blas.hpp +0 -0
  59. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/scm2cpp-cublas.hpp +0 -0
  60. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/scm2cpp-cuda.hpp +0 -0
  61. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_generated/scm2cpp.hpp +0 -0
  62. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/_libfind.py +0 -0
  63. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn/batch_capi.cu +0 -0
  64. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn.egg-info/SOURCES.txt +0 -0
  65. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn.egg-info/dependency_links.txt +0 -0
  66. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn.egg-info/requires.txt +0 -0
  67. {scm2cpp_learn-0.18.0 → scm2cpp_learn-0.19.0}/src/scm2cpp_learn.egg-info/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scm2cpp-learn
3
- Version: 0.18.0
4
- Summary: scikit-learn estimators (lasso, elastic net, ridge, RidgeCV, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, KernelPCA, LDA, TruncatedSVD, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver and CUDA kernels included
3
+ Version: 0.19.0
4
+ Summary: scikit-learn estimators (lasso, elastic net, ridge, RidgeCV, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, KernelPCA, LDA, TruncatedSVD, PLS, CCA, 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
@@ -257,6 +257,7 @@ package picks the fastest one present.
257
257
  | `GramKernelPCA` | KernelPCA (no inverse_transform) | `kernel-pca.scm` | loops / BLAS | no |
258
258
  | `GramLDA` | LinearDiscriminantAnalysis (svd, lsqr, eigen) | `lda.scm` | loops / BLAS | no |
259
259
  | `GramTruncatedSVD` | TruncatedSVD on dense X (exact, as arpack) | `truncated-svd.scm` | loops / BLAS | no |
260
+ | `GramPLSRegression`, `GramPLSCanonical`, `GramCCA`, `GramPLSSVD` | PLSRegression, PLSCanonical, CCA, PLSSVD | `pls.scm` | loops / BLAS | no |
260
261
  | `f_regression, f_classif` | f_regression, f_classif | `fscore.scm` | loops / BLAS / cuBLAS | no |
261
262
  | `SelectKBest, SelectPercentile` | SelectKBest, SelectPercentile | `fscore.scm` | loops / BLAS / cuBLAS | no |
262
263
  | `GramRFE` | RFE(Ridge), RFE(LinearRegression) | `rfe.scm` | loops / BLAS / cuBLAS | inside: Ridge |
@@ -714,6 +715,48 @@ The exact route costs O(n p^2 + p^3); with few components of many
714
715
  features (2,000 here) the randomized one does less work, and on one core
715
716
  it is faster, at its accuracy. Sparse X is not taken yet.
716
717
 
718
+ ## PLS and CCA: `GramPLSRegression`, `GramPLSCanonical`, `GramCCA`, `GramPLSSVD`
719
+
720
+ scikit-learn's `cross_decomposition` estimators over the cross products
721
+ (`examples/kernel-only/pls.scm`). NIPALS multiplies the blocks only by
722
+ weight vectors, and each such product is one of Cxx = X'X, Cxy = X'Y,
723
+ Cyy = Y'Y times a vector: the Y score is Y c for a coefficient vector c,
724
+ so X'(Y c) = Cxy c. The deflations are rank-one updates of the three
725
+ matrices (with a = Cxx w, b = Cxy'w and s2 = w'Cxx w, regression mode is
726
+ Cxx -= a a'/s2, Cxy -= a b'/s2, Cyy -= b b'/s2). So X and Y are read
727
+ once, for the three products (dsyrk and dgemm), and every power
728
+ iteration after that costs O(p^2 + pq + q^2) where scikit-learn's costs
729
+ O(n(p + q)). CCA's mode B takes pinv(X) y = Cxx^+ X'y, Cxx^+ from its
730
+ eigenproblem; PLSSVD is the SVD of Cxy.
731
+
732
+ ```python
733
+ from scm2cpp_learn import GramPLSRegression, GramCCA
734
+ pls = GramPLSRegression(n_components=5).fit(X, Y)
735
+ pls.predict(X), pls.transform(X), pls.x_scores_
736
+ ```
737
+
738
+ Weights, loadings, rotations, coefficients, scores and transforms agree
739
+ with scikit-learn's to 1e-13, with the same iteration counts. One cut
740
+ differs: a deflated block loses a rank exactly, which its SVD shows as a
741
+ singular value near eps but its Gram as an eigenvalue near eps
742
+ lam_max, so mode B's pinv also drops eigenvalues under 1e3 eps lam_max
743
+ (singular values under about 5e-7 of the largest, where scikit-learn's
744
+ cut is 2.2e-10). Measured (`bench/eigen-compare.py`, the MKL build, best
745
+ of three):
746
+
747
+ | case | scikit-learn | package | ratio, one core | ratio, 20 cores |
748
+ |---|---|---|---|---|
749
+ | PLSRegression, 200,000 x 100 -> 5, 5 components | 5.64 s | 0.26 s | 21x | 19x |
750
+ | PLSCanonical, 200,000 x 100 -> 5, 5 components | 5.63 s | 0.14 s | 40x | 59x |
751
+ | CCA, 200,000 x 100 -> 5, 5 components | 31.9 s | 0.14 s | 220x | 190x |
752
+ | PLSSVD, 200,000 x 100 -> 5, 5 components | 0.28 s | 0.14 s | 2.0x | 4.0x |
753
+ | PLSRegression, 50,000 x 500 -> 10, 10 components | 45.5 s | 0.75 s | 61x | 57x |
754
+ | PLSCanonical, 50,000 x 500 -> 10, 10 components | 45.3 s | 0.60 s | 76x | 100x |
755
+ | CCA, 50,000 x 500 -> 10, 10 components | 132 s | 1.21 s | 109x | 151x |
756
+ | PLSSVD, 50,000 x 500 -> 10, 10 components | 0.34 s | 0.34 s | 1.0x | 3.4x |
757
+
758
+ PLSSVD is one SVD of X'Y on both sides, so only the product differs.
759
+
717
760
  ## Bayesian ridge
718
761
 
719
762
  `CovBayesianRidge` is scikit-learn's `BayesianRidge` -- the same model,
@@ -1,21 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: scm2cpp-learn
3
- Version: 0.18.0
4
- Summary: scikit-learn estimators (lasso, elastic net, ridge, RidgeCV, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, KernelPCA, LDA, TruncatedSVD, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver and CUDA kernels 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-learn
9
- Keywords: scikit-learn,lasso,elastic-net,ridge,svm,logistic-regression,pca,lda,coordinate-descent,lapack,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-learn
20
2
 
21
3
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/niitsuma/scm2cpp/blob/master/notebooks/compare-sklearn.ipynb)
@@ -257,6 +239,7 @@ package picks the fastest one present.
257
239
  | `GramKernelPCA` | KernelPCA (no inverse_transform) | `kernel-pca.scm` | loops / BLAS | no |
258
240
  | `GramLDA` | LinearDiscriminantAnalysis (svd, lsqr, eigen) | `lda.scm` | loops / BLAS | no |
259
241
  | `GramTruncatedSVD` | TruncatedSVD on dense X (exact, as arpack) | `truncated-svd.scm` | loops / BLAS | no |
242
+ | `GramPLSRegression`, `GramPLSCanonical`, `GramCCA`, `GramPLSSVD` | PLSRegression, PLSCanonical, CCA, PLSSVD | `pls.scm` | loops / BLAS | no |
260
243
  | `f_regression, f_classif` | f_regression, f_classif | `fscore.scm` | loops / BLAS / cuBLAS | no |
261
244
  | `SelectKBest, SelectPercentile` | SelectKBest, SelectPercentile | `fscore.scm` | loops / BLAS / cuBLAS | no |
262
245
  | `GramRFE` | RFE(Ridge), RFE(LinearRegression) | `rfe.scm` | loops / BLAS / cuBLAS | inside: Ridge |
@@ -714,6 +697,48 @@ The exact route costs O(n p^2 + p^3); with few components of many
714
697
  features (2,000 here) the randomized one does less work, and on one core
715
698
  it is faster, at its accuracy. Sparse X is not taken yet.
716
699
 
700
+ ## PLS and CCA: `GramPLSRegression`, `GramPLSCanonical`, `GramCCA`, `GramPLSSVD`
701
+
702
+ scikit-learn's `cross_decomposition` estimators over the cross products
703
+ (`examples/kernel-only/pls.scm`). NIPALS multiplies the blocks only by
704
+ weight vectors, and each such product is one of Cxx = X'X, Cxy = X'Y,
705
+ Cyy = Y'Y times a vector: the Y score is Y c for a coefficient vector c,
706
+ so X'(Y c) = Cxy c. The deflations are rank-one updates of the three
707
+ matrices (with a = Cxx w, b = Cxy'w and s2 = w'Cxx w, regression mode is
708
+ Cxx -= a a'/s2, Cxy -= a b'/s2, Cyy -= b b'/s2). So X and Y are read
709
+ once, for the three products (dsyrk and dgemm), and every power
710
+ iteration after that costs O(p^2 + pq + q^2) where scikit-learn's costs
711
+ O(n(p + q)). CCA's mode B takes pinv(X) y = Cxx^+ X'y, Cxx^+ from its
712
+ eigenproblem; PLSSVD is the SVD of Cxy.
713
+
714
+ ```python
715
+ from scm2cpp_learn import GramPLSRegression, GramCCA
716
+ pls = GramPLSRegression(n_components=5).fit(X, Y)
717
+ pls.predict(X), pls.transform(X), pls.x_scores_
718
+ ```
719
+
720
+ Weights, loadings, rotations, coefficients, scores and transforms agree
721
+ with scikit-learn's to 1e-13, with the same iteration counts. One cut
722
+ differs: a deflated block loses a rank exactly, which its SVD shows as a
723
+ singular value near eps but its Gram as an eigenvalue near eps
724
+ lam_max, so mode B's pinv also drops eigenvalues under 1e3 eps lam_max
725
+ (singular values under about 5e-7 of the largest, where scikit-learn's
726
+ cut is 2.2e-10). Measured (`bench/eigen-compare.py`, the MKL build, best
727
+ of three):
728
+
729
+ | case | scikit-learn | package | ratio, one core | ratio, 20 cores |
730
+ |---|---|---|---|---|
731
+ | PLSRegression, 200,000 x 100 -> 5, 5 components | 5.64 s | 0.26 s | 21x | 19x |
732
+ | PLSCanonical, 200,000 x 100 -> 5, 5 components | 5.63 s | 0.14 s | 40x | 59x |
733
+ | CCA, 200,000 x 100 -> 5, 5 components | 31.9 s | 0.14 s | 220x | 190x |
734
+ | PLSSVD, 200,000 x 100 -> 5, 5 components | 0.28 s | 0.14 s | 2.0x | 4.0x |
735
+ | PLSRegression, 50,000 x 500 -> 10, 10 components | 45.5 s | 0.75 s | 61x | 57x |
736
+ | PLSCanonical, 50,000 x 500 -> 10, 10 components | 45.3 s | 0.60 s | 76x | 100x |
737
+ | CCA, 50,000 x 500 -> 10, 10 components | 132 s | 1.21 s | 109x | 151x |
738
+ | PLSSVD, 50,000 x 500 -> 10, 10 components | 0.34 s | 0.34 s | 1.0x | 3.4x |
739
+
740
+ PLSSVD is one SVD of X'Y on both sides, so only the product differs.
741
+
717
742
  ## Bayesian ridge
718
743
 
719
744
  `CovBayesianRidge` is scikit-learn's `BayesianRidge` -- the same model,
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "scm2cpp-learn"
7
- version = "0.18.0"
8
- description = "scikit-learn estimators (lasso, elastic net, ridge, RidgeCV, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, KernelPCA, LDA, TruncatedSVD, graphical lasso, RANSAC, SGD, OMP, LARS) translated from Scheme to C++ by scm2cpp; GPU batch solver and CUDA kernels included"
7
+ version = "0.19.0"
8
+ description = "scikit-learn estimators (lasso, elastic net, ridge, RidgeCV, ARD, SVM, SVR, logistic regression, GLMs, Huber, Theil-Sen, F-score selection, RFE, NMF, Gaussian mixture, FastICA, PCA, KernelPCA, LDA, TruncatedSVD, PLS, CCA, 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"}
@@ -50,14 +50,14 @@ __all__ = ["GramLasso", "GramElasticNet", "GramRidge", "GramRidgeCV", "CovLasso"
50
50
  "LBFGSLogisticRegression", "LBFGSHuberRegressor", "LBFGSLogisticRegressionCV",
51
51
  "LBFGSPoissonRegressor", "LBFGSGammaRegressor", "LBFGSTweedieRegressor",
52
52
  "GramLarsCV", "GramLassoLarsCV", "GramOMPCV",
53
- "EMGaussianMixture", "CovPCA", "GramKernelPCA", "GramLDA", "GramTruncatedSVD", "ParallelFastICA", "CovARDRegression",
53
+ "EMGaussianMixture", "CovPCA", "GramKernelPCA", "GramLDA", "GramTruncatedSVD", "GramPLSRegression", "GramPLSCanonical", "GramCCA", "GramPLSSVD", "ParallelFastICA", "CovARDRegression",
54
54
  "L1LinearSVM", "WeiszfeldTheilSen", "f_regression", "f_classif", "SelectKBest",
55
55
  "SelectPercentile", "GramRFE",
56
56
  "CovMultiTaskLasso", "CovMultiTaskLassoCV", "DerivedLasso",
57
57
  "GramLogisticRegression", "GramGroupLasso", "GramMultiTaskLasso",
58
58
  "GramMultiTaskElasticNet", "DesignLasso",
59
59
  "cuda_available", "derived_backend", "kernel"]
60
- __version__ = "0.18.0"
60
+ __version__ = "0.19.0"
61
61
 
62
62
  _BATCH = load_batch_lib()
63
63
  _DP = ctypes.POINTER(ctypes.c_double)
@@ -837,7 +837,10 @@ class GramRidgeCV(Tagged, RegressorMixin, BaseEstimator):
837
837
  and diag H and yhat at every alpha are two products. Z comes from
838
838
  the eigenvectors of Xc'Xc (``gcv_mode="svd"``, the default when
839
839
  n > p, X'X by dsyrk) or of Xc Xc' (``"eigen"``, the default
840
- otherwise); the eigenproblem is LAPACK's dsyevd where the BLAS
840
+ otherwise; as scikit-learn's, it takes e = c / diag G^-1 for
841
+ c = G^-1 y, G = Xc Xc' + 11' + alpha I with the intercept's
842
+ eigenvalue unpenalised, so that a small alpha, where H tends to I,
843
+ loses no digits to 1 - diag H); the eigenproblem is LAPACK's dsyevd where the BLAS
841
844
  build is here. Only ``cv=None`` and ``scoring=None`` are taken.
842
845
 
843
846
  Attributes after fit: alpha_, best_score_ (minus the mean squared
@@ -890,14 +893,19 @@ class GramRidgeCV(Tagged, RegressorMixin, BaseEstimator):
890
893
  else:
891
894
  Xc = np.ascontiguousarray(X - xm)
892
895
  K = _gram(np.ascontiguousarray(Xc.T))
893
- m = n
894
- V, lam, Z, R = np.zeros((n, n)), np.zeros(n), np.zeros((n, n)), np.zeros((n, t))
895
- k.ridge_gcv_dual(K, V, lam, yc, Z, R, n, t)
896
+ if self.fit_intercept:
897
+ K += 1.0
898
+ V, lam, R = np.zeros((n, n)), np.zeros(n), np.zeros((n, t))
899
+ drop = k.ridge_gcv_dual(K, V, lam, yc, R, n, t, int(bool(self.fit_intercept)))
896
900
  na = alphas.size
897
901
  mse = np.zeros((na, t))
898
902
  loo = np.zeros((n, t, na)) if self.store_cv_results else np.zeros(1)
899
- k.ridge_gcv_scan(Z, lam, R, yc, alphas, 1.0 / n if self.fit_intercept else 0.0,
900
- mse, loo, int(bool(self.store_cv_results)), n, m, t, na)
903
+ store = int(bool(self.store_cv_results))
904
+ if mode == "svd":
905
+ k.ridge_gcv_scan(Z, lam, R, yc, alphas, 1.0 / n if self.fit_intercept else 0.0,
906
+ mse, loo, store, n, m, t, na)
907
+ else:
908
+ k.ridge_gcv_scan_dual(V, lam, R, alphas, drop, mse, loo, store, n, t, na)
901
909
  if self.alpha_per_target and t > 1:
902
910
  best = np.argmin(mse, axis=0)
903
911
  al = alphas[best]
@@ -911,9 +919,12 @@ class GramRidgeCV(Tagged, RegressorMixin, BaseEstimator):
911
919
  if mode == "svd":
912
920
  coef = V @ (R / (lam[:, None] + al[None, :]))
913
921
  else:
914
- # (Xc Xc' + alpha I)^-1 yc by the eigenvectors, then Xc' of it
915
- qy = V.T @ yc
916
- coef = Xc.T @ (V @ (qy / (lam[:, None] + al[None, :])))
922
+ # (Xc Xc' + alpha I)^-1 yc by the eigenvectors, then Xc' of
923
+ # it; yc has no part along 1, so the 11' added changes nothing
924
+ w = 1.0 / (lam[:, None] + al[None, :])
925
+ if drop >= 0:
926
+ w[drop] = 0.0
927
+ coef = Xc.T @ (V @ (R * w))
917
928
  if y.ndim == 1:
918
929
  self.coef_ = coef[:, 0]
919
930
  self.intercept_ = float(ym[0] - xm @ coef[:, 0])
@@ -2259,6 +2270,17 @@ class GramKernelPCA(Tagged, TransformerMixin, BaseEstimator):
2259
2270
  return K @ scaled
2260
2271
 
2261
2272
 
2273
+ def _lda_svd_dof(n, K):
2274
+ # the divisor of LinearDiscriminantAnalysis's svd solver: n from
2275
+ # scikit-learn 1.9.1, n - K before; n without scikit-learn
2276
+ try:
2277
+ import sklearn
2278
+ v = tuple(int(x) for x in sklearn.__version__.split(".")[:3] if x.isdigit())
2279
+ except Exception:
2280
+ return n
2281
+ return n - K if v < (1, 9, 1) else n
2282
+
2283
+
2262
2284
  class GramLDA(Tagged, ClassifierMixin, TransformerMixin, BaseEstimator):
2263
2285
  """scikit-learn's ``LinearDiscriminantAnalysis`` over the Gram matrix
2264
2286
  (``examples/kernel-only/lda.scm``): X'X by dsyrk and the class means
@@ -2353,6 +2375,10 @@ class GramLDA(Tagged, ClassifierMixin, TransformerMixin, BaseEstimator):
2353
2375
  self.xbar_ = priors @ means
2354
2376
  std, V, S = np.zeros(p), np.zeros((p, p)), np.zeros(p)
2355
2377
  k.lda_svd_first(np.ascontiguousarray(Sw_emp), std, V, S, p)
2378
+ # S is the SVD of Xc D^-1 / sqrt(n); scikit-learn before 1.9.1
2379
+ # divides by sqrt(n - K) instead (#33626), and its tol and
2380
+ # scalings_ see that scale
2381
+ S *= np.sqrt(n / _lda_svd_dof(n, K))
2356
2382
  rank = int(np.sum(S > self.tol))
2357
2383
  scal = (V[:, :rank] / std[:, None]) / S[:rank]
2358
2384
  fac = 1.0 if K == 1 else 1.0 / (K - 1)
@@ -2481,6 +2507,226 @@ class GramTruncatedSVD(Tagged, TransformerMixin, BaseEstimator):
2481
2507
  return np.asarray(X) @ self.components_
2482
2508
 
2483
2509
 
2510
+ def _pls_moments(X, Y, scale):
2511
+ """Centred (and, with scale, standardised) Cxx, Cxy, Cyy, with the
2512
+ means and deviations: from X'X, X'Y and Y'Y less the n m m' terms,
2513
+ the centred copies only when a column's mean dwarfs its spread (the
2514
+ correction would cancel its digits)."""
2515
+ n = X.shape[0]
2516
+ xm, ym = X.mean(axis=0), Y.mean(axis=0)
2517
+ Gxx, Gxy, Gyy = _gram(X), _gram_xy(X, Y), _gram(np.ascontiguousarray(Y))
2518
+ Gxy = Gxy.reshape(X.shape[1], Y.shape[1])
2519
+ nx, ny = n * xm * xm, n * ym * ym
2520
+ if np.all(np.diagonal(Gxx) - nx > 1e-4 * nx) and np.all(np.diagonal(Gyy) - ny > 1e-4 * ny):
2521
+ Cxx = Gxx - np.outer(xm, n * xm)
2522
+ Cxy = Gxy - np.outer(xm, n * ym)
2523
+ Cyy = Gyy - np.outer(ym, n * ym)
2524
+ else:
2525
+ Xc, Yc = np.ascontiguousarray(X - xm), np.ascontiguousarray(Y - ym)
2526
+ Cxx, Cyy = _gram(Xc), _gram(Yc)
2527
+ Cxy = _gram_xy(Xc, Yc).reshape(X.shape[1], Y.shape[1])
2528
+ if scale:
2529
+ xs = np.sqrt(np.maximum(np.diagonal(Cxx), 0.0) / (n - 1))
2530
+ ys = np.sqrt(np.maximum(np.diagonal(Cyy), 0.0) / (n - 1))
2531
+ xs[xs == 0.0] = 1.0
2532
+ ys[ys == 0.0] = 1.0
2533
+ Cxx = Cxx / np.outer(xs, xs)
2534
+ Cxy = Cxy / np.outer(xs, ys)
2535
+ Cyy = Cyy / np.outer(ys, ys)
2536
+ else:
2537
+ xs, ys = np.ones(X.shape[1]), np.ones(Y.shape[1])
2538
+ return (np.ascontiguousarray(Cxx), np.ascontiguousarray(Cxy), np.ascontiguousarray(Cyy),
2539
+ xm, ym, xs, ys)
2540
+
2541
+
2542
+ class _GramPLS(Tagged, TransformerMixin, BaseEstimator):
2543
+ # scikit-learn's _PLS over the cross products (examples/kernel-only/pls.scm)
2544
+ _multi_output = True
2545
+ _mode, _canon = 0, 0
2546
+
2547
+ def fit(self, X, y):
2548
+ X, y = fit_xy(self, X, y, multi_output=True)
2549
+ n, p = X.shape
2550
+ if n < 2:
2551
+ raise ValueError(f"Found array with {n} sample(s) (shape={X.shape}) while a "
2552
+ "minimum of 2 is required.")
2553
+ self._predict_1d = y.ndim == 1
2554
+ Y = y.reshape(n, -1)
2555
+ q = Y.shape[1]
2556
+ k = int(self.n_components)
2557
+ upper = min(n, p) if not self._canon else min(n, p, q)
2558
+ if not 1 <= k <= upper:
2559
+ raise ValueError(f"`n_components` upper bound is {upper}. Got {k} instead. "
2560
+ "Reduce `n_components`.")
2561
+ algo = 1 if getattr(self, "algorithm", "nipals") == "svd" else 0
2562
+ Cxx, Cxy, Cyy, self._x_mean, self._y_mean, self._x_std, self._y_std = \
2563
+ _pls_moments(X, Y, self.scale)
2564
+ xw, yw = np.zeros((p, k)), np.zeros((q, k))
2565
+ xl, yl = np.zeros((p, k)), np.zeros((q, k))
2566
+ niter = np.zeros(k, dtype=np.int32)
2567
+ found = _gramops_kernels().pls_fit(Cxx, Cxy, Cyy, xw, yw, xl, yl, niter, p, q, k,
2568
+ self._mode, self._canon, algo,
2569
+ int(self.max_iter), float(self.tol))
2570
+ if found < k:
2571
+ warnings.warn(f"y residual is constant at iteration {found}")
2572
+ # scikit-learn keeps the list empty for the svd algorithm
2573
+ self.n_iter_ = [int(t) for t in niter[:found]] if algo == 0 else []
2574
+ if algo == 0:
2575
+ if any(t == int(self.max_iter) for t in self.n_iter_):
2576
+ warnings.warn("Maximum number of iterations reached", UserWarning)
2577
+ self.x_weights_, self.y_weights_ = xw, yw
2578
+ self.x_loadings_, self.y_loadings_ = xl, yl
2579
+ self.x_rotations_ = xw @ np.linalg.pinv(xl.T @ xw)
2580
+ self.y_rotations_ = yw @ np.linalg.pinv(yl.T @ yw)
2581
+ coef = self.x_rotations_ @ yl.T
2582
+ self.coef_ = (coef * self._y_std).T / self._x_std
2583
+ self.intercept_ = self._y_mean
2584
+ self._n_features_out = k
2585
+ self._X, self._Y = X, Y
2586
+ return self
2587
+
2588
+ def transform(self, X, y=None, copy=True):
2589
+ check_is_fitted(self)
2590
+ Xs = (pred_x(self, X) - self._x_mean) / self._x_std
2591
+ xs = Xs @ self.x_rotations_
2592
+ if y is None:
2593
+ return xs
2594
+ Y = np.asarray(y, dtype=np.float64)
2595
+ Y = Y.reshape(-1, 1) if Y.ndim == 1 else Y
2596
+ return xs, ((Y - self._y_mean) / self._y_std) @ self.y_rotations_
2597
+
2598
+ def fit_transform(self, X, y=None):
2599
+ return self.fit(X, y).transform(X, y)
2600
+
2601
+ def inverse_transform(self, X, y=None):
2602
+ check_is_fitted(self)
2603
+ Xr = np.asarray(X, dtype=np.float64) @ self.x_loadings_.T * self._x_std + self._x_mean
2604
+ if y is None:
2605
+ return Xr
2606
+ Yr = np.asarray(y, dtype=np.float64) @ self.y_loadings_.T * self._y_std + self._y_mean
2607
+ return Xr, Yr
2608
+
2609
+ def predict(self, X, copy=True):
2610
+ check_is_fitted(self)
2611
+ yp = (pred_x(self, X) - self._x_mean) @ self.coef_.T + self.intercept_
2612
+ return yp.ravel() if self._predict_1d else yp
2613
+
2614
+
2615
+ class GramPLSRegression(RegressorMixin, _GramPLS):
2616
+ """scikit-learn's ``PLSRegression`` over the cross products
2617
+ (``examples/kernel-only/pls.scm``): X'X (dsyrk), X'Y and Y'Y once,
2618
+ then NIPALS and the regression deflation as products and rank-one
2619
+ updates of those p x p, p x q and q x q matrices, never the n rows
2620
+ again. The scores x_scores_ = X R and y_scores_ (Y less the earlier
2621
+ components' X scores, times the Y weights) are formed at the end.
2622
+
2623
+ Attributes after fit: x_weights_, y_weights_, x_loadings_,
2624
+ y_loadings_, x_rotations_, y_rotations_, x_scores_, y_scores_,
2625
+ coef_, intercept_, n_iter_, n_features_in_.
2626
+ """
2627
+ _mode, _canon = 0, 0
2628
+
2629
+ def __init__(self, n_components=2, *, scale=True, max_iter=500, tol=1e-06, copy=True):
2630
+ self.n_components, self.scale, self.max_iter = n_components, scale, max_iter
2631
+ self.tol, self.copy = tol, copy
2632
+
2633
+ def fit(self, X, y):
2634
+ super().fit(X, y)
2635
+ Xs = (self._X - self._x_mean) / self._x_std
2636
+ Ys = (self._Y - self._y_mean) / self._y_std
2637
+ T = Xs @ self.x_rotations_
2638
+ U = Ys @ self.y_weights_
2639
+ for k in range(U.shape[1]):
2640
+ # Y deflated by the earlier components' X scores (regression mode)
2641
+ U[:, k] -= T[:, :k] @ (self.y_loadings_[:, :k].T @ self.y_weights_[:, k])
2642
+ U[:, k] /= self.y_weights_[:, k] @ self.y_weights_[:, k]
2643
+ self.x_scores_, self.y_scores_ = T, U
2644
+ del self._X, self._Y
2645
+ return self
2646
+
2647
+ def fit_transform(self, X, y=None):
2648
+ return self.fit(X, y).transform(X, y)
2649
+
2650
+
2651
+ class GramPLSCanonical(_GramPLS):
2652
+ """scikit-learn's ``PLSCanonical`` (canonical deflation, mode A,
2653
+ ``algorithm`` "nipals" or "svd") over the cross products, as
2654
+ ``GramPLSRegression``."""
2655
+ _mode, _canon = 0, 1
2656
+
2657
+ def __init__(self, n_components=2, *, scale=True, algorithm="nipals", max_iter=500,
2658
+ tol=1e-06, copy=True):
2659
+ self.n_components, self.scale, self.algorithm = n_components, scale, algorithm
2660
+ self.max_iter, self.tol, self.copy = max_iter, tol, copy
2661
+
2662
+ def fit(self, X, y):
2663
+ if self.algorithm not in ("nipals", "svd"):
2664
+ raise ValueError(f"algorithm={self.algorithm!r}: expected 'nipals' or 'svd'")
2665
+ super().fit(X, y)
2666
+ del self._X, self._Y
2667
+ return self
2668
+
2669
+
2670
+ class GramCCA(_GramPLS):
2671
+ """scikit-learn's ``CCA`` (canonical deflation, mode B: pinv of each
2672
+ block from the eigenproblem of its Gram, cut where _pinv2_old cuts)
2673
+ over the cross products, as ``GramPLSRegression``."""
2674
+ _mode, _canon = 1, 1
2675
+
2676
+ def __init__(self, n_components=2, *, scale=True, max_iter=500, tol=1e-06, copy=True):
2677
+ self.n_components, self.scale, self.max_iter = n_components, scale, max_iter
2678
+ self.tol, self.copy = tol, copy
2679
+
2680
+ def fit(self, X, y):
2681
+ super().fit(X, y)
2682
+ del self._X, self._Y
2683
+ return self
2684
+
2685
+
2686
+ class GramPLSSVD(Tagged, TransformerMixin, BaseEstimator):
2687
+ """scikit-learn's ``PLSSVD``: the SVD of the centred (scaled) X'Y,
2688
+ formed from X'Y less n mx my' instead of from centred copies."""
2689
+ _multi_output = True
2690
+
2691
+ def __init__(self, n_components=2, *, scale=True, copy=True):
2692
+ self.n_components, self.scale, self.copy = n_components, scale, copy
2693
+
2694
+ def fit(self, X, y):
2695
+ X, y = fit_xy(self, X, y, multi_output=True)
2696
+ n, p = X.shape
2697
+ if n < 2:
2698
+ raise ValueError(f"Found array with {n} sample(s) (shape={X.shape}) while a "
2699
+ "minimum of 2 is required.")
2700
+ Y = y.reshape(n, -1)
2701
+ k = int(self.n_components)
2702
+ upper = min(n, p, Y.shape[1])
2703
+ if not 1 <= k <= upper:
2704
+ raise ValueError(f"`n_components` upper bound is {upper}. Got {k} instead. "
2705
+ "Reduce `n_components`.")
2706
+ _, C, _, self._x_mean, self._y_mean, self._x_std, self._y_std = \
2707
+ _pls_moments(X, Y, self.scale)
2708
+ U, _, Vt = np.linalg.svd(C, full_matrices=False)
2709
+ U, Vt = U[:, :k], Vt[:k]
2710
+ # svd_flip, u-based: each column of U's largest entry positive
2711
+ sg = np.sign(U[np.argmax(np.abs(U), axis=0), np.arange(k)])
2712
+ sg[sg == 0] = 1.0
2713
+ self.x_weights_, self.y_weights_ = U * sg, (Vt * sg[:, None]).T
2714
+ self._n_features_out = k
2715
+ return self
2716
+
2717
+ def transform(self, X, y=None):
2718
+ check_is_fitted(self)
2719
+ xs = ((pred_x(self, X) - self._x_mean) / self._x_std) @ self.x_weights_
2720
+ if y is None:
2721
+ return xs
2722
+ Y = np.asarray(y, dtype=np.float64)
2723
+ Y = Y.reshape(-1, 1) if Y.ndim == 1 else Y
2724
+ return xs, ((Y - self._y_mean) / self._y_std) @ self.y_weights_
2725
+
2726
+ def fit_transform(self, X, y=None):
2727
+ return self.fit(X, y).transform(X, y)
2728
+
2729
+
2484
2730
  class ParallelFastICA(Tagged, TransformerMixin, BaseEstimator):
2485
2731
  """FastICA, scikit-learn's ``FastICA`` at its defaults translated
2486
2732
  whole (``examples/kernel-only/fastica.scm``: algorithm="parallel",
@@ -522,15 +522,25 @@ def ridge_gcv_primal(x, xm, yc, g, v, lam, z, r, n, p, t):
522
522
  return _lib.scm2cpp_ridge_gcv_primal(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), xm.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), yc.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), g.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), v.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), lam.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), z.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), r.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, p, t)
523
523
 
524
524
  _lib.scm2cpp_ridge_gcv_dual.restype = ctypes.c_int
525
- _lib.scm2cpp_ridge_gcv_dual.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.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
526
- def ridge_gcv_dual(k, q, mu, yc, z, r, n, t):
525
+ _lib.scm2cpp_ridge_gcv_dual.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, ctypes.c_int]
526
+ def ridge_gcv_dual(k, q, mu, yc, r, n, t, icpt):
527
527
  k = np.ascontiguousarray(k, dtype=np.float64)
528
528
  q = np.ascontiguousarray(q, dtype=np.float64)
529
529
  mu = np.ascontiguousarray(mu, dtype=np.float64)
530
530
  yc = np.ascontiguousarray(yc, dtype=np.float64)
531
- z = np.ascontiguousarray(z, dtype=np.float64)
532
531
  r = np.ascontiguousarray(r, dtype=np.float64)
533
- return _lib.scm2cpp_ridge_gcv_dual(k.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), q.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), mu.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), yc.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), z.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), r.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, t)
532
+ return _lib.scm2cpp_ridge_gcv_dual(k.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), q.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), mu.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), yc.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), r.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, t, icpt)
533
+
534
+ _lib.scm2cpp_ridge_gcv_scan_dual.restype = ctypes.c_int
535
+ _lib.scm2cpp_ridge_gcv_scan_dual.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.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
536
+ def ridge_gcv_scan_dual(q, mu, r, alphas, drop, mse, loo, store, n, t, na):
537
+ q = np.ascontiguousarray(q, dtype=np.float64)
538
+ mu = np.ascontiguousarray(mu, dtype=np.float64)
539
+ r = np.ascontiguousarray(r, dtype=np.float64)
540
+ alphas = np.ascontiguousarray(alphas, dtype=np.float64)
541
+ mse = np.ascontiguousarray(mse, dtype=np.float64)
542
+ loo = np.ascontiguousarray(loo, dtype=np.float64)
543
+ return _lib.scm2cpp_ridge_gcv_scan_dual(q.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), mu.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), r.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), alphas.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), drop, mse.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), loo.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), store, n, t, na)
534
544
 
535
545
  _lib.scm2cpp_ridge_gcv_scan.restype = ctypes.c_int
536
546
  _lib.scm2cpp_ridge_gcv_scan.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_double, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
@@ -690,3 +700,73 @@ def tsvd_wide(x, v, s, z, n, p, k):
690
700
  z = np.ascontiguousarray(z, dtype=np.float64)
691
701
  return _lib.scm2cpp_tsvd_wide(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), v.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), s.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), z.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), n, p, k)
692
702
 
703
+ _lib.scm2cpp_svd_jacobi.restype = ctypes.c_int
704
+ _lib.scm2cpp_svd_jacobi.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
705
+ def svd_jacobi(w, q, r, c):
706
+ w = np.ascontiguousarray(w, dtype=np.float64)
707
+ q = np.ascontiguousarray(q, dtype=np.float64)
708
+ return _lib.scm2cpp_svd_jacobi(w.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), q.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), r, c)
709
+
710
+ _lib.scm2cpp_svd_collect.restype = ctypes.c_int
711
+ _lib.scm2cpp_svd_collect.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.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int]
712
+ def svd_collect(w, q, s, l, rr, ord, r, c):
713
+ w = np.ascontiguousarray(w, dtype=np.float64)
714
+ q = np.ascontiguousarray(q, dtype=np.float64)
715
+ s = np.ascontiguousarray(s, dtype=np.float64)
716
+ l = np.ascontiguousarray(l, dtype=np.float64)
717
+ rr = np.ascontiguousarray(rr, dtype=np.float64)
718
+ ord = np.ascontiguousarray(ord, dtype=np.int32)
719
+ return _lib.scm2cpp_svd_collect(w.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), q.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), s.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), l.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), rr.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), ord.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), r, c)
720
+
721
+ _lib.scm2cpp_sym_svd.restype = ctypes.c_int
722
+ _lib.scm2cpp_sym_svd.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]
723
+ def sym_svd(a, u, s, vt, m, n):
724
+ a = np.ascontiguousarray(a, dtype=np.float64)
725
+ u = np.ascontiguousarray(u, dtype=np.float64)
726
+ s = np.ascontiguousarray(s, dtype=np.float64)
727
+ vt = np.ascontiguousarray(vt, dtype=np.float64)
728
+ return _lib.scm2cpp_sym_svd(a.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), u.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), s.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), vt.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m, n)
729
+
730
+ _lib.scm2cpp_pls_pinv.restype = ctypes.c_int
731
+ _lib.scm2cpp_pls_pinv.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int]
732
+ def pls_pinv(a, pv, m):
733
+ a = np.ascontiguousarray(a, dtype=np.float64)
734
+ pv = np.ascontiguousarray(pv, dtype=np.float64)
735
+ return _lib.scm2cpp_pls_pinv(a.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), pv.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m)
736
+
737
+ _lib.scm2cpp_pls_mv.restype = ctypes.c_int
738
+ _lib.scm2cpp_pls_mv.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
739
+ def pls_mv(a, x, y, m, n):
740
+ a = np.ascontiguousarray(a, dtype=np.float64)
741
+ x = np.ascontiguousarray(x, dtype=np.float64)
742
+ y = np.ascontiguousarray(y, dtype=np.float64)
743
+ return _lib.scm2cpp_pls_mv(a.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), y.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m, n)
744
+
745
+ _lib.scm2cpp_pls_mtv.restype = ctypes.c_int
746
+ _lib.scm2cpp_pls_mtv.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
747
+ def pls_mtv(a, x, y, m, n):
748
+ a = np.ascontiguousarray(a, dtype=np.float64)
749
+ x = np.ascontiguousarray(x, dtype=np.float64)
750
+ y = np.ascontiguousarray(y, dtype=np.float64)
751
+ return _lib.scm2cpp_pls_mtv(a.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), y.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m, n)
752
+
753
+ _lib.scm2cpp_pls_dot.restype = ctypes.c_double
754
+ _lib.scm2cpp_pls_dot.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_int]
755
+ def pls_dot(x, y, m):
756
+ x = np.ascontiguousarray(x, dtype=np.float64)
757
+ y = np.ascontiguousarray(y, dtype=np.float64)
758
+ return _lib.scm2cpp_pls_dot(x.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), y.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), m)
759
+
760
+ _lib.scm2cpp_pls_fit.restype = ctypes.c_int
761
+ _lib.scm2cpp_pls_fit.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.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_double]
762
+ def pls_fit(cxx, cxy, cyy, xw, yw, xl, yl, niter, p, q, k, mode, canon, algo, maxit, tol):
763
+ cxx = np.ascontiguousarray(cxx, dtype=np.float64)
764
+ cxy = np.ascontiguousarray(cxy, dtype=np.float64)
765
+ cyy = np.ascontiguousarray(cyy, dtype=np.float64)
766
+ xw = np.ascontiguousarray(xw, dtype=np.float64)
767
+ yw = np.ascontiguousarray(yw, dtype=np.float64)
768
+ xl = np.ascontiguousarray(xl, dtype=np.float64)
769
+ yl = np.ascontiguousarray(yl, dtype=np.float64)
770
+ niter = np.ascontiguousarray(niter, dtype=np.int32)
771
+ return _lib.scm2cpp_pls_fit(cxx.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), cxy.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), cyy.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), xw.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), yw.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), xl.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), yl.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), niter.ctypes.data_as(ctypes.POINTER(ctypes.c_int)), p, q, k, mode, canon, algo, maxit, tol)
772
+