learningmachine 1.1.0__tar.gz → 2.0.1__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.
- learningmachine-2.0.1/LICENSE +32 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/PKG-INFO +1 -1
- learningmachine-2.0.1/README.md +54 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine/base.py +75 -14
- learningmachine-2.0.1/learningmachine/classifier.py +140 -0
- learningmachine-2.0.1/learningmachine/regression.py +109 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine/utils.py +22 -1
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/PKG-INFO +1 -1
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/SOURCES.txt +1 -1
- learningmachine-2.0.1/setup.py +154 -0
- learningmachine-1.1.0/LICENSE +0 -32
- learningmachine-1.1.0/README.rst +0 -37
- learningmachine-1.1.0/learningmachine/classifier.py +0 -134
- learningmachine-1.1.0/learningmachine/regression.py +0 -92
- learningmachine-1.1.0/setup.py +0 -220
- {learningmachine-1.1.0 → learningmachine-2.0.1}/CONTRIBUTING.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/HISTORY.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/MANIFEST.in +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/Makefile +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/conf.py +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/contributing.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/history.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/index.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/installation.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/make.bat +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/readme.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/docs/usage.rst +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine/__init__.py +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/dependency_links.txt +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/not-zip-safe +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/requires.txt +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/top_level.txt +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/setup.cfg +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/tests/__init__.py +0 -0
- {learningmachine-1.1.0 → learningmachine-2.0.1}/tests/test_learningmachine.py +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
The Clear BSD License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2023-2024] [T. Moudiki]
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted (subject to the limitations in the disclaimer
|
|
8
|
+
below) provided that the following conditions are met:
|
|
9
|
+
|
|
10
|
+
* Redistributions of source code must retain the above copyright notice,
|
|
11
|
+
this list of conditions and the following disclaimer.
|
|
12
|
+
|
|
13
|
+
* Redistributions in binary form must reproduce the above copyright
|
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
|
15
|
+
documentation and/or other materials provided with the distribution.
|
|
16
|
+
|
|
17
|
+
* Neither the name of the copyright holder nor the names of its
|
|
18
|
+
contributors may be used to endorse or promote products derived from this
|
|
19
|
+
software without specific prior written permission.
|
|
20
|
+
|
|
21
|
+
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
|
22
|
+
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
23
|
+
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
24
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
25
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
26
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
27
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
28
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
29
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
30
|
+
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
31
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
32
|
+
POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# learningmachine
|
|
2
|
+
|
|
3
|
+
 [](https://github.com/thierrymoudiki/learningmachine/blob/master/LICENSE) [](https://pepy.tech/project/learningmachine)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Machine Learning with uncertainty quantification and interpretability.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
If R packages are not installed automatically when running `pip`, [install it manually](https://cloud.r-project.org/).
|
|
11
|
+
|
|
12
|
+
**Development version**
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
!pip install git+https://github.com/Techtonique/learningmachine_python.git --verbose
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Stable version**
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
!pip install learningmachine --verbose
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
|
|
26
|
+
See also:
|
|
27
|
+
- [this notebook](https://colab.research.google.com/github/Techtonique/learningmachine_python/blob/main/learningmachine/demo/thierrymoudiki_20240401_calib.ipynb)
|
|
28
|
+
- [this notebook](https://colab.research.google.com/github/Techtonique/learningmachine_python/blob/main/learningmachine/demo/thierrymoudiki_20240508_calib.ipynb)
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import learningmachine as lm
|
|
32
|
+
|
|
33
|
+
from sklearn.datasets import load_diabetes
|
|
34
|
+
from sklearn.model_selection import train_test_split
|
|
35
|
+
from time import time
|
|
36
|
+
from sklearn.metrics import mean_squared_error
|
|
37
|
+
|
|
38
|
+
# Regression (linear)
|
|
39
|
+
fit_obj = lm.BaseRegressor()
|
|
40
|
+
diabetes = load_diabetes()
|
|
41
|
+
X = diabetes.data[:150]
|
|
42
|
+
y = diabetes.target[:150]
|
|
43
|
+
|
|
44
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
|
|
45
|
+
random_state=1213)
|
|
46
|
+
|
|
47
|
+
start = time()
|
|
48
|
+
fit_obj.fit(X_train, y_train)
|
|
49
|
+
print("Elapsed time: ", time() - start)
|
|
50
|
+
|
|
51
|
+
## Compute RMSE
|
|
52
|
+
rms1 = sqrt(mean_squared_error(y_test, fit_obj.predict(X_test), squared=False))
|
|
53
|
+
print(rms1)
|
|
54
|
+
```
|
|
@@ -2,9 +2,16 @@ import sklearn.metrics as skm
|
|
|
2
2
|
import subprocess
|
|
3
3
|
from functools import lru_cache
|
|
4
4
|
from sklearn.base import BaseEstimator
|
|
5
|
-
from rpy2.robjects.vectors import
|
|
5
|
+
from rpy2.robjects.vectors import (
|
|
6
|
+
StrVector,
|
|
7
|
+
FloatMatrix,
|
|
8
|
+
FloatVector,
|
|
9
|
+
IntVector,
|
|
10
|
+
FactorVector,
|
|
11
|
+
)
|
|
6
12
|
from rpy2.robjects.packages import importr
|
|
7
13
|
from rpy2.robjects import r
|
|
14
|
+
from rpy2.robjects import NULL as rNULL
|
|
8
15
|
|
|
9
16
|
base = importr("base")
|
|
10
17
|
stats = importr("stats")
|
|
@@ -23,7 +30,6 @@ class Base(BaseEstimator):
|
|
|
23
30
|
method="ranger",
|
|
24
31
|
pi_method="kdesplitconformal",
|
|
25
32
|
level=95,
|
|
26
|
-
type_prediction_set="score",
|
|
27
33
|
B=100,
|
|
28
34
|
nb_hidden = 0,
|
|
29
35
|
nodes_sim = "sobol",
|
|
@@ -40,7 +46,6 @@ class Base(BaseEstimator):
|
|
|
40
46
|
self.method = method
|
|
41
47
|
self.pi_method = pi_method
|
|
42
48
|
self.level = level
|
|
43
|
-
self.type_prediction_set = type_prediction_set
|
|
44
49
|
self.B = B
|
|
45
50
|
self.nb_hidden = nb_hidden
|
|
46
51
|
assert nodes_sim in ("sobol", "halton", "unif"), \
|
|
@@ -54,7 +59,6 @@ class Base(BaseEstimator):
|
|
|
54
59
|
self.seed = seed
|
|
55
60
|
self.obj = None
|
|
56
61
|
|
|
57
|
-
@lru_cache
|
|
58
62
|
def load_learningmachine(self):
|
|
59
63
|
# Install R packages
|
|
60
64
|
commands1_lm = 'base::system.file(package = "learningmachine")' # check "learningmachine" is installed
|
|
@@ -88,22 +92,18 @@ class Base(BaseEstimator):
|
|
|
88
92
|
|
|
89
93
|
try:
|
|
90
94
|
base.library(StrVector(["learningmachine"]))
|
|
91
|
-
except
|
|
92
|
-
NotImplementedError
|
|
93
|
-
) as e1: # can't load the package from the global environment
|
|
95
|
+
except: # can't load the package from the global environment
|
|
94
96
|
try:
|
|
95
97
|
base.library(
|
|
96
98
|
StrVector(["learningmachine"]),
|
|
97
99
|
lib_loc="learningmachine_r",
|
|
98
100
|
)
|
|
99
|
-
except
|
|
101
|
+
except: # well, we tried
|
|
100
102
|
try:
|
|
101
|
-
r("try(library('learningmachine'), silence=
|
|
102
|
-
except
|
|
103
|
-
NotImplementedError
|
|
104
|
-
) as e3: # well, we tried everything at this point
|
|
103
|
+
r("try(suppressWarnings(suppressMessages(library('learningmachine'))), silence=TRUE)")
|
|
104
|
+
except: # well, we tried everything at this point
|
|
105
105
|
r(
|
|
106
|
-
"try(library('learningmachine', lib.loc='learningmachine_r'), silence=
|
|
106
|
+
"try(suppressWarnings(suppressMessages(library('learningmachine', lib.loc='learningmachine_r'))), silence=TRUE)"
|
|
107
107
|
)
|
|
108
108
|
|
|
109
109
|
def score(self, X, y, scoring=None, **kwargs):
|
|
@@ -176,7 +176,7 @@ class Base(BaseEstimator):
|
|
|
176
176
|
try:
|
|
177
177
|
preds = preds.ravel().astype(int)
|
|
178
178
|
return scoring_options[scoring](y, preds, **kwargs)
|
|
179
|
-
except:
|
|
179
|
+
except TypeError:
|
|
180
180
|
return scoring_options[scoring](y, preds, **kwargs)
|
|
181
181
|
|
|
182
182
|
if self.type == "regression":
|
|
@@ -211,3 +211,64 @@ class Base(BaseEstimator):
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
return scoring_options[scoring](y, preds, **kwargs)
|
|
214
|
+
|
|
215
|
+
def summary(self, X, y,
|
|
216
|
+
class_index = None,
|
|
217
|
+
level = 95,
|
|
218
|
+
show_progress = True,
|
|
219
|
+
cl = None):
|
|
220
|
+
|
|
221
|
+
if cl is None:
|
|
222
|
+
|
|
223
|
+
if self.type == "classification":
|
|
224
|
+
|
|
225
|
+
assert class_index is not None, "class_index must be provided for classification models"
|
|
226
|
+
|
|
227
|
+
self.obj["summary"](X = r.matrix(FloatVector(X.ravel()),
|
|
228
|
+
byrow=True,
|
|
229
|
+
ncol=X.shape[1],
|
|
230
|
+
nrow=X.shape[0]),
|
|
231
|
+
y = FactorVector(IntVector(y)),
|
|
232
|
+
class_index = class_index + 1,
|
|
233
|
+
level = level,
|
|
234
|
+
show_progress = show_progress
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
else: # regression
|
|
238
|
+
|
|
239
|
+
self.obj["summary"](X = r.matrix(FloatVector(X.ravel()),
|
|
240
|
+
byrow=True,
|
|
241
|
+
ncol=X.shape[1],
|
|
242
|
+
nrow=X.shape[0]),
|
|
243
|
+
y = FloatVector(y),
|
|
244
|
+
level = level,
|
|
245
|
+
show_progress = show_progress
|
|
246
|
+
)
|
|
247
|
+
else: # cl is not None, parallel computing
|
|
248
|
+
|
|
249
|
+
if self.type == "classification":
|
|
250
|
+
|
|
251
|
+
assert class_index is not None, "class_index must be provided for classification models"
|
|
252
|
+
|
|
253
|
+
self.obj["summary"](X = r.matrix(FloatVector(X.ravel()),
|
|
254
|
+
byrow=True,
|
|
255
|
+
ncol=X.shape[1],
|
|
256
|
+
nrow=X.shape[0]),
|
|
257
|
+
y = FactorVector(IntVector(y)),
|
|
258
|
+
level = level,
|
|
259
|
+
show_progress = show_progress,
|
|
260
|
+
class_index = class_index + 1,
|
|
261
|
+
cl = cl
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
else: # regression
|
|
265
|
+
|
|
266
|
+
self.obj["summary"](X = r.matrix(FloatVector(X.ravel()),
|
|
267
|
+
byrow=True,
|
|
268
|
+
ncol=X.shape[1],
|
|
269
|
+
nrow=X.shape[0]),
|
|
270
|
+
y = FloatVector(y),
|
|
271
|
+
level = level,
|
|
272
|
+
show_progress = show_progress,
|
|
273
|
+
cl = cl
|
|
274
|
+
)
|
|
@@ -0,0 +1,140 @@
|
|
|
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
|
+
FloatVector,
|
|
7
|
+
IntVector,
|
|
8
|
+
FactorVector,
|
|
9
|
+
ListVector
|
|
10
|
+
)
|
|
11
|
+
from sklearn.base import ClassifierMixin
|
|
12
|
+
from .base import Base
|
|
13
|
+
from .utils import format_value, r_list_to_namedtuple
|
|
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="none",
|
|
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
|
+
B=B,
|
|
47
|
+
nb_hidden=nb_hidden,
|
|
48
|
+
nodes_sim=nodes_sim,
|
|
49
|
+
activ=activ,
|
|
50
|
+
seed=seed,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self.type_prediction_set=type_prediction_set
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
self.obj = r(f"suppressWarnings(suppressMessages(library(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)})")
|
|
57
|
+
except NotImplementedError:
|
|
58
|
+
self.obj = r(
|
|
59
|
+
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)})"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# try:
|
|
63
|
+
# self.load_learningmachine()
|
|
64
|
+
# self.obj = r(
|
|
65
|
+
# 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)})"
|
|
66
|
+
# )
|
|
67
|
+
# except NotImplementedError as e:
|
|
68
|
+
# try:
|
|
69
|
+
# base.suppressWarnings(base.suppressMessages(r.library("learningmachine")))
|
|
70
|
+
# self.obj = r(
|
|
71
|
+
# 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)})"
|
|
72
|
+
# )
|
|
73
|
+
# except NotImplementedError as e:
|
|
74
|
+
# try:
|
|
75
|
+
# self.obj = r(
|
|
76
|
+
# f"""
|
|
77
|
+
# suppressWarnings(suppressMessages(library(learningmachine)));
|
|
78
|
+
# 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)})
|
|
79
|
+
# """
|
|
80
|
+
# )
|
|
81
|
+
# except NotImplementedError as e:
|
|
82
|
+
# print("R package can't be loaded: ", e)
|
|
83
|
+
|
|
84
|
+
def fit(self, X, y, **kwargs):
|
|
85
|
+
"""
|
|
86
|
+
Fit the model according to the given training data.
|
|
87
|
+
"""
|
|
88
|
+
params_dict = {}
|
|
89
|
+
for k, v in kwargs.items():
|
|
90
|
+
params_dict[k.replace('_', '.')] = v
|
|
91
|
+
self.obj["fit"](r.matrix(FloatVector(X.ravel()),
|
|
92
|
+
byrow=True,
|
|
93
|
+
ncol=X.shape[1],
|
|
94
|
+
nrow=X.shape[0]),
|
|
95
|
+
FactorVector(IntVector(y)),
|
|
96
|
+
**params_dict)
|
|
97
|
+
self.classes_ = np.unique(y) # /!\ do not remove
|
|
98
|
+
return self
|
|
99
|
+
|
|
100
|
+
def predict_proba(self, X):
|
|
101
|
+
"""
|
|
102
|
+
Predict using the model.
|
|
103
|
+
"""
|
|
104
|
+
if self.pi_method == "none":
|
|
105
|
+
res = self.obj["predict_proba"](
|
|
106
|
+
r.matrix(FloatVector(X.ravel()),
|
|
107
|
+
byrow=True,
|
|
108
|
+
ncol=X.shape[1],
|
|
109
|
+
nrow=X.shape[0])
|
|
110
|
+
)
|
|
111
|
+
return np.asarray(res)
|
|
112
|
+
return r_list_to_namedtuple(self.obj["predict_proba"](
|
|
113
|
+
r.matrix(FloatVector(X.ravel()),
|
|
114
|
+
byrow=True,
|
|
115
|
+
ncol=X.shape[1],
|
|
116
|
+
nrow=X.shape[0])
|
|
117
|
+
))
|
|
118
|
+
|
|
119
|
+
def predict(self, X):
|
|
120
|
+
"""
|
|
121
|
+
Predict using the model.
|
|
122
|
+
"""
|
|
123
|
+
if self.pi_method == "none":
|
|
124
|
+
return (
|
|
125
|
+
np.asarray(
|
|
126
|
+
self.obj["predict"](
|
|
127
|
+
r.matrix(FloatVector(X.ravel()),
|
|
128
|
+
byrow=True,
|
|
129
|
+
ncol=X.shape[1],
|
|
130
|
+
nrow=X.shape[0])
|
|
131
|
+
)
|
|
132
|
+
) - 1
|
|
133
|
+
)
|
|
134
|
+
return r_list_to_namedtuple(self.obj["predict"](
|
|
135
|
+
r.matrix(FloatVector(X.ravel()),
|
|
136
|
+
byrow=True,
|
|
137
|
+
ncol=X.shape[1],
|
|
138
|
+
nrow=X.shape[0])
|
|
139
|
+
))
|
|
140
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from rpy2.robjects import r
|
|
3
|
+
from rpy2.robjects.packages import importr
|
|
4
|
+
from rpy2.robjects.vectors import FloatVector, ListVector
|
|
5
|
+
from sklearn.base import RegressorMixin
|
|
6
|
+
from .base import Base
|
|
7
|
+
from .utils import format_value, r_list_to_namedtuple
|
|
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="none",
|
|
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.obj = r(f"suppressWarnings(suppressMessages(library(learningmachine))); Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, 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)})")
|
|
48
|
+
except NotImplementedError:
|
|
49
|
+
self.obj = r(
|
|
50
|
+
f"learningmachine::Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, 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)})"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# try:
|
|
54
|
+
# self.load_learningmachine()
|
|
55
|
+
# self.obj = r(
|
|
56
|
+
# f"learningmachine::Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, 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)})"
|
|
57
|
+
# )
|
|
58
|
+
# except NotImplementedError as e:
|
|
59
|
+
# try:
|
|
60
|
+
# base.suppressWarnings(base.suppressMessages(r.library("learningmachine")))
|
|
61
|
+
# self.obj = r(
|
|
62
|
+
# f"Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, 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
|
+
# except NotImplementedError as e:
|
|
65
|
+
# try:
|
|
66
|
+
# self.obj = r(
|
|
67
|
+
# f"""
|
|
68
|
+
# suppressWarnings(suppressMessages(library(learningmachine)));
|
|
69
|
+
# Regressor$new(method = {format_value(self.method)}, pi_method = {format_value(self.pi_method)}, level = {format_value(self.level)}, 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)})
|
|
70
|
+
# """
|
|
71
|
+
# )
|
|
72
|
+
# except NotImplementedError as e:
|
|
73
|
+
# print("R package can't be loaded: ", e)
|
|
74
|
+
|
|
75
|
+
def fit(self, X, y, **kwargs):
|
|
76
|
+
"""
|
|
77
|
+
Fit the model according to the given training data.
|
|
78
|
+
"""
|
|
79
|
+
params_dict = {}
|
|
80
|
+
for k, v in kwargs.items():
|
|
81
|
+
params_dict[k.replace('_', '.')] = v
|
|
82
|
+
self.obj["fit"](
|
|
83
|
+
r.matrix(FloatVector(X.ravel()),
|
|
84
|
+
byrow=True,
|
|
85
|
+
ncol=X.shape[1],
|
|
86
|
+
nrow=X.shape[0]),
|
|
87
|
+
FloatVector(y),
|
|
88
|
+
**params_dict
|
|
89
|
+
)
|
|
90
|
+
return self
|
|
91
|
+
|
|
92
|
+
def predict(self, X):
|
|
93
|
+
"""
|
|
94
|
+
Predict using the model.
|
|
95
|
+
"""
|
|
96
|
+
if self.pi_method == "none":
|
|
97
|
+
return(np.asarray(self.obj["predict"](
|
|
98
|
+
r.matrix(FloatVector(X.ravel()),
|
|
99
|
+
byrow=True,
|
|
100
|
+
ncol=X.shape[1],
|
|
101
|
+
nrow=X.shape[0])
|
|
102
|
+
)))
|
|
103
|
+
return r_list_to_namedtuple(self.obj["predict"](
|
|
104
|
+
r.matrix(FloatVector(X.ravel()),
|
|
105
|
+
byrow=True,
|
|
106
|
+
ncol=X.shape[1],
|
|
107
|
+
nrow=X.shape[0])
|
|
108
|
+
))
|
|
109
|
+
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import numpy as np
|
|
1
2
|
import subprocess
|
|
2
3
|
from rpy2.robjects import r
|
|
4
|
+
from rpy2.robjects import NULL as rNULL
|
|
5
|
+
from collections import namedtuple
|
|
3
6
|
|
|
4
7
|
|
|
5
8
|
def check_pkg_installed():
|
|
@@ -71,4 +74,22 @@ def format_value(value):
|
|
|
71
74
|
if isinstance(value, bool):
|
|
72
75
|
return f"{str(value).upper()}"
|
|
73
76
|
if isinstance(value, int) or isinstance(value, float):
|
|
74
|
-
return f"{value}"
|
|
77
|
+
return f"{value}"
|
|
78
|
+
|
|
79
|
+
# R list to namedtuple
|
|
80
|
+
def r_list_to_namedtuple(r_list):
|
|
81
|
+
# Extract the names from the R list
|
|
82
|
+
if r_list.names is rNULL:
|
|
83
|
+
##names = [f'obs{i+1}' for i in range(len(r_list))]
|
|
84
|
+
# Define a namedtuple type based on the names in the R list
|
|
85
|
+
##DescribeResult = namedtuple('DescribeResult', names)
|
|
86
|
+
# Extract elements from the R list and create a namedtuple
|
|
87
|
+
##elements = {name: r_list.rx2(i+1) for i, name in enumerate(names)}
|
|
88
|
+
##return DescribeResult(**elements)
|
|
89
|
+
return tuple([[int(r_list.rx2(i+1)[j]) for j in range(len(r_list.rx2(i+1)))] for i in range(len(r_list))])
|
|
90
|
+
names = r_list.names
|
|
91
|
+
# Define a namedtuple type based on the names in the R list
|
|
92
|
+
DescribeResult = namedtuple('DescribeResult', names)
|
|
93
|
+
# Extract elements from the R list and create a namedtuple
|
|
94
|
+
elements = {name: np.asarray(r_list.rx2(name)) for name in names}
|
|
95
|
+
return DescribeResult(**elements)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import subprocess
|
|
3
|
+
|
|
4
|
+
def check_r_installed():
|
|
5
|
+
current_platform = platform.system()
|
|
6
|
+
|
|
7
|
+
if current_platform == "Windows":
|
|
8
|
+
# Check if R is installed on Windows by checking the registry
|
|
9
|
+
try:
|
|
10
|
+
subprocess.run(
|
|
11
|
+
["reg", "query", "HKLM\\Software\\R-core\\R"], check=True
|
|
12
|
+
)
|
|
13
|
+
print("R is already installed on Windows.")
|
|
14
|
+
return True
|
|
15
|
+
except subprocess.CalledProcessError:
|
|
16
|
+
print("R is not installed on Windows.")
|
|
17
|
+
return False
|
|
18
|
+
|
|
19
|
+
elif current_platform == "Linux":
|
|
20
|
+
# Check if R is installed on Linux by checking if the 'R' executable is available
|
|
21
|
+
try:
|
|
22
|
+
subprocess.run(["which", "R"], check=True)
|
|
23
|
+
print("R is already installed on Linux.")
|
|
24
|
+
return True
|
|
25
|
+
except subprocess.CalledProcessError:
|
|
26
|
+
print("R is not installed on Linux.")
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
elif current_platform == "Darwin": # macOS
|
|
30
|
+
# Check if R is installed on macOS by checking if the 'R' executable is available
|
|
31
|
+
try:
|
|
32
|
+
subprocess.run(["which", "R"], check=True)
|
|
33
|
+
print("R is already installed on macOS.")
|
|
34
|
+
return True
|
|
35
|
+
except subprocess.CalledProcessError:
|
|
36
|
+
print("R is not installed on macOS.")
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
else:
|
|
40
|
+
print("Unsupported platform. Unable to check for R installation.")
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
def install_r():
|
|
44
|
+
|
|
45
|
+
current_platform = platform.system()
|
|
46
|
+
|
|
47
|
+
if current_platform == "Windows":
|
|
48
|
+
# Install R on Windows using PowerShell
|
|
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}'"
|
|
50
|
+
subprocess.run(install_command, shell=True)
|
|
51
|
+
|
|
52
|
+
elif current_platform == "Linux":
|
|
53
|
+
# Install R on Linux using the appropriate package manager (e.g., apt-get)
|
|
54
|
+
install_command = (
|
|
55
|
+
"sudo apt update -qq && sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9"
|
|
56
|
+
+ "&& sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu focal-cran40/'"
|
|
57
|
+
+ "&& sudo apt update"
|
|
58
|
+
+ "&& sudo apt -y install r-base"
|
|
59
|
+
)
|
|
60
|
+
subprocess.run(install_command, shell=True)
|
|
61
|
+
|
|
62
|
+
elif current_platform == "Darwin": # macOS
|
|
63
|
+
# Install R on macOS using Homebrew
|
|
64
|
+
install_command = "brew install r"
|
|
65
|
+
subprocess.run(install_command, shell=True)
|
|
66
|
+
|
|
67
|
+
else:
|
|
68
|
+
|
|
69
|
+
print("Unsupported platform. Unable to install R.")
|
|
70
|
+
|
|
71
|
+
def install_packages():
|
|
72
|
+
try:
|
|
73
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages('remotes', dependencies=TRUE)"])
|
|
74
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), dependencies=TRUE)"])
|
|
75
|
+
#subprocess.run(["Rscript", "-e", "utils::install.packages('learningmachine', repos='https://techtonique.r-universe.dev', dependencies=TRUE)"])
|
|
76
|
+
subprocess.run(["Rscript", "-e", "remotes::install_github('Techtonique/learningmachine')"])
|
|
77
|
+
except:
|
|
78
|
+
try:
|
|
79
|
+
subprocess.run(["mkdir", "-p", "r-learningmachine"])
|
|
80
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages('remotes', lib='r-learningmachine', dependencies=TRUE)"])
|
|
81
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), lib='r-learningmachine', dependencies=TRUE)"])
|
|
82
|
+
#subprocess.run(["Rscript", "-e", "utils::install.packages('learningmachine', repos='https://techtonique.r-universe.dev', lib='r-learningmachine', dependencies=TRUE)"])
|
|
83
|
+
subprocess.run(["Rscript", "-e", "remotes::install_github('Techtonique/learningmachine', lib='r-learningmachine')"])
|
|
84
|
+
except:
|
|
85
|
+
try:
|
|
86
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages('remotes', dependencies=TRUE)"])
|
|
87
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), dependencies=TRUE)"])
|
|
88
|
+
#subprocess.run(["Rscript", "-e", "utils::install.packages('learningmachine', repos='https://techtonique.r-universe.dev', dependencies=TRUE)"])
|
|
89
|
+
subprocess.run(["Rscript", "-e", "remotes::install_github('Techtonique/learningmachine')"])
|
|
90
|
+
except:
|
|
91
|
+
try:
|
|
92
|
+
subprocess.run(["mkdir", "-p", "r-learningmachine"])
|
|
93
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages('remotes', lib='r-learningmachine', dependencies=TRUE)"])
|
|
94
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), lib='r-learningmachine', dependencies=TRUE)"])
|
|
95
|
+
#subprocess.run(["Rscript", "-e", "utils::install.packages('learningmachine', repos='https://techtonique.r-universe.dev', lib='r-learningmachine', dependencies=TRUE)"])
|
|
96
|
+
subprocess.run(["Rscript", "-e", "remotes::install_github('Techtonique/learningmachine', lib='r-learningmachine')"])
|
|
97
|
+
except:
|
|
98
|
+
try:
|
|
99
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages('remotes', dependencies=TRUE)"])
|
|
100
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), dependencies=TRUE)"])
|
|
101
|
+
subprocess.run(["Rscript", "-e", "remotes::install_github('Techtonique/learningmachine')"])
|
|
102
|
+
except:
|
|
103
|
+
subprocess.run(["mkdir", "-p", "r-learningmachine"])
|
|
104
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages('remotes', lib='r-learningmachine', dependencies=TRUE)"])
|
|
105
|
+
subprocess.run(["Rscript", "-e", "utils::install.packages(c('R6', 'Rcpp', 'skimr'), lib='r-learningmachine', dependencies=TRUE)"])
|
|
106
|
+
subprocess.run(["Rscript", "-e", "remotes::install_github('Techtonique/learningmachine', lib='r-learningmachine')"])
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Check if R is installed; if not, install it
|
|
110
|
+
if not check_r_installed():
|
|
111
|
+
print("Installing R...")
|
|
112
|
+
install_r()
|
|
113
|
+
else:
|
|
114
|
+
print("No installation needed.")
|
|
115
|
+
|
|
116
|
+
install_packages()
|
|
117
|
+
|
|
118
|
+
subprocess.run(["pip", "install", "rpy2"])
|
|
119
|
+
|
|
120
|
+
from setuptools import setup, find_packages
|
|
121
|
+
from codecs import open
|
|
122
|
+
from os import path
|
|
123
|
+
|
|
124
|
+
# 4 - Package setup -----------------------------------------------
|
|
125
|
+
|
|
126
|
+
"""The setup script."""
|
|
127
|
+
|
|
128
|
+
setup(
|
|
129
|
+
author="T. Moudiki",
|
|
130
|
+
author_email="thierry.moudiki@gmail.com",
|
|
131
|
+
python_requires=">=3.6",
|
|
132
|
+
classifiers=[
|
|
133
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
134
|
+
"Intended Audience :: Developers",
|
|
135
|
+
"License :: OSI Approved :: BSD License",
|
|
136
|
+
"Natural Language :: English",
|
|
137
|
+
"Programming Language :: Python :: 3",
|
|
138
|
+
"Programming Language :: Python :: 3.6",
|
|
139
|
+
"Programming Language :: Python :: 3.7",
|
|
140
|
+
"Programming Language :: Python :: 3.8",
|
|
141
|
+
],
|
|
142
|
+
description="Machine Learning with uncertainty quantification and interpretability",
|
|
143
|
+
install_requires=['numpy', 'pandas', 'rpy2>=3.4.5', 'scikit-learn', 'scipy'],
|
|
144
|
+
license="BSD Clause Clear license",
|
|
145
|
+
long_description="Machine Learning with uncertainty quantification and interpretability.",
|
|
146
|
+
include_package_data=True,
|
|
147
|
+
keywords="learningmachine",
|
|
148
|
+
name="learningmachine",
|
|
149
|
+
packages=find_packages(include=["learningmachine", "learningmachine.*"]),
|
|
150
|
+
test_suite="tests",
|
|
151
|
+
url="https://github.com/Techtonique/learningmachine_python",
|
|
152
|
+
version="2.0.1",
|
|
153
|
+
zip_safe=False,
|
|
154
|
+
)
|
learningmachine-1.1.0/LICENSE
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
BSD License
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2024, T. Moudiki
|
|
6
|
-
All rights reserved.
|
|
7
|
-
|
|
8
|
-
Redistribution and use in source and binary forms, with or without modification,
|
|
9
|
-
are permitted provided that the following conditions are met:
|
|
10
|
-
|
|
11
|
-
* Redistributions of source code must retain the above copyright notice, this
|
|
12
|
-
list of conditions and the following disclaimer.
|
|
13
|
-
|
|
14
|
-
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
15
|
-
list of conditions and the following disclaimer in the documentation and/or
|
|
16
|
-
other materials provided with the distribution.
|
|
17
|
-
|
|
18
|
-
* Neither the name of the copyright holder nor the names of its
|
|
19
|
-
contributors may be used to endorse or promote products derived from this
|
|
20
|
-
software without specific prior written permission.
|
|
21
|
-
|
|
22
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
23
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
24
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
25
|
-
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
26
|
-
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
27
|
-
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
-
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
29
|
-
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
30
|
-
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
31
|
-
OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
-
|
learningmachine-1.1.0/README.rst
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
===============
|
|
2
|
-
learningmachine
|
|
3
|
-
===============
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
.. image:: https://img.shields.io/pypi/v/learningmachine.svg
|
|
7
|
-
:target: https://pypi.python.org/pypi/learningmachine
|
|
8
|
-
|
|
9
|
-
.. image:: https://img.shields.io/travis/Techtonique/learningmachine.svg
|
|
10
|
-
:target: https://travis-ci.com/Techtonique/learningmachine
|
|
11
|
-
|
|
12
|
-
.. image:: https://readthedocs.org/projects/learningmachine/badge/?version=latest
|
|
13
|
-
:target: https://learningmachine.readthedocs.io/en/latest/?version=latest
|
|
14
|
-
:alt: Documentation Status
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Machine Learning with uncertainty quantification and interpretability
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* Free software: BSD license
|
|
23
|
-
* Documentation: https://learningmachine.readthedocs.io.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Features
|
|
27
|
-
--------
|
|
28
|
-
|
|
29
|
-
* TODO
|
|
30
|
-
|
|
31
|
-
Credits
|
|
32
|
-
-------
|
|
33
|
-
|
|
34
|
-
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
|
|
35
|
-
|
|
36
|
-
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
|
|
37
|
-
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
|
|
@@ -1,134 +0,0 @@
|
|
|
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
|
-
)
|
|
@@ -1,92 +0,0 @@
|
|
|
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
|
-
)
|
learningmachine-1.1.0/setup.py
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
|
|
3
|
-
import platform
|
|
4
|
-
import subprocess
|
|
5
|
-
from os import path
|
|
6
|
-
from setuptools import setup, find_packages
|
|
7
|
-
|
|
8
|
-
# 0 - utility functions -----------------------------------------------
|
|
9
|
-
|
|
10
|
-
def check_r_installed():
|
|
11
|
-
current_platform = platform.system()
|
|
12
|
-
|
|
13
|
-
if current_platform == "Windows":
|
|
14
|
-
# Check if R is installed on Windows by checking the registry
|
|
15
|
-
try:
|
|
16
|
-
subprocess.run(
|
|
17
|
-
["reg", "query", "HKLM\\Software\\R-core\\R"], check=True
|
|
18
|
-
)
|
|
19
|
-
print("R is already installed on Windows.")
|
|
20
|
-
return True
|
|
21
|
-
except subprocess.CalledProcessError as e:
|
|
22
|
-
install_r(prompt=True)
|
|
23
|
-
return True
|
|
24
|
-
|
|
25
|
-
elif current_platform in ("Darwin", "Linux"):
|
|
26
|
-
# Check if R is installed on Linux by checking if the 'R' executable is available
|
|
27
|
-
|
|
28
|
-
try:
|
|
29
|
-
# Try to find the 'R' executable using 'which' (if available)
|
|
30
|
-
subprocess.check_call(['which', 'R'])
|
|
31
|
-
print(f"R is already installed on {current_platform}.")
|
|
32
|
-
return True
|
|
33
|
-
except subprocess.CalledProcessError:
|
|
34
|
-
# 'which' might not be available, or R is not installed
|
|
35
|
-
print('R may not be installed.')
|
|
36
|
-
install_r(prompt=True)
|
|
37
|
-
return True
|
|
38
|
-
|
|
39
|
-
else:
|
|
40
|
-
|
|
41
|
-
print("Unsupported platform (check manually: https://cloud.r-project.org/)")
|
|
42
|
-
return False
|
|
43
|
-
|
|
44
|
-
def install_r(prompt=False):
|
|
45
|
-
|
|
46
|
-
current_platform = platform.system()
|
|
47
|
-
|
|
48
|
-
if prompt == True:
|
|
49
|
-
print("Installing R...")
|
|
50
|
-
# choice = input("Would you like to install R? (yes/no): ").strip().lower()
|
|
51
|
-
# if choice == 'yes':
|
|
52
|
-
# print("Installing R...")
|
|
53
|
-
# elif choice == 'no':
|
|
54
|
-
# print("No problem. R will not be installed.")
|
|
55
|
-
# return
|
|
56
|
-
# else:
|
|
57
|
-
# print("Invalid input. Please enter 'yes' or 'no'.")
|
|
58
|
-
# return
|
|
59
|
-
|
|
60
|
-
if current_platform == "Windows":
|
|
61
|
-
# Install R on Windows using PowerShell
|
|
62
|
-
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}'"
|
|
63
|
-
subprocess.run(install_command, shell=True)
|
|
64
|
-
|
|
65
|
-
elif current_platform == "Linux":
|
|
66
|
-
# Install R on Linux using the appropriate package manager (e.g., apt-get)
|
|
67
|
-
install_command = (
|
|
68
|
-
"sudo apt update -qq && sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9"
|
|
69
|
-
+ "&& sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu focal-cran40/'"
|
|
70
|
-
+ "&& sudo apt update"
|
|
71
|
-
+ "&& sudo apt install r-base"
|
|
72
|
-
)
|
|
73
|
-
try:
|
|
74
|
-
subprocess.run(install_command, shell=True)
|
|
75
|
-
except NotImplementedError as e:
|
|
76
|
-
print("Error installing R on this Linux distribution. Please check manually: https://cloud.r-project.org/")
|
|
77
|
-
|
|
78
|
-
elif current_platform == "Darwin": # macOS
|
|
79
|
-
# Install R on macOS using Homebrew
|
|
80
|
-
install_command = "brew install r"
|
|
81
|
-
try:
|
|
82
|
-
subprocess.run(install_command, shell=True)
|
|
83
|
-
except NotImplementedError as e:
|
|
84
|
-
print("Error installing R on macOS. Please check manually: https://cloud.r-project.org/")
|
|
85
|
-
|
|
86
|
-
else:
|
|
87
|
-
print("Unsupported platform. Unable to install R.")
|
|
88
|
-
|
|
89
|
-
def load_learningmachine():
|
|
90
|
-
# Install R packages
|
|
91
|
-
commands1_lm = 'base::system.file(package = "learningmachine")' # check "learningmachine" is installed
|
|
92
|
-
commands2_lm = 'base::system.file("learningmachine_r", package = "learningmachine")' # check "learningmachine" is installed locally
|
|
93
|
-
exec_commands1_lm = subprocess.run(
|
|
94
|
-
["Rscript", "-e", commands1_lm], capture_output=True, text=True
|
|
95
|
-
)
|
|
96
|
-
exec_commands2_lm = subprocess.run(
|
|
97
|
-
["Rscript", "-e", commands2_lm], capture_output=True, text=True
|
|
98
|
-
)
|
|
99
|
-
if (
|
|
100
|
-
len(exec_commands1_lm.stdout) == 7
|
|
101
|
-
and len(exec_commands2_lm.stdout) == 7
|
|
102
|
-
): # kind of convoluted, but works
|
|
103
|
-
print("Installing R packages along with 'learningmachine'...")
|
|
104
|
-
commands1 = [
|
|
105
|
-
'try(utils::install.packages(c("R6", "Rcpp", "skimr"), repos="https://cloud.r-project.org", dependencies = TRUE), silent=TRUE)',
|
|
106
|
-
'try(utils::install.packages("learningmachine", repos="https://techtonique.r-universe.dev", dependencies = TRUE), silent=TRUE)',
|
|
107
|
-
]
|
|
108
|
-
commands2 = [
|
|
109
|
-
'try(utils::install.packages(c("R6", "Rcpp", "skimr"), lib="./learningmachine_r", repos="https://cloud.r-project.org", dependencies = TRUE), silent=TRUE)',
|
|
110
|
-
'try(utils::install.packages("learningmachine", lib="./learningmachine_r", repos="https://techtonique.r-universe.dev", dependencies = TRUE), silent=TRUE)',
|
|
111
|
-
]
|
|
112
|
-
commands3 = [
|
|
113
|
-
'try(utils::install.packages(c("R6", "Rcpp", "remotes", "skimr"), repos="https://cloud.r-project.org", dependencies = TRUE), silent=TRUE)',
|
|
114
|
-
'try(remotes::install_github("Techtonique/learningmachine"), silent=TRUE)',
|
|
115
|
-
]
|
|
116
|
-
commands4 = [
|
|
117
|
-
'try(utils::install.packages(c("R6", "Rcpp", "remotes", "skimr"), lib="./learningmachine_r", repos="https://cloud.r-project.org", dependencies = TRUE), silent=TRUE)',
|
|
118
|
-
'try(remotes::install_github("Techtonique/learningmachine", lib="./learningmachine_r", dependencies = TRUE), silent=TRUE)',
|
|
119
|
-
]
|
|
120
|
-
|
|
121
|
-
try:
|
|
122
|
-
for cmd in commands3:
|
|
123
|
-
try:
|
|
124
|
-
subprocess.run(["Rscript", "-e", cmd])
|
|
125
|
-
except:
|
|
126
|
-
pass
|
|
127
|
-
except NotImplementedError as e: # can't install packages globally
|
|
128
|
-
try:
|
|
129
|
-
subprocess.run(["mkdir", "learningmachine_r"])
|
|
130
|
-
for cmd in commands4:
|
|
131
|
-
try:
|
|
132
|
-
subprocess.run(["Rscript", "-e", cmd])
|
|
133
|
-
except:
|
|
134
|
-
pass
|
|
135
|
-
except NotImplementedError as e:
|
|
136
|
-
try:
|
|
137
|
-
for cmd in commands1:
|
|
138
|
-
try:
|
|
139
|
-
subprocess.run(["Rscript", "-e", cmd])
|
|
140
|
-
except:
|
|
141
|
-
pass
|
|
142
|
-
except NotImplementedError as e:
|
|
143
|
-
subprocess.run(["mkdir", "learningmachine_r"])
|
|
144
|
-
for cmd in commands2:
|
|
145
|
-
try:
|
|
146
|
-
subprocess.run(["Rscript", "-e", cmd])
|
|
147
|
-
except:
|
|
148
|
-
pass
|
|
149
|
-
|
|
150
|
-
# try:
|
|
151
|
-
# base.library(StrVector(["learningmachine"]))
|
|
152
|
-
# except (
|
|
153
|
-
# NotImplementedError
|
|
154
|
-
# ) as e1: # can't load the package from the global environment
|
|
155
|
-
# try:
|
|
156
|
-
# base.library(
|
|
157
|
-
# StrVector(["learningmachine"]), lib_loc="learningmachine_r"
|
|
158
|
-
# )
|
|
159
|
-
# except NotImplementedError as e2: # well, we tried
|
|
160
|
-
# try:
|
|
161
|
-
# r("try(library('learningmachine'), silence=TRUE)")
|
|
162
|
-
# except (
|
|
163
|
-
# NotImplementedError
|
|
164
|
-
# ) as e3: # well, we tried everything at this point
|
|
165
|
-
# r(
|
|
166
|
-
# "try(library('learningmachine', lib.loc='learningmachine_r'), silence=TRUE)"
|
|
167
|
-
# )
|
|
168
|
-
|
|
169
|
-
# 1 - import Python packages -----------------------------------------------
|
|
170
|
-
|
|
171
|
-
subprocess.run(["pip", "install", "rpy2"])
|
|
172
|
-
try:
|
|
173
|
-
subprocess.run(["pip", "install", "setuptools"])
|
|
174
|
-
except ModuleNotFoundError as e:
|
|
175
|
-
print("Error installing setuptools. Please install setuptools manually.")
|
|
176
|
-
|
|
177
|
-
from rpy2.robjects.packages import importr
|
|
178
|
-
from rpy2.robjects.vectors import StrVector
|
|
179
|
-
from rpy2.robjects import r
|
|
180
|
-
|
|
181
|
-
base = importr("base")
|
|
182
|
-
|
|
183
|
-
if not check_r_installed():
|
|
184
|
-
install_r()
|
|
185
|
-
else:
|
|
186
|
-
print("R is already installed.")
|
|
187
|
-
|
|
188
|
-
load_learningmachine()
|
|
189
|
-
|
|
190
|
-
# 4 - Package setup -----------------------------------------------
|
|
191
|
-
|
|
192
|
-
"""The setup script."""
|
|
193
|
-
|
|
194
|
-
setup(
|
|
195
|
-
author="T. Moudiki",
|
|
196
|
-
author_email="thierry.moudiki@gmail.com",
|
|
197
|
-
python_requires=">=3.6",
|
|
198
|
-
classifiers=[
|
|
199
|
-
"Development Status :: 2 - Pre-Alpha",
|
|
200
|
-
"Intended Audience :: Developers",
|
|
201
|
-
"License :: OSI Approved :: BSD License",
|
|
202
|
-
"Natural Language :: English",
|
|
203
|
-
"Programming Language :: Python :: 3",
|
|
204
|
-
"Programming Language :: Python :: 3.6",
|
|
205
|
-
"Programming Language :: Python :: 3.7",
|
|
206
|
-
"Programming Language :: Python :: 3.8",
|
|
207
|
-
],
|
|
208
|
-
description="Machine Learning with uncertainty quantification and interpretability",
|
|
209
|
-
install_requires=['numpy', 'pandas', 'rpy2>=3.4.5', 'scikit-learn', 'scipy'],
|
|
210
|
-
license="BSD Clause Clear license",
|
|
211
|
-
long_description="Machine Learning with uncertainty quantification and interpretability.",
|
|
212
|
-
include_package_data=True,
|
|
213
|
-
keywords="learningmachine",
|
|
214
|
-
name="learningmachine",
|
|
215
|
-
packages=find_packages(include=["learningmachine", "learningmachine.*"]),
|
|
216
|
-
test_suite="tests",
|
|
217
|
-
url="https://github.com/Techtonique/learningmachine_python",
|
|
218
|
-
version="1.1.0",
|
|
219
|
-
zip_safe=False,
|
|
220
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{learningmachine-1.1.0 → learningmachine-2.0.1}/learningmachine.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|