learningmachine 0.2.3__tar.gz → 1.1.2__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 (33) hide show
  1. {learningmachine-0.2.3 → learningmachine-1.1.2}/PKG-INFO +6 -3
  2. learningmachine-1.1.2/learningmachine/__init__.py +10 -0
  3. learningmachine-1.1.2/learningmachine/base.py +209 -0
  4. learningmachine-1.1.2/learningmachine/classifier.py +134 -0
  5. learningmachine-1.1.2/learningmachine/regression.py +92 -0
  6. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine/utils.py +12 -0
  7. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine.egg-info/PKG-INFO +6 -3
  8. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine.egg-info/SOURCES.txt +2 -1
  9. {learningmachine-0.2.3 → learningmachine-1.1.2}/setup.py +46 -38
  10. learningmachine-0.2.3/learningmachine/__init__.py +0 -11
  11. learningmachine-0.2.3/learningmachine/base.py +0 -75
  12. learningmachine-0.2.3/learningmachine/basemodels.py +0 -231
  13. {learningmachine-0.2.3 → learningmachine-1.1.2}/CONTRIBUTING.rst +0 -0
  14. {learningmachine-0.2.3 → learningmachine-1.1.2}/HISTORY.rst +0 -0
  15. {learningmachine-0.2.3 → learningmachine-1.1.2}/LICENSE +0 -0
  16. {learningmachine-0.2.3 → learningmachine-1.1.2}/MANIFEST.in +0 -0
  17. {learningmachine-0.2.3 → learningmachine-1.1.2}/README.rst +0 -0
  18. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/Makefile +0 -0
  19. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/conf.py +0 -0
  20. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/contributing.rst +0 -0
  21. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/history.rst +0 -0
  22. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/index.rst +0 -0
  23. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/installation.rst +0 -0
  24. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/make.bat +0 -0
  25. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/readme.rst +0 -0
  26. {learningmachine-0.2.3 → learningmachine-1.1.2}/docs/usage.rst +0 -0
  27. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine.egg-info/dependency_links.txt +0 -0
  28. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine.egg-info/not-zip-safe +0 -0
  29. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine.egg-info/requires.txt +0 -0
  30. {learningmachine-0.2.3 → learningmachine-1.1.2}/learningmachine.egg-info/top_level.txt +0 -0
  31. {learningmachine-0.2.3 → learningmachine-1.1.2}/setup.cfg +0 -0
  32. {learningmachine-0.2.3 → learningmachine-1.1.2}/tests/__init__.py +0 -0
  33. {learningmachine-0.2.3 → learningmachine-1.1.2}/tests/test_learningmachine.py +0 -0
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: learningmachine
3
- Version: 0.2.3
3
+ Version: 1.1.2
4
4
  Summary: Machine Learning with uncertainty quantification and interpretability
5
5
  Home-page: https://github.com/Techtonique/learningmachine_python
6
6
  Author: T. Moudiki
7
7
  Author-email: thierry.moudiki@gmail.com
8
8
  License: BSD Clause Clear license
9
9
  Keywords: learningmachine
10
- Platform: UNKNOWN
11
10
  Classifier: Development Status :: 2 - Pre-Alpha
12
11
  Classifier: Intended Audience :: Developers
13
12
  Classifier: License :: OSI Approved :: BSD License
@@ -18,6 +17,10 @@ Classifier: Programming Language :: Python :: 3.7
18
17
  Classifier: Programming Language :: Python :: 3.8
19
18
  Requires-Python: >=3.6
20
19
  License-File: LICENSE
20
+ Requires-Dist: numpy
21
+ Requires-Dist: pandas
22
+ Requires-Dist: rpy2>=3.4.5
23
+ Requires-Dist: scikit-learn
24
+ Requires-Dist: scipy
21
25
 
22
26
  Machine Learning with uncertainty quantification and interpretability.
23
-
@@ -0,0 +1,10 @@
1
+ """Top-level package for learningmachine."""
2
+
3
+ __author__ = """T. Moudiki"""
4
+ __email__ = "thierry.moudiki@gmail.com"
5
+
6
+ from .base import Base
7
+ from .classifier import Classifier
8
+ from .regression import Regressor
9
+
10
+ __all__ = ["Base", "Classifier", "Regressor"]
@@ -0,0 +1,209 @@
1
+ import sklearn.metrics as skm
2
+ import subprocess
3
+ from functools import lru_cache
4
+ from sklearn.base import BaseEstimator
5
+ from rpy2.robjects.vectors import StrVector
6
+ from rpy2.robjects.packages import importr
7
+ from rpy2.robjects import r
8
+
9
+ base = importr("base")
10
+ stats = importr("stats")
11
+ utils = importr("utils")
12
+
13
+
14
+ class Base(BaseEstimator):
15
+ """
16
+ Base class.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ type=None,
22
+ name="Base",
23
+ method="ranger",
24
+ pi_method="kdesplitconformal",
25
+ level=95,
26
+ type_prediction_set="score",
27
+ B=100,
28
+ nb_hidden = 0,
29
+ nodes_sim = "sobol",
30
+ activ = "relu",
31
+ params=None,
32
+ seed=123,
33
+ ):
34
+ """
35
+ Initialize the model.
36
+ """
37
+ super().__init__()
38
+ self.name = name
39
+ self.type = type
40
+ self.method = method
41
+ self.pi_method = pi_method
42
+ self.level = level
43
+ self.type_prediction_set = type_prediction_set
44
+ self.B = B
45
+ self.nb_hidden = nb_hidden
46
+ assert nodes_sim in ("sobol", "halton", "unif"), \
47
+ "must have nodes_sim in ('sobol', 'halton', 'unif')"
48
+ self.nodes_sim = "sobol"
49
+ assert activ in ("relu", "sigmoid", "tanh",
50
+ "leakyrelu", "elu", "linear"), \
51
+ "must have activ in ('relu', 'sigmoid', 'tanh', 'leakyrelu', 'elu', 'linear')"
52
+ self.activ = activ
53
+ self.params = params
54
+ self.seed = seed
55
+ self.obj = None
56
+
57
+ @lru_cache
58
+ def load_learningmachine(self):
59
+ # Install R packages
60
+ commands1_lm = 'base::system.file(package = "learningmachine")' # check "learningmachine" is installed
61
+ commands2_lm = 'base::system.file("learningmachine_r", package = "learningmachine")' # check "learningmachine" is installed locally
62
+ exec_commands1_lm = subprocess.run(
63
+ ["Rscript", "-e", commands1_lm], capture_output=True, text=True
64
+ )
65
+ exec_commands2_lm = subprocess.run(
66
+ ["Rscript", "-e", commands2_lm], capture_output=True, text=True
67
+ )
68
+ if (
69
+ len(exec_commands1_lm.stdout) == 7
70
+ and len(exec_commands2_lm.stdout) == 7
71
+ ): # kind of convoluted, but works
72
+ print("Installing R packages along with 'learningmachine'...")
73
+ commands1 = [
74
+ 'try(utils::install.packages(c("R6", "Rcpp", "skimr"), repos="https://cloud.r-project.org", dependencies = TRUE), silent=FALSE)',
75
+ 'try(utils::install.packages("learningmachine", repos="https://techtonique.r-universe.dev", dependencies = TRUE), silent=FALSE)',
76
+ ]
77
+ commands2 = [
78
+ 'try(utils::install.packages(c("R6", "Rcpp", "skimr"), lib="./learningmachine_r", repos="https://cloud.r-project.org", dependencies = TRUE), silent=FALSE)',
79
+ 'try(utils::install.packages("learningmachine", lib="./learningmachine_r", repos="https://techtonique.r-universe.dev", dependencies = TRUE), silent=FALSE)',
80
+ ]
81
+ try:
82
+ for cmd in commands1:
83
+ subprocess.run(["Rscript", "-e", cmd])
84
+ except NotImplementedError as e: # can't install packages globally
85
+ subprocess.run(["mkdir", "learningmachine_r"])
86
+ for cmd in commands2:
87
+ subprocess.run(["Rscript", "-e", cmd])
88
+
89
+ try:
90
+ base.library(StrVector(["learningmachine"]))
91
+ except: # can't load the package from the global environment
92
+ try:
93
+ base.library(
94
+ StrVector(["learningmachine"]),
95
+ lib_loc="learningmachine_r",
96
+ )
97
+ except: # well, we tried
98
+ try:
99
+ r("try(library('learningmachine'), silence=TRUE)")
100
+ except: # well, we tried everything at this point
101
+ r(
102
+ "try(library('learningmachine', lib.loc='learningmachine_r'), silence=TRUE)"
103
+ )
104
+
105
+ def score(self, X, y, scoring=None, **kwargs):
106
+ """Score the model on test set features X and response y.
107
+
108
+ Parameters:
109
+
110
+ X: {array-like}, shape = [n_samples, n_features]
111
+ Training vectors, where n_samples is the number
112
+ of samples and n_features is the number of features
113
+
114
+ y: array-like, shape = [n_samples]
115
+ Target values
116
+
117
+ scoring: str
118
+ must be in ('explained_variance', 'neg_mean_absolute_error',
119
+ 'neg_mean_squared_error', 'neg_mean_squared_log_error',
120
+ 'neg_median_absolute_error', 'r2')
121
+
122
+ **kwargs: additional parameters to be passed to scoring functions
123
+
124
+ Returns:
125
+
126
+ model scores: {array-like}
127
+
128
+ """
129
+
130
+ preds = self.predict(X)
131
+
132
+ if self.type == "classification":
133
+
134
+ if scoring is None:
135
+ scoring = "accuracy"
136
+
137
+ # check inputs
138
+ assert scoring in (
139
+ "accuracy",
140
+ "average_precision",
141
+ "brier_score_loss",
142
+ "f1",
143
+ "f1_micro",
144
+ "f1_macro",
145
+ "f1_weighted",
146
+ "f1_samples",
147
+ "neg_log_loss",
148
+ "precision",
149
+ "recall",
150
+ "roc_auc",
151
+ ), "'scoring' should be in ('accuracy', 'average_precision', \
152
+ 'brier_score_loss', 'f1', 'f1_micro', \
153
+ 'f1_macro', 'f1_weighted', 'f1_samples', \
154
+ 'neg_log_loss', 'precision', 'recall', \
155
+ 'roc_auc')"
156
+
157
+ scoring_options = {
158
+ "accuracy": skm.accuracy_score,
159
+ "average_precision": skm.average_precision_score,
160
+ "brier_score_loss": skm.brier_score_loss,
161
+ "f1": skm.f1_score,
162
+ "f1_micro": skm.f1_score,
163
+ "f1_macro": skm.f1_score,
164
+ "f1_weighted": skm.f1_score,
165
+ "f1_samples": skm.f1_score,
166
+ "neg_log_loss": skm.log_loss,
167
+ "precision": skm.precision_score,
168
+ "recall": skm.recall_score,
169
+ "roc_auc": skm.roc_auc_score,
170
+ }
171
+
172
+ try:
173
+ preds = preds.ravel().astype(int)
174
+ return scoring_options[scoring](y, preds, **kwargs)
175
+ except:
176
+ return scoring_options[scoring](y, preds, **kwargs)
177
+
178
+ if self.type == "regression":
179
+
180
+ if (
181
+ type(preds) == tuple
182
+ ): # if there are std. devs in the predictions
183
+ preds = preds[0]
184
+
185
+ if scoring is None:
186
+ scoring = "neg_mean_squared_error"
187
+
188
+ # check inputs
189
+ assert scoring in (
190
+ "explained_variance",
191
+ "neg_mean_absolute_error",
192
+ "neg_mean_squared_error",
193
+ "neg_mean_squared_log_error",
194
+ "neg_median_absolute_error",
195
+ "r2",
196
+ ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
197
+ 'neg_mean_squared_error', 'neg_mean_squared_log_error', \
198
+ 'neg_median_absolute_error', 'r2')"
199
+
200
+ scoring_options = {
201
+ "explained_variance": skm.explained_variance_score,
202
+ "neg_mean_absolute_error": skm.median_absolute_error,
203
+ "neg_mean_squared_error": skm.mean_squared_error,
204
+ "neg_mean_squared_log_error": skm.mean_squared_log_error,
205
+ "neg_median_absolute_error": skm.median_absolute_error,
206
+ "r2": skm.r2_score,
207
+ }
208
+
209
+ return scoring_options[scoring](y, preds, **kwargs)
@@ -0,0 +1,134 @@
1
+ import numpy as np
2
+ import sklearn.metrics as skm
3
+ from rpy2.robjects import r
4
+ from rpy2.robjects.packages import importr
5
+ from rpy2.robjects.vectors import (
6
+ FloatMatrix,
7
+ FloatVector,
8
+ IntVector,
9
+ FactorVector,
10
+ )
11
+ from sklearn.base import ClassifierMixin
12
+ from .base import Base
13
+ from .utils import format_value
14
+
15
+ base = importr("base")
16
+ stats = importr("stats")
17
+ utils = importr("utils")
18
+
19
+
20
+ class Classifier(Base, ClassifierMixin):
21
+ """
22
+ Classifier.
23
+ """
24
+
25
+ def __init__(
26
+ self,
27
+ method="ranger",
28
+ pi_method="kdesplitconformal",
29
+ level=95,
30
+ type_prediction_set="score",
31
+ B=100,
32
+ nb_hidden = 0,
33
+ nodes_sim = "sobol",
34
+ activ = "relu",
35
+ seed=123,
36
+ ):
37
+ """
38
+ Initialize the model.
39
+ """
40
+ super().__init__(
41
+ name = "Classifier",
42
+ type = "classification",
43
+ method=method,
44
+ pi_method=pi_method,
45
+ level=level,
46
+ type_prediction_set=type_prediction_set,
47
+ B=B,
48
+ nb_hidden=nb_hidden,
49
+ nodes_sim=nodes_sim,
50
+ activ=activ,
51
+ seed=seed,
52
+ )
53
+
54
+ try:
55
+ self.load_learningmachine()
56
+ self.obj = r(
57
+ f"learningmachine::Classifier$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, type_prediction_set = {format_value(self.type_prediction_set)}, B = {format_value(self.B)}, nb_hidden = {format_value(self.nb_hidden)}, nodes_sim = {format_value(self.nodes_sim)}, activ = {format_value(self.activ)}, seed = {format_value(self.seed)})"
58
+ )
59
+ except NotImplementedError as e:
60
+ try:
61
+ r.library("learningmachine")
62
+ self.obj = r(
63
+ f"Classifier$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, type_prediction_set = {format_value(self.type_prediction_set)}, B = {format_value(self.B)}, nb_hidden = {format_value(self.nb_hidden)}, nodes_sim = {format_value(self.nodes_sim)}, activ = {format_value(self.activ)}, seed = {format_value(self.seed)})"
64
+ )
65
+ except NotImplementedError as e:
66
+ try:
67
+ self.obj = r(
68
+ f"""
69
+ library(learningmachine);
70
+ Classifier$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, type_prediction_set = {format_value(self.type_prediction_set)}, B = {format_value(self.B)}, nb_hidden = {format_value(self.nb_hidden)}, nodes_sim = {format_value(self.nodes_sim)}, activ = {format_value(self.activ)}, seed = {format_value(self.seed)})
71
+ """
72
+ )
73
+ except NotImplementedError as e:
74
+ print("R package can't be loaded: ", e)
75
+
76
+ def fit(self, X, y):
77
+ """
78
+ Fit the model according to the given training data.
79
+ """
80
+ self.obj["fit"](
81
+ r.matrix(FloatVector(X.ravel()),
82
+ byrow=True,
83
+ ncol=X.shape[1],
84
+ nrow=X.shape[0]),
85
+ FactorVector(IntVector(y)),
86
+ )
87
+ self.classes_ = np.unique(y) # /!\ do not remove
88
+ return self
89
+
90
+ def predict_proba(self, X):
91
+ """
92
+ Predict using the model.
93
+ """
94
+ if self.level is None:
95
+ res = self.obj["predict_proba"](
96
+ r.matrix(FloatVector(X.ravel()),
97
+ byrow=True,
98
+ ncol=X.shape[1],
99
+ nrow=X.shape[0])
100
+ )
101
+ return np.asarray(res)
102
+ res = self.obj["predict_proba"](
103
+ r.matrix(FloatVector(X.ravel()),
104
+ byrow=True,
105
+ ncol=X.shape[1],
106
+ nrow=X.shape[0])
107
+ )
108
+ return np.asarray(res[0])
109
+
110
+ def predict(self, X):
111
+ """
112
+ Predict using the model.
113
+ """
114
+ if self.level is None:
115
+ return (
116
+ np.asarray(
117
+ self.obj["predict"](
118
+ r.matrix(FloatVector(X.ravel()),
119
+ byrow=True,
120
+ ncol=X.shape[1],
121
+ nrow=X.shape[0])
122
+ )
123
+ ) - 1
124
+ )
125
+ return (
126
+ np.asarray(
127
+ self.obj["predict"](
128
+ r.matrix(FloatVector(X.ravel()),
129
+ byrow=True,
130
+ ncol=X.shape[1],
131
+ nrow=X.shape[0])
132
+ )
133
+ )
134
+ )
@@ -0,0 +1,92 @@
1
+ import numpy as np
2
+ from rpy2.robjects import r
3
+ from rpy2.robjects.packages import importr
4
+ from rpy2.robjects.vectors import FloatMatrix, FloatVector
5
+ from sklearn.base import RegressorMixin
6
+ from .base import Base
7
+ from .utils import format_value
8
+
9
+ base = importr("base")
10
+ stats = importr("stats")
11
+ utils = importr("utils")
12
+
13
+
14
+ class Regressor(Base, RegressorMixin):
15
+ """
16
+ Regressor.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ method="ranger",
22
+ pi_method="kdesplitconformal",
23
+ level=95,
24
+ B=100,
25
+ nb_hidden = 0,
26
+ nodes_sim = "sobol",
27
+ activ = "relu",
28
+ seed=123,
29
+ ):
30
+ """
31
+ Initialize the model.
32
+ """
33
+ super().__init__(
34
+ name = "Regressor",
35
+ type = "regression",
36
+ method=method,
37
+ pi_method=pi_method,
38
+ level=level,
39
+ B=B,
40
+ nb_hidden=nb_hidden,
41
+ nodes_sim=nodes_sim,
42
+ activ=activ,
43
+ seed=seed,
44
+ )
45
+
46
+ try:
47
+ self.load_learningmachine()
48
+ self.obj = r(
49
+ f"learningmachine::Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, type_prediction_set = {format_value(self.type_prediction_set)}, B = {format_value(self.B)}, nb_hidden = {format_value(self.nb_hidden)}, nodes_sim = {format_value(self.nodes_sim)}, activ = {format_value(self.activ)}, seed = {format_value(self.seed)})"
50
+ )
51
+ except NotImplementedError as e:
52
+ try:
53
+ r.library("learningmachine")
54
+ self.obj = r(
55
+ f"Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, type_prediction_set = {format_value(self.type_prediction_set)}, B = {format_value(self.B)}, nb_hidden = {format_value(self.nb_hidden)}, nodes_sim = {format_value(self.nodes_sim)}, activ = {format_value(self.activ)}, seed = {format_value(self.seed)})"
56
+ )
57
+ except NotImplementedError as e:
58
+ try:
59
+ self.obj = r(
60
+ f"""
61
+ library(learningmachine);
62
+ Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, type_prediction_set = {format_value(self.type_prediction_set)}, B = {format_value(self.B)}, nb_hidden = {format_value(self.nb_hidden)}, nodes_sim = {format_value(self.nodes_sim)}, activ = {format_value(self.activ)}, seed = {format_value(self.seed)})
63
+ """
64
+ )
65
+ except NotImplementedError as e:
66
+ print("R package can't be loaded: ", e)
67
+
68
+ def fit(self, X, y):
69
+ """
70
+ Fit the model according to the given training data.
71
+ """
72
+ self.obj["fit"](
73
+ r.matrix(FloatVector(X.ravel()),
74
+ byrow=True,
75
+ ncol=X.shape[1],
76
+ nrow=X.shape[0]),
77
+ FloatVector(y),
78
+ )
79
+ return self
80
+
81
+ def predict(self, X):
82
+ """
83
+ Predict using the model.
84
+ """
85
+ return np.asarray(
86
+ self.obj["predict"](
87
+ r.matrix(FloatVector(X.ravel()),
88
+ byrow=True,
89
+ ncol=X.shape[1],
90
+ nrow=X.shape[0])
91
+ )
92
+ )
@@ -60,3 +60,15 @@ def check_install_r_pkg():
60
60
  if check_pkg_installed() == True:
61
61
  return 1
62
62
  return 0
63
+
64
+
65
+ # Formatting object as a string
66
+ def format_value(value):
67
+ if value is None:
68
+ return f"NULL"
69
+ if isinstance(value, str):
70
+ return f'"{value}"'
71
+ if isinstance(value, bool):
72
+ return f"{str(value).upper()}"
73
+ if isinstance(value, int) or isinstance(value, float):
74
+ return f"{value}"
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: learningmachine
3
- Version: 0.2.3
3
+ Version: 1.1.2
4
4
  Summary: Machine Learning with uncertainty quantification and interpretability
5
5
  Home-page: https://github.com/Techtonique/learningmachine_python
6
6
  Author: T. Moudiki
7
7
  Author-email: thierry.moudiki@gmail.com
8
8
  License: BSD Clause Clear license
9
9
  Keywords: learningmachine
10
- Platform: UNKNOWN
11
10
  Classifier: Development Status :: 2 - Pre-Alpha
12
11
  Classifier: Intended Audience :: Developers
13
12
  Classifier: License :: OSI Approved :: BSD License
@@ -18,6 +17,10 @@ Classifier: Programming Language :: Python :: 3.7
18
17
  Classifier: Programming Language :: Python :: 3.8
19
18
  Requires-Python: >=3.6
20
19
  License-File: LICENSE
20
+ Requires-Dist: numpy
21
+ Requires-Dist: pandas
22
+ Requires-Dist: rpy2>=3.4.5
23
+ Requires-Dist: scikit-learn
24
+ Requires-Dist: scipy
21
25
 
22
26
  Machine Learning with uncertainty quantification and interpretability.
23
-
@@ -16,7 +16,8 @@ docs/readme.rst
16
16
  docs/usage.rst
17
17
  learningmachine/__init__.py
18
18
  learningmachine/base.py
19
- learningmachine/basemodels.py
19
+ learningmachine/classifier.py
20
+ learningmachine/regression.py
20
21
  learningmachine/utils.py
21
22
  learningmachine.egg-info/PKG-INFO
22
23
  learningmachine.egg-info/SOURCES.txt
@@ -1,17 +1,5 @@
1
- #!/usr/bin/env python
2
-
3
- # 1 - import Python packages -----------------------------------------------
4
-
5
- import subprocess
6
-
7
- subprocess.run(["pip", "install", "rpy2"])
8
-
9
- from os import path
10
1
  import platform
11
- from setuptools import setup, find_packages
12
-
13
-
14
- # 2 - utility functions -----------------------------------------------
2
+ import subprocess
15
3
 
16
4
  def check_r_installed():
17
5
  current_platform = platform.system()
@@ -25,9 +13,7 @@ def check_r_installed():
25
13
  print("R is already installed on Windows.")
26
14
  return True
27
15
  except subprocess.CalledProcessError:
28
- print(
29
- "R is required but not installed on Windows (check manually: https://cloud.r-project.org/)."
30
- )
16
+ print("R is not installed on Windows.")
31
17
  return False
32
18
 
33
19
  elif current_platform == "Linux":
@@ -37,9 +23,7 @@ def check_r_installed():
37
23
  print("R is already installed on Linux.")
38
24
  return True
39
25
  except subprocess.CalledProcessError:
40
- print(
41
- "R is required but not installed on Linux (check manually: https://cloud.r-project.org/)."
42
- )
26
+ print("R is not installed on Linux.")
43
27
  return False
44
28
 
45
29
  elif current_platform == "Darwin": # macOS
@@ -49,21 +33,20 @@ def check_r_installed():
49
33
  print("R is already installed on macOS.")
50
34
  return True
51
35
  except subprocess.CalledProcessError:
52
- print(
53
- "R is required but not installed on macOS (check manually: https://cloud.r-project.org/)."
54
- )
36
+ print("R is not installed on macOS.")
55
37
  return False
56
38
 
57
39
  else:
58
- print("Unsupported platform (check manually: https://cloud.r-project.org/)")
40
+ print("Unsupported platform. Unable to check for R installation.")
59
41
  return False
60
42
 
61
43
  def install_r():
44
+
62
45
  current_platform = platform.system()
63
46
 
64
47
  if current_platform == "Windows":
65
48
  # Install R on Windows using PowerShell
66
- install_command = "Start-Process powershell -Verb runAs -ArgumentList '-Command \"& {Invoke-WebRequest https://cran.r-project.org/bin/windows/base/R-4.1.2-win.exe -OutFile R.exe}; Start-Process R.exe -ArgumentList '/SILENT' -Wait}'"
49
+ install_command = "Start-Process powershell -Verb subprocess.runAs -ArgumentList '-Command \"& {Invoke-WebRequest https://cran.r-project.org/bin/windows/base/R-4.1.2-win.exe -OutFile R.exe}; Start-Process R.exe -ArgumentList '/SILENT' -Wait}'"
67
50
  subprocess.run(install_command, shell=True)
68
51
 
69
52
  elif current_platform == "Linux":
@@ -72,31 +55,56 @@ def install_r():
72
55
  "sudo apt update -qq && sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9"
73
56
  + "&& sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu focal-cran40/'"
74
57
  + "&& sudo apt update"
75
- + "&& sudo apt install r-base"
58
+ + "&& sudo apt -y install r-base"
76
59
  )
77
- try:
78
- subprocess.run(install_command, shell=True)
79
- except Exception as e:
80
- print("Error installing R on this Linux distribution. Please check manually: https://cloud.r-project.org/")
60
+ subprocess.run(install_command, shell=True)
81
61
 
82
62
  elif current_platform == "Darwin": # macOS
83
63
  # Install R on macOS using Homebrew
84
64
  install_command = "brew install r"
85
- try:
86
- subprocess.run(install_command, shell=True)
87
- except Exception as e:
88
- print("Error installing R on macOS. Please check manually: https://cloud.r-project.org/")
65
+ subprocess.run(install_command, shell=True)
89
66
 
90
67
  else:
91
- print("Unsupported platform. Unable to install R.")
92
68
 
69
+ print("Unsupported platform. Unable to install R.")
93
70
 
94
- # 3 - check if R is installed -----------------------------------------------
95
-
71
+ def install_packages():
72
+ try:
73
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(devtools, dependencies=TRUE)"])
74
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), dependencies=TRUE)"])
75
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages('learningmachine', repos='https://techtonique.r-universe.dev', dependencies=TRUE)"])
76
+ except:
77
+ try:
78
+ subprocess.run(["mkdir", "-p", "r-learningmachine"])
79
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(devtools, lib='r-learningmachine', dependencies=TRUE)"])
80
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), lib='r-learningmachine', dependencies=TRUE)"])
81
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages('learningmachine', repos='https://techtonique.r-universe.dev', lib='r-learningmachine', dependencies=TRUE)"])
82
+ except:
83
+ try:
84
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(devtools, dependencies=TRUE)"])
85
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), dependencies=TRUE)"])
86
+ subprocess.run(["sudo", "Rscript", "-e", "devtools::install_github('Techtonique/learningmachine')"])
87
+ except:
88
+ subprocess.run(["mkdir", "-p", "r-learningmachine"])
89
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(devtools, lib='r-learningmachine', dependencies=TRUE)"])
90
+ subprocess.run(["sudo", "Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), lib='r-learningmachine', dependencies=TRUE)"])
91
+ subprocess.run(["sudo", "Rscript", "-e", "devtools::install_github('Techtonique/learningmachine', lib='r-learningmachine')"])
92
+
93
+
94
+ # Check if R is installed; if not, install it
96
95
  if not check_r_installed():
96
+ print("Installing R...")
97
97
  install_r()
98
98
  else:
99
- print("R is already installed.")
99
+ print("No installation needed.")
100
+
101
+ install_packages()
102
+
103
+ subprocess.run(["pip", "install", "rpy2"])
104
+
105
+ from setuptools import setup, find_packages
106
+ from codecs import open
107
+ from os import path
100
108
 
101
109
  # 4 - Package setup -----------------------------------------------
102
110
 
@@ -126,6 +134,6 @@ setup(
126
134
  packages=find_packages(include=["learningmachine", "learningmachine.*"]),
127
135
  test_suite="tests",
128
136
  url="https://github.com/Techtonique/learningmachine_python",
129
- version="0.2.3",
137
+ version="1.1.2",
130
138
  zip_safe=False,
131
139
  )
@@ -1,11 +0,0 @@
1
- """Top-level package for learningmachine."""
2
-
3
- __author__ = """T. Moudiki"""
4
- __email__ = "thierry.moudiki@gmail.com"
5
- __version__ = "0.2.0"
6
-
7
- from .base import Base
8
- from .basemodels import BaseClassifier, BaseRegressor
9
- from .utils import check_install_r_pkg
10
-
11
- __all__ = ["check_install_r_pkg", "Base", "BaseClassifier", "BaseRegressor"]
@@ -1,75 +0,0 @@
1
- import subprocess
2
- from functools import lru_cache
3
- from rpy2.robjects import r
4
- from rpy2.robjects.packages import importr
5
- from rpy2.robjects.vectors import StrVector
6
- from sklearn.base import BaseEstimator
7
-
8
- base = importr("base")
9
- stats = importr("stats")
10
-
11
-
12
- @lru_cache(maxsize=32)
13
- def load_learningmachine():
14
- # Install R packages
15
- commands1_lm = 'base::system.file(package = "learningmachine")' # check "learningmachine" is installed
16
- commands2_lm = 'base::system.file("learningmachine_r", package = "learningmachine")' # check "learningmachine" is installed locally
17
- exec_commands1_lm = subprocess.run(
18
- ["Rscript", "-e", commands1_lm], capture_output=True, text=True
19
- )
20
- exec_commands2_lm = subprocess.run(
21
- ["Rscript", "-e", commands2_lm], capture_output=True, text=True
22
- )
23
- if (
24
- len(exec_commands1_lm.stdout) == 7
25
- and len(exec_commands2_lm.stdout) == 7
26
- ): # kind of convoluted, but works
27
- print("Installing R packages along with 'learningmachine'...")
28
- commands1 = [
29
- 'try(utils::install.packages(c("R6", "Rcpp", "skimr"), repos="https://cloud.r-project.org", dependencies = TRUE), silent=TRUE)',
30
- 'try(utils::install.packages("learningmachine", repos="https://techtonique.r-universe.dev", dependencies = TRUE), silent=TRUE)',
31
- ]
32
- commands2 = [
33
- 'try(utils::install.packages(c("R6", "Rcpp", "skimr"), lib="./learningmachine_r", repos="https://cloud.r-project.org", dependencies = TRUE), silent=TRUE)',
34
- 'try(utils::install.packages("learningmachine", lib="./learningmachine_r", repos="https://techtonique.r-universe.dev", dependencies = TRUE), silent=TRUE)',
35
- ]
36
- try:
37
- for cmd in commands1:
38
- subprocess.run(["Rscript", "-e", cmd])
39
- except Exception as e: # can't install packages globally
40
- subprocess.run(["mkdir", "learningmachine_r"])
41
- for cmd in commands2:
42
- subprocess.run(["Rscript", "-e", cmd])
43
-
44
- try:
45
- base.library(StrVector(["learningmachine"]))
46
- except (
47
- Exception
48
- ) as e1: # can't load the package from the global environment
49
- try:
50
- base.library(
51
- StrVector(["learningmachine"]), lib_loc="learningmachine_r"
52
- )
53
- except Exception as e2: # well, we tried
54
- try:
55
- r("try(library('learningmachine'), silence=TRUE)")
56
- except (
57
- NotImplementedError
58
- ) as e3: # well, we tried everything at this point
59
- r(
60
- "try(library('learningmachine', lib.loc='learningmachine_r'), silence=TRUE)"
61
- )
62
-
63
-
64
- class Base(BaseEstimator):
65
- """
66
- Base class.
67
- """
68
-
69
- def __init__(self):
70
- """
71
- Initialize the model.
72
- """
73
- self.type_fit = None
74
- self.obj = None
75
- load_learningmachine()
@@ -1,231 +0,0 @@
1
- import numpy as np
2
- import sklearn.metrics as skm
3
- from subprocess import run
4
- from rpy2.robjects import r
5
- from rpy2.robjects.packages import importr
6
- from rpy2.robjects.vectors import (
7
- FloatMatrix,
8
- FloatVector,
9
- IntVector,
10
- StrVector,
11
- )
12
- from sklearn.base import RegressorMixin, ClassifierMixin
13
- from .base import Base
14
-
15
- base = importr("base")
16
- stats = importr("stats")
17
- utils = importr("utils")
18
-
19
-
20
- class BaseRegressor(Base, RegressorMixin):
21
- """
22
- Base Regressor.
23
- """
24
-
25
- def __init__(self):
26
- """
27
- Initialize the model.
28
- """
29
- super().__init__()
30
- self.type_fit = "regression"
31
- self.obj = r("learningmachine::BaseRegressor$new()")
32
-
33
- def fit(self, X, y):
34
- """
35
- Fit the model according to the given training data.
36
- """
37
- self.obj["fit"](
38
- r.matrix(
39
- FloatVector(X), byrow=True, nrow=X.shape[0], ncol=X.shape[1]
40
- ),
41
- FloatVector(y),
42
- )
43
- return self
44
-
45
- def predict(self, X):
46
- """
47
- Predict using the model.
48
- """
49
- return np.asarray(
50
- self.obj["predict"](
51
- r.matrix(
52
- FloatMatrix(X), byrow=True, nrow=X.shape[0], ncol=X.shape[1]
53
- )
54
- )
55
- )
56
-
57
- def score(self, X, y, scoring=None, **kwargs):
58
- """Score the model on test set features X and response y.
59
-
60
- Parameters:
61
-
62
- X: {array-like}, shape = [n_samples, n_features]
63
- Training vectors, where n_samples is the number
64
- of samples and n_features is the number of features
65
-
66
- y: array-like, shape = [n_samples]
67
- Target values
68
-
69
- scoring: str
70
- must be in ('explained_variance', 'neg_mean_absolute_error',
71
- 'neg_mean_squared_error', 'neg_mean_squared_log_error',
72
- 'neg_median_absolute_error', 'r2')
73
-
74
- **kwargs: additional parameters to be passed to scoring functions
75
-
76
- Returns:
77
-
78
- model scores: {array-like}
79
-
80
- """
81
-
82
- preds = self.predict(X)
83
-
84
- if type(preds) == tuple: # if there are std. devs in the predictions
85
- preds = preds[0]
86
-
87
- if scoring is None:
88
- scoring = "neg_mean_squared_error"
89
-
90
- # check inputs
91
- assert scoring in (
92
- "explained_variance",
93
- "neg_mean_absolute_error",
94
- "neg_mean_squared_error",
95
- "neg_mean_squared_log_error",
96
- "neg_median_absolute_error",
97
- "r2",
98
- ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
99
- 'neg_mean_squared_error', 'neg_mean_squared_log_error', \
100
- 'neg_median_absolute_error', 'r2')"
101
-
102
- scoring_options = {
103
- "explained_variance": skm.explained_variance_score,
104
- "neg_mean_absolute_error": skm.median_absolute_error,
105
- "neg_mean_squared_error": skm.mean_squared_error,
106
- "neg_mean_squared_log_error": skm.mean_squared_log_error,
107
- "neg_median_absolute_error": skm.median_absolute_error,
108
- "r2": skm.r2_score,
109
- }
110
-
111
- return scoring_options[scoring](y, preds, **kwargs)
112
-
113
-
114
- class BaseClassifier(Base, ClassifierMixin):
115
- """
116
- Base Classifier.
117
- """
118
-
119
- def __init__(self):
120
- """
121
- Initialize the model.
122
- """
123
- super().__init__()
124
- self.type_fit = "classification"
125
- self.obj = r("learningmachine::BaseClassifier$new()")
126
-
127
- def fit(self, X, y):
128
- """
129
- Fit the model according to the given training data.
130
- """
131
- self.obj["fit"](
132
- r.matrix(
133
- FloatMatrix(X), byrow=True, nrow=X.shape[0], ncol=X.shape[1]
134
- ),
135
- base.as_factor(IntVector(y)),
136
- )
137
- self.classes_ = np.unique(y)
138
- return self
139
-
140
- def predict(self, X):
141
- """
142
- Predict classes using the model.
143
- """
144
- return np.asarray(
145
- self.obj["predict"](
146
- r.matrix(
147
- FloatMatrix(X), byrow=True, nrow=X.shape[0], ncol=X.shape[1]
148
- )
149
- )
150
- )
151
-
152
- def predict_proba(self, X):
153
- """
154
- Predict probabilities using the model.
155
- """
156
- return np.asarray(
157
- self.obj["predict_proba"](
158
- r.matrix(
159
- FloatMatrix(X), byrow=True, nrow=X.shape[0], ncol=X.shape[1]
160
- )
161
- )
162
- )
163
-
164
- def score(self, X, y, scoring=None, **kwargs):
165
- """Score the model on test set features X and response y.
166
-
167
- Parameters:
168
-
169
- X: {array-like}, shape = [n_samples, n_features]
170
- Training vectors, where n_samples is the number
171
- of samples and n_features is the number of features
172
-
173
- y: array-like, shape = [n_samples]
174
- Target values
175
-
176
- scoring: str
177
- must be in ('accuracy', 'average_precision',
178
- 'brier_score_loss', 'f1', 'f1_micro',
179
- 'f1_macro', 'f1_weighted', 'f1_samples',
180
- 'neg_log_loss', 'precision', 'recall',
181
- 'roc_auc')
182
-
183
- **kwargs: additional parameters to be passed to scoring functions
184
-
185
- Returns:
186
-
187
- model scores: {array-like}
188
-
189
- """
190
-
191
- preds = self.predict(X)
192
-
193
- if scoring is None:
194
- scoring = "accuracy"
195
-
196
- # check inputs
197
- assert scoring in (
198
- "accuracy",
199
- "average_precision",
200
- "brier_score_loss",
201
- "f1",
202
- "f1_micro",
203
- "f1_macro",
204
- "f1_weighted",
205
- "f1_samples",
206
- "neg_log_loss",
207
- "precision",
208
- "recall",
209
- "roc_auc",
210
- ), "'scoring' should be in ('accuracy', 'average_precision', \
211
- 'brier_score_loss', 'f1', 'f1_micro', \
212
- 'f1_macro', 'f1_weighted', 'f1_samples', \
213
- 'neg_log_loss', 'precision', 'recall', \
214
- 'roc_auc')"
215
-
216
- scoring_options = {
217
- "accuracy": skm.accuracy_score,
218
- "average_precision": skm.average_precision_score,
219
- "brier_score_loss": skm.brier_score_loss,
220
- "f1": skm.f1_score,
221
- "f1_micro": skm.f1_score,
222
- "f1_macro": skm.f1_score,
223
- "f1_weighted": skm.f1_score,
224
- "f1_samples": skm.f1_score,
225
- "neg_log_loss": skm.log_loss,
226
- "precision": skm.precision_score,
227
- "recall": skm.recall_score,
228
- "roc_auc": skm.roc_auc_score,
229
- }
230
-
231
- return scoring_options[scoring](y, preds, **kwargs)
File without changes