nnetsauce

 1from .base.base import Base
 2from .base.baseRegressor import BaseRegressor
 3from .boosting.adaBoostClassifier import AdaBoostClassifier
 4from .custom.customClassifier import CustomClassifier
 5from .custom.customRegressor import CustomRegressor
 6from .datasets import Downloader
 7from .deep.deepClassifier import DeepClassifier
 8from .deep.deepRegressor import DeepRegressor
 9from .deep.deepMTS import DeepMTS
10from .glm.glmClassifier import GLMClassifier
11from .glm.glmRegressor import GLMRegressor
12from .lazypredict.lazyClassifier import LazyClassifier
13from .lazypredict.lazyRegressor import LazyRegressor
14from .lazypredict.lazydeepClassifier import LazyDeepClassifier
15from .lazypredict.lazydeepRegressor import LazyDeepRegressor
16from .lazypredict.lazydeepMTS import LazyDeepMTS
17from .mts.mts import MTS
18from .mts.classical import ClassicalMTS
19from .multitask.multitaskClassifier import MultitaskClassifier
20from .multitask.simplemultitaskClassifier import SimpleMultitaskClassifier
21from .optimizers.optimizer import Optimizer
22from .predictioninterval import PredictionInterval
23from .randombag.randomBagClassifier import RandomBagClassifier
24from .randombag.randomBagRegressor import RandomBagRegressor
25from .ridge2.ridge2Classifier import Ridge2Classifier
26from .ridge2.ridge2Regressor import Ridge2Regressor
27from .ridge2.ridge2MultitaskClassifier import Ridge2MultitaskClassifier
28from .rvfl.bayesianrvflRegressor import BayesianRVFLRegressor
29from .rvfl.bayesianrvfl2Regressor import BayesianRVFL2Regressor
30from .sampling import SubSampler
31
32__all__ = [
33    "AdaBoostClassifier",
34    "Base",
35    "BaseRegressor",
36    "BayesianRVFLRegressor",
37    "BayesianRVFL2Regressor",
38    "ClassicalMTS",
39    "CustomClassifier",
40    "CustomRegressor",
41    "DeepClassifier",
42    "DeepRegressor",
43    "DeepMTS",
44    "Downloader",
45    "GLMClassifier",
46    "GLMRegressor",
47    "LazyClassifier",
48    "LazyRegressor",
49    "LazyDeepClassifier",
50    "LazyDeepRegressor",
51    "LazyDeepMTS",
52    "MTS",
53    "MultitaskClassifier",
54    "PredictionInterval",
55    "SimpleMultitaskClassifier",
56    "Optimizer",
57    "RandomBagRegressor",
58    "RandomBagClassifier",
59    "Ridge2Regressor",
60    "Ridge2Classifier",
61    "Ridge2MultitaskClassifier",
62    "SubSampler",
63]
class AdaBoostClassifier(nnetsauce.boosting.bst.Boosting, sklearn.base.ClassifierMixin):
 21class AdaBoostClassifier(Boosting, ClassifierMixin):
 22    """AdaBoost Classification (SAMME) model class derived from class Boosting
 23
 24    Parameters:
 25
 26        obj: object
 27            any object containing a method fit (obj.fit()) and a method predict
 28            (obj.predict())
 29
 30        n_estimators: int
 31            number of boosting iterations
 32
 33        learning_rate: float
 34            learning rate of the boosting procedure
 35
 36        n_hidden_features: int
 37            number of nodes in the hidden layer
 38
 39        reg_lambda: float
 40            regularization parameter for weights
 41
 42        reg_alpha: float
 43            controls compromize between l1 and l2 norm of weights
 44
 45        activation_name: str
 46            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 47
 48        a: float
 49            hyperparameter for 'prelu' or 'elu' activation function
 50
 51        nodes_sim: str
 52            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 53            'uniform'
 54
 55        bias: boolean
 56            indicates if the hidden layer contains a bias term (True) or not
 57            (False)
 58
 59        dropout: float
 60            regularization parameter; (random) percentage of nodes dropped out
 61            of the training
 62
 63        direct_link: boolean
 64            indicates if the original predictors are included (True) in model's
 65            fitting or not (False)
 66
 67        n_clusters: int
 68            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 69                no clustering)
 70
 71        cluster_encode: bool
 72            defines how the variable containing clusters is treated (default is one-hot)
 73            if `False`, then labels are used, without one-hot encoding
 74
 75        type_clust: str
 76            type of clustering method: currently k-means ('kmeans') or Gaussian
 77            Mixture Model ('gmm')
 78
 79        type_scaling: a tuple of 3 strings
 80            scaling methods for inputs, hidden layer, and clustering respectively
 81            (and when relevant).
 82            Currently available: standardization ('std') or MinMax scaling ('minmax')
 83
 84        col_sample: float
 85            percentage of covariates randomly chosen for training
 86
 87        row_sample: float
 88            percentage of rows chosen for training, by stratified bootstrapping
 89
 90        seed: int
 91            reproducibility seed for nodes_sim=='uniform'
 92
 93        verbose: int
 94            0 for no output, 1 for a progress bar (default is 1)
 95
 96        method: str
 97            type of Adaboost method, 'SAMME' (discrete) or 'SAMME.R' (real)
 98
 99        backend: str
100            "cpu" or "gpu" or "tpu"
101
102    Attributes:
103
104        alpha_: list
105            AdaBoost coefficients alpha_m
106
107        base_learners_: dict
108            a dictionary containing the base learners
109
110    Examples:
111
112    See also [https://github.com/Techtonique/nnetsauce/blob/master/examples/adaboost_classification.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/adaboost_classification.py)
113
114    ```python
115    import nnetsauce as ns
116    import numpy as np
117    from sklearn.datasets import load_breast_cancer
118    from sklearn.linear_model import LogisticRegression
119    from sklearn.model_selection import train_test_split
120    from sklearn import metrics
121    from time import time
122
123    breast_cancer = load_breast_cancer()
124    Z = breast_cancer.data
125    t = breast_cancer.target
126    np.random.seed(123)
127    X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2)
128
129    # SAMME.R
130    clf = LogisticRegression(solver='liblinear', multi_class = 'ovr',
131                            random_state=123)
132    fit_obj = ns.AdaBoostClassifier(clf,
133                                    n_hidden_features=int(11.22338867),
134                                    direct_link=True,
135                                    n_estimators=250, learning_rate=0.01126343,
136                                    col_sample=0.72684326, row_sample=0.86429443,
137                                    dropout=0.63078613, n_clusters=2,
138                                    type_clust="gmm",
139                                    verbose=1, seed = 123,
140                                    method="SAMME.R")
141
142    start = time()
143    fit_obj.fit(X_train, y_train)
144    print(f"Elapsed {time() - start}")
145
146    start = time()
147    print(fit_obj.score(X_test, y_test))
148    print(f"Elapsed {time() - start}")
149
150    preds = fit_obj.predict(X_test)
151
152    print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
153    print(metrics.classification_report(preds, y_test))
154
155    ```
156
157    """
158
159    # construct the object -----
160
161    def __init__(
162        self,
163        obj,
164        n_estimators=10,
165        learning_rate=0.1,
166        n_hidden_features=1,
167        reg_lambda=0,
168        reg_alpha=0.5,
169        activation_name="relu",
170        a=0.01,
171        nodes_sim="sobol",
172        bias=True,
173        dropout=0,
174        direct_link=False,
175        n_clusters=2,
176        cluster_encode=True,
177        type_clust="kmeans",
178        type_scaling=("std", "std", "std"),
179        col_sample=1,
180        row_sample=1,
181        seed=123,
182        verbose=1,
183        method="SAMME",
184        backend="cpu",
185    ):
186        self.type_fit = "classification"
187        self.verbose = verbose
188        self.method = method
189        self.reg_lambda = reg_lambda
190        self.reg_alpha = reg_alpha
191
192        super().__init__(
193            obj=obj,
194            n_estimators=n_estimators,
195            learning_rate=learning_rate,
196            n_hidden_features=n_hidden_features,
197            activation_name=activation_name,
198            a=a,
199            nodes_sim=nodes_sim,
200            bias=bias,
201            dropout=dropout,
202            direct_link=direct_link,
203            n_clusters=n_clusters,
204            cluster_encode=cluster_encode,
205            type_clust=type_clust,
206            type_scaling=type_scaling,
207            col_sample=col_sample,
208            row_sample=row_sample,
209            seed=seed,
210            backend=backend,
211        )
212
213        self.alpha_ = []
214        self.base_learners_ = dict.fromkeys(range(n_estimators))
215
216    def fit(self, X, y, sample_weight=None, **kwargs):
217        """Fit Boosting model to training data (X, y).
218
219        Parameters:
220
221            X: {array-like}, shape = [n_samples, n_features]
222                Training vectors, where n_samples is the number
223                of samples and n_features is the number of features.
224
225            y: array-like, shape = [n_samples]
226                Target values.
227
228            **kwargs: additional parameters to be passed to
229                    self.cook_training_set or self.obj.fit
230
231        Returns:
232
233             self: object
234        """
235
236        assert mx.is_factor(y), "y must contain only integers"
237
238        assert self.method in (
239            "SAMME",
240            "SAMME.R",
241        ), "`method` must be either 'SAMME' or 'SAMME.R'"
242
243        assert (self.reg_lambda <= 1) & (
244            self.reg_lambda >= 0
245        ), "must have self.reg_lambda <= 1 &  self.reg_lambda >= 0"
246
247        assert (self.reg_alpha <= 1) & (
248            self.reg_alpha >= 0
249        ), "must have self.reg_alpha <= 1 &  self.reg_alpha >= 0"
250
251        # training
252        n, p = X.shape
253        self.n_classes = len(np.unique(y))
254        self.classes_ = np.unique(y)  # for compatibility with sklearn
255        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
256
257        if sample_weight is None:
258            w_m = np.repeat(1.0 / n, n)
259        else:
260            w_m = np.asarray(sample_weight)
261
262        base_learner = CustomClassifier(
263            self.obj,
264            n_hidden_features=self.n_hidden_features,
265            activation_name=self.activation_name,
266            a=self.a,
267            nodes_sim=self.nodes_sim,
268            bias=self.bias,
269            dropout=self.dropout,
270            direct_link=self.direct_link,
271            n_clusters=self.n_clusters,
272            type_clust=self.type_clust,
273            type_scaling=self.type_scaling,
274            col_sample=self.col_sample,
275            row_sample=self.row_sample,
276            seed=self.seed,
277        )
278
279        if self.verbose == 1:
280            pbar = Progbar(self.n_estimators)
281
282        if self.method == "SAMME":
283            err_m = 1e6
284            err_bound = 1 - 1 / self.n_classes
285            self.alpha_.append(1.0)
286            x_range_n = range(n)
287
288            for m in range(self.n_estimators):
289                preds = base_learner.fit(
290                    X, y, sample_weight=w_m.ravel(), **kwargs
291                ).predict(X)
292
293                self.base_learners_.update(
294                    {m: pickle.loads(pickle.dumps(base_learner, -1))}
295                )
296
297                cond = [y[i] != preds[i] for i in x_range_n]
298
299                err_m = max(
300                    sum([elt[0] * elt[1] for elt in zip(cond, w_m)]),
301                    2.220446049250313e-16,
302                )  # sum(w_m) == 1
303
304                if self.reg_lambda > 0:
305                    err_m += self.reg_lambda * (
306                        (1 - self.reg_alpha) * 0.5 * sum([x**2 for x in w_m])
307                        + self.reg_alpha * sum([abs(x) for x in w_m])
308                    )
309
310                err_m = min(err_m, err_bound)
311
312                alpha_m = self.learning_rate * log(
313                    (self.n_classes - 1) * (1 - err_m) / err_m
314                )
315
316                self.alpha_.append(alpha_m)
317
318                w_m_temp = [exp(alpha_m * cond[i]) for i in x_range_n]
319
320                sum_w_m = sum(w_m_temp)
321
322                w_m = np.asarray([w_m_temp[i] / sum_w_m for i in x_range_n])
323
324                base_learner.set_params(seed=self.seed + (m + 1) * 1000)
325
326                if self.verbose == 1:
327                    pbar.update(m)
328
329            if self.verbose == 1:
330                pbar.update(self.n_estimators)
331
332            self.n_estimators = len(self.base_learners_)
333            self.classes_ = np.unique(y)
334
335            return self
336
337        if self.method == "SAMME.R":
338            Y = mo.one_hot_encode2(y, self.n_classes)
339
340            if sample_weight is None:
341                w_m = np.repeat(1.0 / n, n)  # (N, 1)
342
343            else:
344                w_m = np.asarray(sample_weight)
345
346            for m in range(self.n_estimators):
347                probs = base_learner.fit(
348                    X, y, sample_weight=w_m.ravel(), **kwargs
349                ).predict_proba(X)
350
351                np.clip(
352                    a=probs, a_min=2.220446049250313e-16, a_max=1.0, out=probs
353                )
354
355                self.base_learners_.update(
356                    {m: pickle.loads(pickle.dumps(base_learner, -1))}
357                )
358
359                w_m *= np.exp(
360                    -1.0
361                    * self.learning_rate
362                    * (1.0 - 1.0 / self.n_classes)
363                    * xlogy(Y, probs).sum(axis=1)
364                )
365
366                w_m /= np.sum(w_m)
367
368                base_learner.set_params(seed=self.seed + (m + 1) * 1000)
369
370                if self.verbose == 1:
371                    pbar.update(m)
372
373            if self.verbose == 1:
374                pbar.update(self.n_estimators)
375
376            self.n_estimators = len(self.base_learners_)
377            self.classes_ = np.unique(y)
378
379            return self
380
381    def predict(self, X, **kwargs):
382        """Predict test data X.
383
384        Parameters:
385
386            X: {array-like}, shape = [n_samples, n_features]
387                Training vectors, where n_samples is the number
388                of samples and n_features is the number of features.
389
390            **kwargs: additional parameters to be passed to
391                  self.cook_test_set
392
393        Returns:
394
395            model predictions: {array-like}
396        """
397        return self.predict_proba(X, **kwargs).argmax(axis=1)
398
399    def predict_proba(self, X, **kwargs):
400        """Predict probabilities for test data X.
401
402        Parameters:
403
404            X: {array-like}, shape = [n_samples, n_features]
405                Training vectors, where n_samples is the number
406                of samples and n_features is the number of features.
407
408            **kwargs: additional parameters to be passed to
409                  self.cook_test_set
410
411        Returns:
412
413            probability estimates for test data: {array-like}
414
415        """
416
417        n_iter = len(self.base_learners_)
418
419        if self.method == "SAMME":
420            ensemble_learner = np.zeros((X.shape[0], self.n_classes))
421
422            # if self.verbose == 1:
423            #    pbar = Progbar(n_iter)
424
425            for idx, base_learner in self.base_learners_.items():
426                preds = base_learner.predict(X, **kwargs)
427
428                ensemble_learner += self.alpha_[idx] * mo.one_hot_encode2(
429                    preds, self.n_classes
430                )
431
432                # if self.verbose == 1:
433                #    pbar.update(idx)
434
435            # if self.verbose == 1:
436            #    pbar.update(n_iter)
437
438            expit_ensemble_learner = expit(ensemble_learner)
439
440            sum_ensemble = expit_ensemble_learner.sum(axis=1)
441
442            return expit_ensemble_learner / sum_ensemble[:, None]
443
444        # if self.method == "SAMME.R":
445        ensemble_learner = 0
446
447        # if self.verbose == 1:
448        #    pbar = Progbar(n_iter)
449
450        for idx, base_learner in self.base_learners_.items():
451            probs = base_learner.predict_proba(X, **kwargs)
452
453            np.clip(a=probs, a_min=2.220446049250313e-16, a_max=1.0, out=probs)
454
455            log_preds_proba = np.log(probs)
456
457            ensemble_learner += (
458                log_preds_proba - log_preds_proba.mean(axis=1)[:, None]
459            )
460
461            # if self.verbose == 1:
462            #    pbar.update(idx)
463
464        ensemble_learner *= self.n_classes - 1
465
466        # if self.verbose == 1:
467        #    pbar.update(n_iter)
468
469        expit_ensemble_learner = expit(ensemble_learner)
470
471        sum_ensemble = expit_ensemble_learner.sum(axis=1)
472
473        return expit_ensemble_learner / sum_ensemble[:, None]

AdaBoost Classification (SAMME) model class derived from class Boosting

Parameters:

obj: object
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict())

n_estimators: int
    number of boosting iterations

learning_rate: float
    learning rate of the boosting procedure

n_hidden_features: int
    number of nodes in the hidden layer

reg_lambda: float
    regularization parameter for weights

reg_alpha: float
    controls compromize between l1 and l2 norm of weights

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

col_sample: float
    percentage of covariates randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

seed: int
    reproducibility seed for nodes_sim=='uniform'

verbose: int
    0 for no output, 1 for a progress bar (default is 1)

method: str
    type of Adaboost method, 'SAMME' (discrete) or 'SAMME.R' (real)

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

alpha_: list
    AdaBoost coefficients alpha_m

base_learners_: dict
    a dictionary containing the base learners

Examples:

See also https://github.com/Techtonique/nnetsauce/blob/master/examples/adaboost_classification.py

import nnetsauce as ns
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn import metrics
from time import time

breast_cancer = load_breast_cancer()
Z = breast_cancer.data
t = breast_cancer.target
np.random.seed(123)
X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2)

# SAMME.R
clf = LogisticRegression(solver='liblinear', multi_class = 'ovr',
                        random_state=123)
fit_obj = ns.AdaBoostClassifier(clf,
                                n_hidden_features=int(11.22338867),
                                direct_link=True,
                                n_estimators=250, learning_rate=0.01126343,
                                col_sample=0.72684326, row_sample=0.86429443,
                                dropout=0.63078613, n_clusters=2,
                                type_clust="gmm",
                                verbose=1, seed = 123,
                                method="SAMME.R")

start = time()
fit_obj.fit(X_train, y_train)
print(f"Elapsed {time() - start}")

start = time()
print(fit_obj.score(X_test, y_test))
print(f"Elapsed {time() - start}")

preds = fit_obj.predict(X_test)

print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
print(metrics.classification_report(preds, y_test))
def fit(self, X, y, sample_weight=None, **kwargs):
216    def fit(self, X, y, sample_weight=None, **kwargs):
217        """Fit Boosting model to training data (X, y).
218
219        Parameters:
220
221            X: {array-like}, shape = [n_samples, n_features]
222                Training vectors, where n_samples is the number
223                of samples and n_features is the number of features.
224
225            y: array-like, shape = [n_samples]
226                Target values.
227
228            **kwargs: additional parameters to be passed to
229                    self.cook_training_set or self.obj.fit
230
231        Returns:
232
233             self: object
234        """
235
236        assert mx.is_factor(y), "y must contain only integers"
237
238        assert self.method in (
239            "SAMME",
240            "SAMME.R",
241        ), "`method` must be either 'SAMME' or 'SAMME.R'"
242
243        assert (self.reg_lambda <= 1) & (
244            self.reg_lambda >= 0
245        ), "must have self.reg_lambda <= 1 &  self.reg_lambda >= 0"
246
247        assert (self.reg_alpha <= 1) & (
248            self.reg_alpha >= 0
249        ), "must have self.reg_alpha <= 1 &  self.reg_alpha >= 0"
250
251        # training
252        n, p = X.shape
253        self.n_classes = len(np.unique(y))
254        self.classes_ = np.unique(y)  # for compatibility with sklearn
255        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
256
257        if sample_weight is None:
258            w_m = np.repeat(1.0 / n, n)
259        else:
260            w_m = np.asarray(sample_weight)
261
262        base_learner = CustomClassifier(
263            self.obj,
264            n_hidden_features=self.n_hidden_features,
265            activation_name=self.activation_name,
266            a=self.a,
267            nodes_sim=self.nodes_sim,
268            bias=self.bias,
269            dropout=self.dropout,
270            direct_link=self.direct_link,
271            n_clusters=self.n_clusters,
272            type_clust=self.type_clust,
273            type_scaling=self.type_scaling,
274            col_sample=self.col_sample,
275            row_sample=self.row_sample,
276            seed=self.seed,
277        )
278
279        if self.verbose == 1:
280            pbar = Progbar(self.n_estimators)
281
282        if self.method == "SAMME":
283            err_m = 1e6
284            err_bound = 1 - 1 / self.n_classes
285            self.alpha_.append(1.0)
286            x_range_n = range(n)
287
288            for m in range(self.n_estimators):
289                preds = base_learner.fit(
290                    X, y, sample_weight=w_m.ravel(), **kwargs
291                ).predict(X)
292
293                self.base_learners_.update(
294                    {m: pickle.loads(pickle.dumps(base_learner, -1))}
295                )
296
297                cond = [y[i] != preds[i] for i in x_range_n]
298
299                err_m = max(
300                    sum([elt[0] * elt[1] for elt in zip(cond, w_m)]),
301                    2.220446049250313e-16,
302                )  # sum(w_m) == 1
303
304                if self.reg_lambda > 0:
305                    err_m += self.reg_lambda * (
306                        (1 - self.reg_alpha) * 0.5 * sum([x**2 for x in w_m])
307                        + self.reg_alpha * sum([abs(x) for x in w_m])
308                    )
309
310                err_m = min(err_m, err_bound)
311
312                alpha_m = self.learning_rate * log(
313                    (self.n_classes - 1) * (1 - err_m) / err_m
314                )
315
316                self.alpha_.append(alpha_m)
317
318                w_m_temp = [exp(alpha_m * cond[i]) for i in x_range_n]
319
320                sum_w_m = sum(w_m_temp)
321
322                w_m = np.asarray([w_m_temp[i] / sum_w_m for i in x_range_n])
323
324                base_learner.set_params(seed=self.seed + (m + 1) * 1000)
325
326                if self.verbose == 1:
327                    pbar.update(m)
328
329            if self.verbose == 1:
330                pbar.update(self.n_estimators)
331
332            self.n_estimators = len(self.base_learners_)
333            self.classes_ = np.unique(y)
334
335            return self
336
337        if self.method == "SAMME.R":
338            Y = mo.one_hot_encode2(y, self.n_classes)
339
340            if sample_weight is None:
341                w_m = np.repeat(1.0 / n, n)  # (N, 1)
342
343            else:
344                w_m = np.asarray(sample_weight)
345
346            for m in range(self.n_estimators):
347                probs = base_learner.fit(
348                    X, y, sample_weight=w_m.ravel(), **kwargs
349                ).predict_proba(X)
350
351                np.clip(
352                    a=probs, a_min=2.220446049250313e-16, a_max=1.0, out=probs
353                )
354
355                self.base_learners_.update(
356                    {m: pickle.loads(pickle.dumps(base_learner, -1))}
357                )
358
359                w_m *= np.exp(
360                    -1.0
361                    * self.learning_rate
362                    * (1.0 - 1.0 / self.n_classes)
363                    * xlogy(Y, probs).sum(axis=1)
364                )
365
366                w_m /= np.sum(w_m)
367
368                base_learner.set_params(seed=self.seed + (m + 1) * 1000)
369
370                if self.verbose == 1:
371                    pbar.update(m)
372
373            if self.verbose == 1:
374                pbar.update(self.n_estimators)
375
376            self.n_estimators = len(self.base_learners_)
377            self.classes_ = np.unique(y)
378
379            return self

Fit Boosting model to training data (X, y).

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

 self: object
def predict(self, X, **kwargs):
381    def predict(self, X, **kwargs):
382        """Predict test data X.
383
384        Parameters:
385
386            X: {array-like}, shape = [n_samples, n_features]
387                Training vectors, where n_samples is the number
388                of samples and n_features is the number of features.
389
390            **kwargs: additional parameters to be passed to
391                  self.cook_test_set
392
393        Returns:
394
395            model predictions: {array-like}
396        """
397        return self.predict_proba(X, **kwargs).argmax(axis=1)

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
      self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
399    def predict_proba(self, X, **kwargs):
400        """Predict probabilities for test data X.
401
402        Parameters:
403
404            X: {array-like}, shape = [n_samples, n_features]
405                Training vectors, where n_samples is the number
406                of samples and n_features is the number of features.
407
408            **kwargs: additional parameters to be passed to
409                  self.cook_test_set
410
411        Returns:
412
413            probability estimates for test data: {array-like}
414
415        """
416
417        n_iter = len(self.base_learners_)
418
419        if self.method == "SAMME":
420            ensemble_learner = np.zeros((X.shape[0], self.n_classes))
421
422            # if self.verbose == 1:
423            #    pbar = Progbar(n_iter)
424
425            for idx, base_learner in self.base_learners_.items():
426                preds = base_learner.predict(X, **kwargs)
427
428                ensemble_learner += self.alpha_[idx] * mo.one_hot_encode2(
429                    preds, self.n_classes
430                )
431
432                # if self.verbose == 1:
433                #    pbar.update(idx)
434
435            # if self.verbose == 1:
436            #    pbar.update(n_iter)
437
438            expit_ensemble_learner = expit(ensemble_learner)
439
440            sum_ensemble = expit_ensemble_learner.sum(axis=1)
441
442            return expit_ensemble_learner / sum_ensemble[:, None]
443
444        # if self.method == "SAMME.R":
445        ensemble_learner = 0
446
447        # if self.verbose == 1:
448        #    pbar = Progbar(n_iter)
449
450        for idx, base_learner in self.base_learners_.items():
451            probs = base_learner.predict_proba(X, **kwargs)
452
453            np.clip(a=probs, a_min=2.220446049250313e-16, a_max=1.0, out=probs)
454
455            log_preds_proba = np.log(probs)
456
457            ensemble_learner += (
458                log_preds_proba - log_preds_proba.mean(axis=1)[:, None]
459            )
460
461            # if self.verbose == 1:
462            #    pbar.update(idx)
463
464        ensemble_learner *= self.n_classes - 1
465
466        # if self.verbose == 1:
467        #    pbar.update(n_iter)
468
469        expit_ensemble_learner = expit(ensemble_learner)
470
471        sum_ensemble = expit_ensemble_learner.sum(axis=1)
472
473        return expit_ensemble_learner / sum_ensemble[:, None]

Predict probabilities for test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
      self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class Base(sklearn.base.BaseEstimator):
 34class Base(BaseEstimator):
 35    """Base model from which all the other classes inherit.
 36
 37    This class contains the most important data preprocessing/feature engineering methods.
 38
 39    Parameters:
 40
 41        n_hidden_features: int
 42            number of nodes in the hidden layer
 43
 44        activation_name: str
 45            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 46
 47        a: float
 48            hyperparameter for 'prelu' or 'elu' activation function
 49
 50        nodes_sim: str
 51            type of simulation for hidden layer nodes: 'sobol', 'hammersley', 'halton',
 52            'uniform'
 53
 54        bias: boolean
 55            indicates if the hidden layer contains a bias term (True) or
 56            not (False)
 57
 58        dropout: float
 59            regularization parameter; (random) percentage of nodes dropped out
 60            of the training
 61
 62        direct_link: boolean
 63            indicates if the original features are included (True) in model's
 64            fitting or not (False)
 65
 66        n_clusters: int
 67            number of clusters for type_clust='kmeans' or type_clust='gmm'
 68            clustering (could be 0: no clustering)
 69
 70        cluster_encode: bool
 71            defines how the variable containing clusters is treated (default is one-hot);
 72            if `False`, then labels are used, without one-hot encoding
 73
 74        type_clust: str
 75            type of clustering method: currently k-means ('kmeans') or Gaussian
 76            Mixture Model ('gmm')
 77
 78        type_scaling: a tuple of 3 strings
 79            scaling methods for inputs, hidden layer, and clustering respectively
 80            (and when relevant).
 81            Currently available: standardization ('std') or MinMax scaling ('minmax') or robust scaling ('robust') or  max absolute scaling ('maxabs')
 82
 83        col_sample: float
 84            percentage of features randomly chosen for training
 85
 86        row_sample: float
 87            percentage of rows chosen for training, by stratified bootstrapping
 88
 89        seed: int
 90            reproducibility seed for nodes_sim=='uniform', clustering and dropout
 91
 92        backend: str
 93            "cpu" or "gpu" or "tpu"
 94
 95    """
 96
 97    # construct the object -----
 98
 99    def __init__(
100        self,
101        n_hidden_features=5,
102        activation_name="relu",
103        a=0.01,
104        nodes_sim="sobol",
105        bias=True,
106        dropout=0,
107        direct_link=True,
108        n_clusters=2,
109        cluster_encode=True,
110        type_clust="kmeans",
111        type_scaling=("std", "std", "std"),
112        col_sample=1,
113        row_sample=1,
114        seed=123,
115        backend="cpu",
116    ):
117        # input checks -----
118
119        sys_platform = platform.system()
120
121        if (sys_platform == "Windows") and (backend in ("gpu", "tpu")):
122            warnings.warn(
123                "No GPU/TPU computing on Windows yet, backend set to 'cpu'"
124            )
125            backend = "cpu"
126
127        assert activation_name in (
128            "relu",
129            "tanh",
130            "sigmoid",
131            "prelu",
132            "elu",
133        ), "'activation_name' must be in ('relu', 'tanh', 'sigmoid','prelu', 'elu')"
134
135        assert nodes_sim in (
136            "sobol",
137            "hammersley",
138            "uniform",
139            "halton",
140        ), "'nodes_sim' must be in ('sobol', 'hammersley', 'uniform', 'halton')"
141
142        assert type_clust in (
143            "kmeans",
144            "gmm",
145        ), "'type_clust' must be in ('kmeans', 'gmm')"
146
147        assert (len(type_scaling) == 3) & all(
148            type_scaling[i] in ("minmax", "std", "robust", "maxabs")
149            for i in range(len(type_scaling))
150        ), "'type_scaling' must have length 3, and available scaling methods are 'minmax' scaling, standardization ('std'), robust scaling ('robust') and max absolute ('maxabs')"
151
152        assert (col_sample >= 0) & (
153            col_sample <= 1
154        ), "'col_sample' must be comprised between 0 and 1 (both included)"
155
156        assert backend in (
157            "cpu",
158            "gpu",
159            "tpu",
160        ), "must have 'backend' in ('cpu', 'gpu', 'tpu')"
161
162        self.n_hidden_features = n_hidden_features
163        self.activation_name = activation_name
164        self.a = a
165        self.nodes_sim = nodes_sim
166        self.bias = bias
167        self.seed = seed
168        self.backend = backend
169        self.dropout = dropout
170        self.direct_link = direct_link
171        self.cluster_encode = cluster_encode
172        self.type_clust = type_clust
173        self.type_scaling = type_scaling
174        self.col_sample = col_sample
175        self.row_sample = row_sample
176        self.n_clusters = n_clusters
177        if isinstance(self, RegressorMixin):
178            self.type_fit = "regression"
179        elif isinstance(self, ClassifierMixin):
180            self.type_fit = "classification"
181        self.subsampler_ = None
182        self.index_col_ = None
183        self.index_row_ = True
184        self.clustering_obj_ = None
185        self.clustering_scaler_ = None
186        self.nn_scaler_ = None
187        self.scaler_ = None
188        self.encoder_ = None
189        self.W_ = None
190        self.X_ = None
191        self.y_ = None
192        self.y_mean_ = None
193        self.beta_ = None
194
195        # activation function -----
196        if sys_platform in ("Linux", "Darwin"):
197            activation_options = {
198                "relu": ac.relu if (self.backend == "cpu") else jnn.relu,
199                "tanh": np.tanh if (self.backend == "cpu") else jnp.tanh,
200                "sigmoid": (
201                    ac.sigmoid if (self.backend == "cpu") else jnn.sigmoid
202                ),
203                "prelu": partial(ac.prelu, a=a),
204                "elu": (
205                    partial(ac.elu, a=a)
206                    if (self.backend == "cpu")
207                    else partial(jnn.elu, a=a)
208                ),
209            }
210        else:  # on Windows currently, no JAX
211            activation_options = {
212                "relu": (
213                    ac.relu if (self.backend == "cpu") else NotImplementedError
214                ),
215                "tanh": (
216                    np.tanh if (self.backend == "cpu") else NotImplementedError
217                ),
218                "sigmoid": (
219                    ac.sigmoid
220                    if (self.backend == "cpu")
221                    else NotImplementedError
222                ),
223                "prelu": partial(ac.prelu, a=a),
224                "elu": (
225                    partial(ac.elu, a=a)
226                    if (self.backend == "cpu")
227                    else NotImplementedError
228                ),
229            }
230        self.activation_func = activation_options[activation_name]
231
232    # "preprocessing" methods to be inherited -----
233
234    def encode_clusters(self, X=None, predict=False, **kwargs):  #
235        """Create new covariates with kmeans or GMM clustering
236
237        Parameters:
238
239            X: {array-like}, shape = [n_samples, n_features]
240                Training vectors, where n_samples is the number
241                of samples and n_features is the number of features.
242
243            predict: boolean
244                is False on training set and True on test set
245
246            **kwargs:
247                additional parameters to be passed to the
248                clustering method
249
250        Returns:
251
252            Clusters' matrix, one-hot encoded: {array-like}
253
254        """
255
256        np.random.seed(self.seed)
257
258        if X is None:
259            X = self.X_
260
261        if isinstance(X, pd.DataFrame):
262            X = copy.deepcopy(X.values.astype(float))
263
264        if predict is False:  # encode training set
265            # scale input data before clustering
266            self.clustering_scaler_, scaled_X = mo.scale_covariates(
267                X, choice=self.type_scaling[2]
268            )
269
270            self.clustering_obj_, X_clustered = mo.cluster_covariates(
271                scaled_X,
272                self.n_clusters,
273                self.seed,
274                type_clust=self.type_clust,
275                **kwargs
276            )
277
278            if self.cluster_encode == True:
279                return mo.one_hot_encode(X_clustered, self.n_clusters).astype(
280                    np.float16
281                )
282
283            return X_clustered.astype(np.float16)
284
285        # if predict == True, encode test set
286        X_clustered = self.clustering_obj_.predict(
287            self.clustering_scaler_.transform(X)
288        )
289
290        if self.cluster_encode == True:
291            return mo.one_hot_encode(X_clustered, self.n_clusters).astype(
292                np.float16
293            )
294
295        return X_clustered.astype(np.float16)
296
297    def create_layer(self, scaled_X, W=None):
298        """Create hidden layer.
299
300        Parameters:
301
302            scaled_X: {array-like}, shape = [n_samples, n_features]
303                Training vectors, where n_samples is the number
304                of samples and n_features is the number of features
305
306            W: {array-like}, shape = [n_features, hidden_features]
307                if provided, constructs the hidden layer with W; otherwise computed internally
308
309        Returns:
310
311            Hidden layer matrix: {array-like}
312
313        """
314
315        n_features = scaled_X.shape[1]
316
317        # hash_sim = {
318        #         "sobol": generate_sobol,
319        #         "hammersley": generate_hammersley,
320        #         "uniform": generate_uniform,
321        #         "halton": generate_halton
322        #     }
323
324        if self.bias is False:  # no bias term in the hidden layer
325            if W is None:
326                if self.nodes_sim == "sobol":
327                    self.W_ = generate_sobol(
328                        n_dims=n_features,
329                        n_points=self.n_hidden_features,
330                        seed=self.seed,
331                    )
332                elif self.nodes_sim == "hammersley":
333                    self.W_ = generate_hammersley(
334                        n_dims=n_features,
335                        n_points=self.n_hidden_features,
336                        seed=self.seed,
337                    )
338                elif self.nodes_sim == "uniform":
339                    self.W_ = generate_uniform(
340                        n_dims=n_features,
341                        n_points=self.n_hidden_features,
342                        seed=self.seed,
343                    )
344                else:
345                    self.W_ = generate_halton(
346                        n_dims=n_features,
347                        n_points=self.n_hidden_features,
348                        seed=self.seed,
349                    )
350
351                # self.W_ = hash_sim[self.nodes_sim](
352                #             n_dims=n_features,
353                #             n_points=self.n_hidden_features,
354                #             seed=self.seed,
355                #         )
356
357                assert (
358                    scaled_X.shape[1] == self.W_.shape[0]
359                ), "check dimensions of covariates X and matrix W"
360
361                return mo.dropout(
362                    x=self.activation_func(
363                        mo.safe_sparse_dot(
364                            a=scaled_X, b=self.W_, backend=self.backend
365                        )
366                    ),
367                    drop_prob=self.dropout,
368                    seed=self.seed,
369                )
370
371            # W is not none
372            assert (
373                scaled_X.shape[1] == W.shape[0]
374            ), "check dimensions of covariates X and matrix W"
375
376            # self.W_ = W
377            return mo.dropout(
378                x=self.activation_func(
379                    mo.safe_sparse_dot(a=scaled_X, b=W, backend=self.backend)
380                ),
381                drop_prob=self.dropout,
382                seed=self.seed,
383            )
384
385        # with bias term in the hidden layer
386        if W is None:
387            n_features_1 = n_features + 1
388
389            if self.nodes_sim == "sobol":
390                self.W_ = generate_sobol(
391                    n_dims=n_features_1,
392                    n_points=self.n_hidden_features,
393                    seed=self.seed,
394                )
395            elif self.nodes_sim == "hammersley":
396                self.W_ = generate_hammersley(
397                    n_dims=n_features_1,
398                    n_points=self.n_hidden_features,
399                    seed=self.seed,
400                )
401            elif self.nodes_sim == "uniform":
402                self.W_ = generate_uniform(
403                    n_dims=n_features_1,
404                    n_points=self.n_hidden_features,
405                    seed=self.seed,
406                )
407            else:
408                self.W_ = generate_halton(
409                    n_dims=n_features_1,
410                    n_points=self.n_hidden_features,
411                    seed=self.seed,
412                )
413
414            # self.W_ = hash_sim[self.nodes_sim](
415            #         n_dims=n_features_1,
416            #         n_points=self.n_hidden_features,
417            #         seed=self.seed,
418            #     )
419
420            return mo.dropout(
421                x=self.activation_func(
422                    mo.safe_sparse_dot(
423                        a=mo.cbind(
424                            np.ones(scaled_X.shape[0]),
425                            scaled_X,
426                            backend=self.backend,
427                        ),
428                        b=self.W_,
429                        backend=self.backend,
430                    )
431                ),
432                drop_prob=self.dropout,
433                seed=self.seed,
434            )
435
436        # W is not None
437        # self.W_ = W
438        return mo.dropout(
439            x=self.activation_func(
440                mo.safe_sparse_dot(
441                    a=mo.cbind(
442                        np.ones(scaled_X.shape[0]),
443                        scaled_X,
444                        backend=self.backend,
445                    ),
446                    b=W,
447                    backend=self.backend,
448                )
449            ),
450            drop_prob=self.dropout,
451            seed=self.seed,
452        )
453
454    def cook_training_set(self, y=None, X=None, W=None, **kwargs):
455        """Create new hidden features for training set, with hidden layer, center the response.
456
457        Parameters:
458
459            y: array-like, shape = [n_samples]
460                Target values
461
462            X: {array-like}, shape = [n_samples, n_features]
463                Training vectors, where n_samples is the number
464                of samples and n_features is the number of features
465
466            W: {array-like}, shape = [n_features, hidden_features]
467                if provided, constructs the hidden layer via W
468
469        Returns:
470
471            (centered response, direct link + hidden layer matrix): {tuple}
472
473        """
474
475        # either X and y are stored or not
476        # assert ((y is None) & (X is None)) | ((y is not None) & (X is not None))
477        if self.n_hidden_features > 0:  # has a hidden layer
478            assert (
479                len(self.type_scaling) >= 2
480            ), "must have len(self.type_scaling) >= 2 when self.n_hidden_features > 0"
481
482        if X is None:
483            if self.col_sample == 1:
484                input_X = self.X_
485            else:
486                n_features = self.X_.shape[1]
487                new_n_features = int(np.ceil(n_features * self.col_sample))
488                assert (
489                    new_n_features >= 1
490                ), "check class attribute 'col_sample' and the number of covariates provided for X"
491                np.random.seed(self.seed)
492                index_col = np.random.choice(
493                    range(n_features), size=new_n_features, replace=False
494                )
495                self.index_col_ = index_col
496                input_X = self.X_[:, self.index_col_]
497
498        else:  # X is not None # keep X vs self.X_
499            if isinstance(X, pd.DataFrame):
500                X = copy.deepcopy(X.values.astype(float))
501
502            if self.col_sample == 1:
503                input_X = X
504            else:
505                n_features = X.shape[1]
506                new_n_features = int(np.ceil(n_features * self.col_sample))
507                assert (
508                    new_n_features >= 1
509                ), "check class attribute 'col_sample' and the number of covariates provided for X"
510                np.random.seed(self.seed)
511                index_col = np.random.choice(
512                    range(n_features), size=new_n_features, replace=False
513                )
514                self.index_col_ = index_col
515                input_X = X[:, self.index_col_]
516
517        if (
518            self.n_clusters <= 0
519        ):  # data without any clustering: self.n_clusters is None -----
520            if self.n_hidden_features > 0:  # with hidden layer
521                self.nn_scaler_, scaled_X = mo.scale_covariates(
522                    input_X, choice=self.type_scaling[1]
523                )
524                Phi_X = (
525                    self.create_layer(scaled_X)
526                    if W is None
527                    else self.create_layer(scaled_X, W=W)
528                )
529                Z = (
530                    mo.cbind(input_X, Phi_X, backend=self.backend)
531                    if self.direct_link is True
532                    else Phi_X
533                )
534                self.scaler_, scaled_Z = mo.scale_covariates(
535                    Z, choice=self.type_scaling[0]
536                )
537            else:  # no hidden layer
538                Z = input_X
539                self.scaler_, scaled_Z = mo.scale_covariates(
540                    Z, choice=self.type_scaling[0]
541                )
542        else:  # data with clustering: self.n_clusters is not None ----- # keep
543            augmented_X = mo.cbind(
544                input_X,
545                self.encode_clusters(input_X, **kwargs),
546                backend=self.backend,
547            )
548
549            if self.n_hidden_features > 0:  # with hidden layer
550                self.nn_scaler_, scaled_X = mo.scale_covariates(
551                    augmented_X, choice=self.type_scaling[1]
552                )
553                Phi_X = (
554                    self.create_layer(scaled_X)
555                    if W is None
556                    else self.create_layer(scaled_X, W=W)
557                )
558                Z = (
559                    mo.cbind(augmented_X, Phi_X, backend=self.backend)
560                    if self.direct_link is True
561                    else Phi_X
562                )
563                self.scaler_, scaled_Z = mo.scale_covariates(
564                    Z, choice=self.type_scaling[0]
565                )
566            else:  # no hidden layer
567                Z = augmented_X
568                self.scaler_, scaled_Z = mo.scale_covariates(
569                    Z, choice=self.type_scaling[0]
570                )
571
572        # Returning model inputs -----
573        if mx.is_factor(y) is False:  # regression
574            # center y
575            if y is None:
576                self.y_mean_, centered_y = mo.center_response(self.y_)
577            else:
578                self.y_mean_, centered_y = mo.center_response(y)
579
580            # y is subsampled
581            if self.row_sample < 1:
582                n, p = Z.shape
583
584                self.subsampler_ = (
585                    SubSampler(
586                        y=self.y_, row_sample=self.row_sample, seed=self.seed
587                    )
588                    if y is None
589                    else SubSampler(
590                        y=y, row_sample=self.row_sample, seed=self.seed
591                    )
592                )
593
594                self.index_row_ = self.subsampler_.subsample()
595
596                n_row_sample = len(self.index_row_)
597                # regression
598                return (
599                    centered_y[self.index_row_].reshape(n_row_sample),
600                    self.scaler_.transform(
601                        Z[self.index_row_, :].reshape(n_row_sample, p)
602                    ),
603                )
604            # y is not subsampled
605            # regression
606            return (centered_y, self.scaler_.transform(Z))
607
608        # classification
609        # y is subsampled
610        if self.row_sample < 1:
611            n, p = Z.shape
612
613            self.subsampler_ = (
614                SubSampler(
615                    y=self.y_, row_sample=self.row_sample, seed=self.seed
616                )
617                if y is None
618                else SubSampler(y=y, row_sample=self.row_sample, seed=self.seed)
619            )
620
621            self.index_row_ = self.subsampler_.subsample()
622
623            n_row_sample = len(self.index_row_)
624            # classification
625            return (
626                y[self.index_row_].reshape(n_row_sample),
627                self.scaler_.transform(
628                    Z[self.index_row_, :].reshape(n_row_sample, p)
629                ),
630            )
631        # y is not subsampled
632        # classification
633        return (y, self.scaler_.transform(Z))
634
635    def cook_test_set(self, X, **kwargs):
636        """Transform data from test set, with hidden layer.
637
638        Parameters:
639
640            X: {array-like}, shape = [n_samples, n_features]
641                Training vectors, where n_samples is the number
642                of samples and n_features is the number of features
643
644            **kwargs: additional parameters to be passed to self.encode_cluster
645
646        Returns:
647
648            Transformed test set : {array-like}
649        """
650
651        if isinstance(X, pd.DataFrame):
652            X = copy.deepcopy(X.values.astype(float))
653
654        if (
655            self.n_clusters == 0
656        ):  # data without clustering: self.n_clusters is None -----
657            if self.n_hidden_features > 0:
658                # if hidden layer
659                scaled_X = (
660                    self.nn_scaler_.transform(X)
661                    if (self.col_sample == 1)
662                    else self.nn_scaler_.transform(X[:, self.index_col_])
663                )
664                Phi_X = self.create_layer(scaled_X, self.W_)
665                if self.direct_link == True:
666                    return self.scaler_.transform(
667                        mo.cbind(scaled_X, Phi_X, backend=self.backend)
668                    )
669                # when self.direct_link == False
670                return self.scaler_.transform(Phi_X)
671            # if no hidden layer # self.n_hidden_features == 0
672            return self.scaler_.transform(X)
673
674        # data with clustering: self.n_clusters > 0 -----
675        if self.col_sample == 1:
676            predicted_clusters = self.encode_clusters(
677                X=X, predict=True, **kwargs
678            )
679            augmented_X = mo.cbind(X, predicted_clusters, backend=self.backend)
680        else:
681            predicted_clusters = self.encode_clusters(
682                X=X[:, self.index_col_], predict=True, **kwargs
683            )
684            augmented_X = mo.cbind(
685                X[:, self.index_col_], predicted_clusters, backend=self.backend
686            )
687
688        if self.n_hidden_features > 0:  # if hidden layer
689            scaled_X = self.nn_scaler_.transform(augmented_X)
690            Phi_X = self.create_layer(scaled_X, self.W_)
691            if self.direct_link == True:
692                return self.scaler_.transform(
693                    mo.cbind(augmented_X, Phi_X, backend=self.backend)
694                )
695            return self.scaler_.transform(Phi_X)
696
697        # if no hidden layer
698        return self.scaler_.transform(augmented_X)
699
700    def score(self, X, y, scoring=None, **kwargs):
701        """Score the model on test set features X and response y.
702
703        Parameters:
704
705            X: {array-like}, shape = [n_samples, n_features]
706                Training vectors, where n_samples is the number
707                of samples and n_features is the number of features
708
709            y: array-like, shape = [n_samples]
710                Target values
711
712            scoring: str
713                must be in ('explained_variance', 'neg_mean_absolute_error',
714                            'neg_mean_squared_error', 'neg_mean_squared_log_error',
715                            'neg_median_absolute_error', 'r2')
716
717            **kwargs: additional parameters to be passed to scoring functions
718
719        Returns:
720
721        model scores: {array-like}
722
723        """
724
725        preds = self.predict(X)
726
727        if self.type_fit == "classification":
728
729            if scoring is None:
730                scoring = "accuracy"
731
732            # check inputs
733            assert scoring in (
734                "accuracy",
735                "average_precision",
736                "brier_score_loss",
737                "f1",
738                "f1_micro",
739                "f1_macro",
740                "f1_weighted",
741                "f1_samples",
742                "neg_log_loss",
743                "precision",
744                "recall",
745                "roc_auc",
746            ), "'scoring' should be in ('accuracy', 'average_precision', \
747                            'brier_score_loss', 'f1', 'f1_micro', \
748                            'f1_macro', 'f1_weighted',  'f1_samples', \
749                            'neg_log_loss', 'precision', 'recall', \
750                            'roc_auc')"
751
752            scoring_options = {
753                "accuracy": skm.accuracy_score,
754                "average_precision": skm.average_precision_score,
755                "brier_score_loss": skm.brier_score_loss,
756                "f1": skm.f1_score,
757                "f1_micro": skm.f1_score,
758                "f1_macro": skm.f1_score,
759                "f1_weighted": skm.f1_score,
760                "f1_samples": skm.f1_score,
761                "neg_log_loss": skm.log_loss,
762                "precision": skm.precision_score,
763                "recall": skm.recall_score,
764                "roc_auc": skm.roc_auc_score,
765            }
766
767            return scoring_options[scoring](y, preds, **kwargs)
768
769        if self.type_fit == "regression":
770
771            if (
772                type(preds) == tuple
773            ):  # if there are std. devs in the predictions
774                preds = preds[0]
775
776            if scoring is None:
777                scoring = "neg_root_mean_squared_error"
778
779            # check inputs
780            assert scoring in (
781                "explained_variance",
782                "neg_mean_absolute_error",
783                "neg_mean_squared_error",
784                "neg_mean_squared_log_error",
785                "neg_median_absolute_error",
786                "neg_root_mean_squared_error",
787                "r2",
788            ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
789                            'neg_mean_squared_error', 'neg_mean_squared_log_error', \
790                            'neg_median_absolute_error', 'r2', 'neg_root_mean_squared_error')"
791
792            scoring_options = {
793                "neg_root_mean_squared_error": skm.root_mean_squared_error,
794                "explained_variance": skm.explained_variance_score,
795                "neg_mean_absolute_error": skm.median_absolute_error,
796                "neg_mean_squared_error": skm.mean_squared_error,
797                "neg_mean_squared_log_error": skm.mean_squared_log_error,
798                "neg_median_absolute_error": skm.median_absolute_error,
799                "r2": skm.r2_score,
800            }
801
802            return scoring_options[scoring](y, preds, **kwargs)

Base model from which all the other classes inherit.

This class contains the most important data preprocessing/feature engineering methods.

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for hidden layer nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or
    not (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original features are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for type_clust='kmeans' or type_clust='gmm'
    clustering (could be 0: no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot);
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax') or robust scaling ('robust') or  max absolute scaling ('maxabs')

col_sample: float
    percentage of features randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

seed: int
    reproducibility seed for nodes_sim=='uniform', clustering and dropout

backend: str
    "cpu" or "gpu" or "tpu"
def encode_clusters(self, X=None, predict=False, **kwargs):
234    def encode_clusters(self, X=None, predict=False, **kwargs):  #
235        """Create new covariates with kmeans or GMM clustering
236
237        Parameters:
238
239            X: {array-like}, shape = [n_samples, n_features]
240                Training vectors, where n_samples is the number
241                of samples and n_features is the number of features.
242
243            predict: boolean
244                is False on training set and True on test set
245
246            **kwargs:
247                additional parameters to be passed to the
248                clustering method
249
250        Returns:
251
252            Clusters' matrix, one-hot encoded: {array-like}
253
254        """
255
256        np.random.seed(self.seed)
257
258        if X is None:
259            X = self.X_
260
261        if isinstance(X, pd.DataFrame):
262            X = copy.deepcopy(X.values.astype(float))
263
264        if predict is False:  # encode training set
265            # scale input data before clustering
266            self.clustering_scaler_, scaled_X = mo.scale_covariates(
267                X, choice=self.type_scaling[2]
268            )
269
270            self.clustering_obj_, X_clustered = mo.cluster_covariates(
271                scaled_X,
272                self.n_clusters,
273                self.seed,
274                type_clust=self.type_clust,
275                **kwargs
276            )
277
278            if self.cluster_encode == True:
279                return mo.one_hot_encode(X_clustered, self.n_clusters).astype(
280                    np.float16
281                )
282
283            return X_clustered.astype(np.float16)
284
285        # if predict == True, encode test set
286        X_clustered = self.clustering_obj_.predict(
287            self.clustering_scaler_.transform(X)
288        )
289
290        if self.cluster_encode == True:
291            return mo.one_hot_encode(X_clustered, self.n_clusters).astype(
292                np.float16
293            )
294
295        return X_clustered.astype(np.float16)

Create new covariates with kmeans or GMM clustering

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

predict: boolean
    is False on training set and True on test set

**kwargs:
    additional parameters to be passed to the
    clustering method

Returns:

Clusters' matrix, one-hot encoded: {array-like}
def create_layer(self, scaled_X, W=None):
297    def create_layer(self, scaled_X, W=None):
298        """Create hidden layer.
299
300        Parameters:
301
302            scaled_X: {array-like}, shape = [n_samples, n_features]
303                Training vectors, where n_samples is the number
304                of samples and n_features is the number of features
305
306            W: {array-like}, shape = [n_features, hidden_features]
307                if provided, constructs the hidden layer with W; otherwise computed internally
308
309        Returns:
310
311            Hidden layer matrix: {array-like}
312
313        """
314
315        n_features = scaled_X.shape[1]
316
317        # hash_sim = {
318        #         "sobol": generate_sobol,
319        #         "hammersley": generate_hammersley,
320        #         "uniform": generate_uniform,
321        #         "halton": generate_halton
322        #     }
323
324        if self.bias is False:  # no bias term in the hidden layer
325            if W is None:
326                if self.nodes_sim == "sobol":
327                    self.W_ = generate_sobol(
328                        n_dims=n_features,
329                        n_points=self.n_hidden_features,
330                        seed=self.seed,
331                    )
332                elif self.nodes_sim == "hammersley":
333                    self.W_ = generate_hammersley(
334                        n_dims=n_features,
335                        n_points=self.n_hidden_features,
336                        seed=self.seed,
337                    )
338                elif self.nodes_sim == "uniform":
339                    self.W_ = generate_uniform(
340                        n_dims=n_features,
341                        n_points=self.n_hidden_features,
342                        seed=self.seed,
343                    )
344                else:
345                    self.W_ = generate_halton(
346                        n_dims=n_features,
347                        n_points=self.n_hidden_features,
348                        seed=self.seed,
349                    )
350
351                # self.W_ = hash_sim[self.nodes_sim](
352                #             n_dims=n_features,
353                #             n_points=self.n_hidden_features,
354                #             seed=self.seed,
355                #         )
356
357                assert (
358                    scaled_X.shape[1] == self.W_.shape[0]
359                ), "check dimensions of covariates X and matrix W"
360
361                return mo.dropout(
362                    x=self.activation_func(
363                        mo.safe_sparse_dot(
364                            a=scaled_X, b=self.W_, backend=self.backend
365                        )
366                    ),
367                    drop_prob=self.dropout,
368                    seed=self.seed,
369                )
370
371            # W is not none
372            assert (
373                scaled_X.shape[1] == W.shape[0]
374            ), "check dimensions of covariates X and matrix W"
375
376            # self.W_ = W
377            return mo.dropout(
378                x=self.activation_func(
379                    mo.safe_sparse_dot(a=scaled_X, b=W, backend=self.backend)
380                ),
381                drop_prob=self.dropout,
382                seed=self.seed,
383            )
384
385        # with bias term in the hidden layer
386        if W is None:
387            n_features_1 = n_features + 1
388
389            if self.nodes_sim == "sobol":
390                self.W_ = generate_sobol(
391                    n_dims=n_features_1,
392                    n_points=self.n_hidden_features,
393                    seed=self.seed,
394                )
395            elif self.nodes_sim == "hammersley":
396                self.W_ = generate_hammersley(
397                    n_dims=n_features_1,
398                    n_points=self.n_hidden_features,
399                    seed=self.seed,
400                )
401            elif self.nodes_sim == "uniform":
402                self.W_ = generate_uniform(
403                    n_dims=n_features_1,
404                    n_points=self.n_hidden_features,
405                    seed=self.seed,
406                )
407            else:
408                self.W_ = generate_halton(
409                    n_dims=n_features_1,
410                    n_points=self.n_hidden_features,
411                    seed=self.seed,
412                )
413
414            # self.W_ = hash_sim[self.nodes_sim](
415            #         n_dims=n_features_1,
416            #         n_points=self.n_hidden_features,
417            #         seed=self.seed,
418            #     )
419
420            return mo.dropout(
421                x=self.activation_func(
422                    mo.safe_sparse_dot(
423                        a=mo.cbind(
424                            np.ones(scaled_X.shape[0]),
425                            scaled_X,
426                            backend=self.backend,
427                        ),
428                        b=self.W_,
429                        backend=self.backend,
430                    )
431                ),
432                drop_prob=self.dropout,
433                seed=self.seed,
434            )
435
436        # W is not None
437        # self.W_ = W
438        return mo.dropout(
439            x=self.activation_func(
440                mo.safe_sparse_dot(
441                    a=mo.cbind(
442                        np.ones(scaled_X.shape[0]),
443                        scaled_X,
444                        backend=self.backend,
445                    ),
446                    b=W,
447                    backend=self.backend,
448                )
449            ),
450            drop_prob=self.dropout,
451            seed=self.seed,
452        )

Create hidden layer.

Parameters:

scaled_X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

W: {array-like}, shape = [n_features, hidden_features]
    if provided, constructs the hidden layer with W; otherwise computed internally

Returns:

Hidden layer matrix: {array-like}
def cook_training_set(self, y=None, X=None, W=None, **kwargs):
454    def cook_training_set(self, y=None, X=None, W=None, **kwargs):
455        """Create new hidden features for training set, with hidden layer, center the response.
456
457        Parameters:
458
459            y: array-like, shape = [n_samples]
460                Target values
461
462            X: {array-like}, shape = [n_samples, n_features]
463                Training vectors, where n_samples is the number
464                of samples and n_features is the number of features
465
466            W: {array-like}, shape = [n_features, hidden_features]
467                if provided, constructs the hidden layer via W
468
469        Returns:
470
471            (centered response, direct link + hidden layer matrix): {tuple}
472
473        """
474
475        # either X and y are stored or not
476        # assert ((y is None) & (X is None)) | ((y is not None) & (X is not None))
477        if self.n_hidden_features > 0:  # has a hidden layer
478            assert (
479                len(self.type_scaling) >= 2
480            ), "must have len(self.type_scaling) >= 2 when self.n_hidden_features > 0"
481
482        if X is None:
483            if self.col_sample == 1:
484                input_X = self.X_
485            else:
486                n_features = self.X_.shape[1]
487                new_n_features = int(np.ceil(n_features * self.col_sample))
488                assert (
489                    new_n_features >= 1
490                ), "check class attribute 'col_sample' and the number of covariates provided for X"
491                np.random.seed(self.seed)
492                index_col = np.random.choice(
493                    range(n_features), size=new_n_features, replace=False
494                )
495                self.index_col_ = index_col
496                input_X = self.X_[:, self.index_col_]
497
498        else:  # X is not None # keep X vs self.X_
499            if isinstance(X, pd.DataFrame):
500                X = copy.deepcopy(X.values.astype(float))
501
502            if self.col_sample == 1:
503                input_X = X
504            else:
505                n_features = X.shape[1]
506                new_n_features = int(np.ceil(n_features * self.col_sample))
507                assert (
508                    new_n_features >= 1
509                ), "check class attribute 'col_sample' and the number of covariates provided for X"
510                np.random.seed(self.seed)
511                index_col = np.random.choice(
512                    range(n_features), size=new_n_features, replace=False
513                )
514                self.index_col_ = index_col
515                input_X = X[:, self.index_col_]
516
517        if (
518            self.n_clusters <= 0
519        ):  # data without any clustering: self.n_clusters is None -----
520            if self.n_hidden_features > 0:  # with hidden layer
521                self.nn_scaler_, scaled_X = mo.scale_covariates(
522                    input_X, choice=self.type_scaling[1]
523                )
524                Phi_X = (
525                    self.create_layer(scaled_X)
526                    if W is None
527                    else self.create_layer(scaled_X, W=W)
528                )
529                Z = (
530                    mo.cbind(input_X, Phi_X, backend=self.backend)
531                    if self.direct_link is True
532                    else Phi_X
533                )
534                self.scaler_, scaled_Z = mo.scale_covariates(
535                    Z, choice=self.type_scaling[0]
536                )
537            else:  # no hidden layer
538                Z = input_X
539                self.scaler_, scaled_Z = mo.scale_covariates(
540                    Z, choice=self.type_scaling[0]
541                )
542        else:  # data with clustering: self.n_clusters is not None ----- # keep
543            augmented_X = mo.cbind(
544                input_X,
545                self.encode_clusters(input_X, **kwargs),
546                backend=self.backend,
547            )
548
549            if self.n_hidden_features > 0:  # with hidden layer
550                self.nn_scaler_, scaled_X = mo.scale_covariates(
551                    augmented_X, choice=self.type_scaling[1]
552                )
553                Phi_X = (
554                    self.create_layer(scaled_X)
555                    if W is None
556                    else self.create_layer(scaled_X, W=W)
557                )
558                Z = (
559                    mo.cbind(augmented_X, Phi_X, backend=self.backend)
560                    if self.direct_link is True
561                    else Phi_X
562                )
563                self.scaler_, scaled_Z = mo.scale_covariates(
564                    Z, choice=self.type_scaling[0]
565                )
566            else:  # no hidden layer
567                Z = augmented_X
568                self.scaler_, scaled_Z = mo.scale_covariates(
569                    Z, choice=self.type_scaling[0]
570                )
571
572        # Returning model inputs -----
573        if mx.is_factor(y) is False:  # regression
574            # center y
575            if y is None:
576                self.y_mean_, centered_y = mo.center_response(self.y_)
577            else:
578                self.y_mean_, centered_y = mo.center_response(y)
579
580            # y is subsampled
581            if self.row_sample < 1:
582                n, p = Z.shape
583
584                self.subsampler_ = (
585                    SubSampler(
586                        y=self.y_, row_sample=self.row_sample, seed=self.seed
587                    )
588                    if y is None
589                    else SubSampler(
590                        y=y, row_sample=self.row_sample, seed=self.seed
591                    )
592                )
593
594                self.index_row_ = self.subsampler_.subsample()
595
596                n_row_sample = len(self.index_row_)
597                # regression
598                return (
599                    centered_y[self.index_row_].reshape(n_row_sample),
600                    self.scaler_.transform(
601                        Z[self.index_row_, :].reshape(n_row_sample, p)
602                    ),
603                )
604            # y is not subsampled
605            # regression
606            return (centered_y, self.scaler_.transform(Z))
607
608        # classification
609        # y is subsampled
610        if self.row_sample < 1:
611            n, p = Z.shape
612
613            self.subsampler_ = (
614                SubSampler(
615                    y=self.y_, row_sample=self.row_sample, seed=self.seed
616                )
617                if y is None
618                else SubSampler(y=y, row_sample=self.row_sample, seed=self.seed)
619            )
620
621            self.index_row_ = self.subsampler_.subsample()
622
623            n_row_sample = len(self.index_row_)
624            # classification
625            return (
626                y[self.index_row_].reshape(n_row_sample),
627                self.scaler_.transform(
628                    Z[self.index_row_, :].reshape(n_row_sample, p)
629                ),
630            )
631        # y is not subsampled
632        # classification
633        return (y, self.scaler_.transform(Z))

Create new hidden features for training set, with hidden layer, center the response.

Parameters:

y: array-like, shape = [n_samples]
    Target values

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

W: {array-like}, shape = [n_features, hidden_features]
    if provided, constructs the hidden layer via W

Returns:

(centered response, direct link + hidden layer matrix): {tuple}
def cook_test_set(self, X, **kwargs):
635    def cook_test_set(self, X, **kwargs):
636        """Transform data from test set, with hidden layer.
637
638        Parameters:
639
640            X: {array-like}, shape = [n_samples, n_features]
641                Training vectors, where n_samples is the number
642                of samples and n_features is the number of features
643
644            **kwargs: additional parameters to be passed to self.encode_cluster
645
646        Returns:
647
648            Transformed test set : {array-like}
649        """
650
651        if isinstance(X, pd.DataFrame):
652            X = copy.deepcopy(X.values.astype(float))
653
654        if (
655            self.n_clusters == 0
656        ):  # data without clustering: self.n_clusters is None -----
657            if self.n_hidden_features > 0:
658                # if hidden layer
659                scaled_X = (
660                    self.nn_scaler_.transform(X)
661                    if (self.col_sample == 1)
662                    else self.nn_scaler_.transform(X[:, self.index_col_])
663                )
664                Phi_X = self.create_layer(scaled_X, self.W_)
665                if self.direct_link == True:
666                    return self.scaler_.transform(
667                        mo.cbind(scaled_X, Phi_X, backend=self.backend)
668                    )
669                # when self.direct_link == False
670                return self.scaler_.transform(Phi_X)
671            # if no hidden layer # self.n_hidden_features == 0
672            return self.scaler_.transform(X)
673
674        # data with clustering: self.n_clusters > 0 -----
675        if self.col_sample == 1:
676            predicted_clusters = self.encode_clusters(
677                X=X, predict=True, **kwargs
678            )
679            augmented_X = mo.cbind(X, predicted_clusters, backend=self.backend)
680        else:
681            predicted_clusters = self.encode_clusters(
682                X=X[:, self.index_col_], predict=True, **kwargs
683            )
684            augmented_X = mo.cbind(
685                X[:, self.index_col_], predicted_clusters, backend=self.backend
686            )
687
688        if self.n_hidden_features > 0:  # if hidden layer
689            scaled_X = self.nn_scaler_.transform(augmented_X)
690            Phi_X = self.create_layer(scaled_X, self.W_)
691            if self.direct_link == True:
692                return self.scaler_.transform(
693                    mo.cbind(augmented_X, Phi_X, backend=self.backend)
694                )
695            return self.scaler_.transform(Phi_X)
696
697        # if no hidden layer
698        return self.scaler_.transform(augmented_X)

Transform data from test set, with hidden layer.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

**kwargs: additional parameters to be passed to self.encode_cluster

Returns:

Transformed test set : {array-like}
def score(self, X, y, scoring=None, **kwargs):
700    def score(self, X, y, scoring=None, **kwargs):
701        """Score the model on test set features X and response y.
702
703        Parameters:
704
705            X: {array-like}, shape = [n_samples, n_features]
706                Training vectors, where n_samples is the number
707                of samples and n_features is the number of features
708
709            y: array-like, shape = [n_samples]
710                Target values
711
712            scoring: str
713                must be in ('explained_variance', 'neg_mean_absolute_error',
714                            'neg_mean_squared_error', 'neg_mean_squared_log_error',
715                            'neg_median_absolute_error', 'r2')
716
717            **kwargs: additional parameters to be passed to scoring functions
718
719        Returns:
720
721        model scores: {array-like}
722
723        """
724
725        preds = self.predict(X)
726
727        if self.type_fit == "classification":
728
729            if scoring is None:
730                scoring = "accuracy"
731
732            # check inputs
733            assert scoring in (
734                "accuracy",
735                "average_precision",
736                "brier_score_loss",
737                "f1",
738                "f1_micro",
739                "f1_macro",
740                "f1_weighted",
741                "f1_samples",
742                "neg_log_loss",
743                "precision",
744                "recall",
745                "roc_auc",
746            ), "'scoring' should be in ('accuracy', 'average_precision', \
747                            'brier_score_loss', 'f1', 'f1_micro', \
748                            'f1_macro', 'f1_weighted',  'f1_samples', \
749                            'neg_log_loss', 'precision', 'recall', \
750                            'roc_auc')"
751
752            scoring_options = {
753                "accuracy": skm.accuracy_score,
754                "average_precision": skm.average_precision_score,
755                "brier_score_loss": skm.brier_score_loss,
756                "f1": skm.f1_score,
757                "f1_micro": skm.f1_score,
758                "f1_macro": skm.f1_score,
759                "f1_weighted": skm.f1_score,
760                "f1_samples": skm.f1_score,
761                "neg_log_loss": skm.log_loss,
762                "precision": skm.precision_score,
763                "recall": skm.recall_score,
764                "roc_auc": skm.roc_auc_score,
765            }
766
767            return scoring_options[scoring](y, preds, **kwargs)
768
769        if self.type_fit == "regression":
770
771            if (
772                type(preds) == tuple
773            ):  # if there are std. devs in the predictions
774                preds = preds[0]
775
776            if scoring is None:
777                scoring = "neg_root_mean_squared_error"
778
779            # check inputs
780            assert scoring in (
781                "explained_variance",
782                "neg_mean_absolute_error",
783                "neg_mean_squared_error",
784                "neg_mean_squared_log_error",
785                "neg_median_absolute_error",
786                "neg_root_mean_squared_error",
787                "r2",
788            ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
789                            'neg_mean_squared_error', 'neg_mean_squared_log_error', \
790                            'neg_median_absolute_error', 'r2', 'neg_root_mean_squared_error')"
791
792            scoring_options = {
793                "neg_root_mean_squared_error": skm.root_mean_squared_error,
794                "explained_variance": skm.explained_variance_score,
795                "neg_mean_absolute_error": skm.median_absolute_error,
796                "neg_mean_squared_error": skm.mean_squared_error,
797                "neg_mean_squared_log_error": skm.mean_squared_log_error,
798                "neg_median_absolute_error": skm.median_absolute_error,
799                "r2": skm.r2_score,
800            }
801
802            return scoring_options[scoring](y, preds, **kwargs)

Score the model on test set features X and response y.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

y: array-like, shape = [n_samples]
    Target values

scoring: str
    must be in ('explained_variance', 'neg_mean_absolute_error',
                'neg_mean_squared_error', 'neg_mean_squared_log_error',
                'neg_median_absolute_error', 'r2')

**kwargs: additional parameters to be passed to scoring functions

Returns:

model scores: {array-like}

class BaseRegressor(nnetsauce.Base, sklearn.base.RegressorMixin):
 15class BaseRegressor(Base, RegressorMixin):
 16    """Random Vector Functional Link Network regression without shrinkage
 17
 18    Parameters:
 19
 20        n_hidden_features: int
 21            number of nodes in the hidden layer
 22
 23        activation_name: str
 24            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 25
 26        a: float
 27            hyperparameter for 'prelu' or 'elu' activation function
 28
 29        nodes_sim: str
 30            type of simulation for hidden layer nodes: 'sobol', 'hammersley', 'halton',
 31            'uniform'
 32
 33        bias: boolean
 34            indicates if the hidden layer contains a bias term (True) or
 35            not (False)
 36
 37        dropout: float
 38            regularization parameter; (random) percentage of nodes dropped out
 39            of the training
 40
 41        direct_link: boolean
 42            indicates if the original features are included (True) in model's
 43            fitting or not (False)
 44
 45        n_clusters: int
 46            number of clusters for type_clust='kmeans' or type_clust='gmm'
 47            clustering (could be 0: no clustering)
 48
 49        cluster_encode: bool
 50            defines how the variable containing clusters is treated (default is one-hot);
 51            if `False`, then labels are used, without one-hot encoding
 52
 53        type_clust: str
 54            type of clustering method: currently k-means ('kmeans') or Gaussian
 55            Mixture Model ('gmm')
 56
 57        type_scaling: a tuple of 3 strings
 58            scaling methods for inputs, hidden layer, and clustering respectively
 59            (and when relevant).
 60            Currently available: standardization ('std') or MinMax scaling ('minmax')
 61
 62        col_sample: float
 63            percentage of features randomly chosen for training
 64
 65        row_sample: float
 66            percentage of rows chosen for training, by stratified bootstrapping
 67
 68        seed: int
 69            reproducibility seed for nodes_sim=='uniform', clustering and dropout
 70
 71        backend: str
 72            "cpu" or "gpu" or "tpu"
 73
 74    Attributes:
 75
 76        beta_: vector
 77            regression coefficients
 78
 79        GCV_: float
 80            Generalized Cross-Validation error
 81
 82    """
 83
 84    # construct the object -----
 85
 86    def __init__(
 87        self,
 88        n_hidden_features=5,
 89        activation_name="relu",
 90        a=0.01,
 91        nodes_sim="sobol",
 92        bias=True,
 93        dropout=0,
 94        direct_link=True,
 95        n_clusters=2,
 96        cluster_encode=True,
 97        type_clust="kmeans",
 98        type_scaling=("std", "std", "std"),
 99        col_sample=1,
100        row_sample=1,
101        seed=123,
102        backend="cpu",
103    ):
104        super().__init__(
105            n_hidden_features=n_hidden_features,
106            activation_name=activation_name,
107            a=a,
108            nodes_sim=nodes_sim,
109            bias=bias,
110            dropout=dropout,
111            direct_link=direct_link,
112            n_clusters=n_clusters,
113            cluster_encode=cluster_encode,
114            type_clust=type_clust,
115            type_scaling=type_scaling,
116            col_sample=col_sample,
117            row_sample=row_sample,
118            seed=seed,
119            backend=backend,
120        )
121
122    def fit(self, X, y, **kwargs):
123        """Fit BaseRegressor to training data (X, y)
124
125        Parameters:
126
127            X: {array-like}, shape = [n_samples, n_features]
128                Training vectors, where n_samples is the number
129                of samples and n_features is the number of features
130
131            y: array-like, shape = [n_samples]
132                Target values
133
134            **kwargs: additional parameters to be passed to self.cook_training_set
135
136        Returns:
137
138            self: object
139        """
140
141        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
142
143        fit_obj = lmf.beta_Sigma_hat(
144            X=scaled_Z, y=centered_y, backend=self.backend
145        )
146
147        self.beta_ = fit_obj["beta_hat"]
148
149        self.GCV_ = fit_obj["GCV"]
150
151        return self
152
153    def predict(self, X, **kwargs):
154        """Predict test data X.
155
156        Parameters:
157
158            X: {array-like}, shape = [n_samples, n_features]
159                Training vectors, where n_samples is the number
160                of samples and n_features is the number of features
161
162            **kwargs: additional parameters to be passed to self.cook_test_set
163
164        Returns:
165
166            model predictions: {array-like}
167        """
168
169        if len(X.shape) == 1:
170            n_features = X.shape[0]
171            new_X = mo.rbind(
172                X.reshape(1, n_features),
173                np.ones(n_features).reshape(1, n_features),
174            )
175
176            return (
177                self.y_mean_
178                + mo.safe_sparse_dot(
179                    a=self.cook_test_set(new_X, **kwargs),
180                    b=self.beta_,
181                    backend=self.backend,
182                )
183            )[0]
184
185        return self.y_mean_ + mo.safe_sparse_dot(
186            a=self.cook_test_set(X, **kwargs),
187            b=self.beta_,
188            backend=self.backend,
189        )

Random Vector Functional Link Network regression without shrinkage

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for hidden layer nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or
    not (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original features are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for type_clust='kmeans' or type_clust='gmm'
    clustering (could be 0: no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot);
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

col_sample: float
    percentage of features randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

seed: int
    reproducibility seed for nodes_sim=='uniform', clustering and dropout

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

beta_: vector
    regression coefficients

GCV_: float
    Generalized Cross-Validation error
def fit(self, X, y, **kwargs):
122    def fit(self, X, y, **kwargs):
123        """Fit BaseRegressor to training data (X, y)
124
125        Parameters:
126
127            X: {array-like}, shape = [n_samples, n_features]
128                Training vectors, where n_samples is the number
129                of samples and n_features is the number of features
130
131            y: array-like, shape = [n_samples]
132                Target values
133
134            **kwargs: additional parameters to be passed to self.cook_training_set
135
136        Returns:
137
138            self: object
139        """
140
141        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
142
143        fit_obj = lmf.beta_Sigma_hat(
144            X=scaled_Z, y=centered_y, backend=self.backend
145        )
146
147        self.beta_ = fit_obj["beta_hat"]
148
149        self.GCV_ = fit_obj["GCV"]
150
151        return self

Fit BaseRegressor to training data (X, y)

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

y: array-like, shape = [n_samples]
    Target values

**kwargs: additional parameters to be passed to self.cook_training_set

Returns:

self: object
def predict(self, X, **kwargs):
153    def predict(self, X, **kwargs):
154        """Predict test data X.
155
156        Parameters:
157
158            X: {array-like}, shape = [n_samples, n_features]
159                Training vectors, where n_samples is the number
160                of samples and n_features is the number of features
161
162            **kwargs: additional parameters to be passed to self.cook_test_set
163
164        Returns:
165
166            model predictions: {array-like}
167        """
168
169        if len(X.shape) == 1:
170            n_features = X.shape[0]
171            new_X = mo.rbind(
172                X.reshape(1, n_features),
173                np.ones(n_features).reshape(1, n_features),
174            )
175
176            return (
177                self.y_mean_
178                + mo.safe_sparse_dot(
179                    a=self.cook_test_set(new_X, **kwargs),
180                    b=self.beta_,
181                    backend=self.backend,
182                )
183            )[0]
184
185        return self.y_mean_ + mo.safe_sparse_dot(
186            a=self.cook_test_set(X, **kwargs),
187            b=self.beta_,
188            backend=self.backend,
189        )

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

**kwargs: additional parameters to be passed to self.cook_test_set

Returns:

model predictions: {array-like}
class BayesianRVFLRegressor(nnetsauce.Base, sklearn.base.RegressorMixin):
 15class BayesianRVFLRegressor(Base, RegressorMixin):
 16    """Bayesian Random Vector Functional Link Network regression with one prior
 17
 18    Parameters:
 19
 20        n_hidden_features: int
 21            number of nodes in the hidden layer
 22
 23        activation_name: str
 24            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 25
 26        a: float
 27            hyperparameter for 'prelu' or 'elu' activation function
 28
 29        nodes_sim: str
 30            type of simulation for the nodes: 'sobol', 'hammersley', 'halton', 'uniform'
 31
 32        bias: boolean
 33            indicates if the hidden layer contains a bias term (True) or not (False)
 34
 35        dropout: float
 36            regularization parameter; (random) percentage of nodes dropped out
 37            of the training
 38
 39        direct_link: boolean
 40            indicates if the original features are included (True) in model''s fitting or not (False)
 41
 42        n_clusters: int
 43            number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering)
 44
 45        cluster_encode: bool
 46            defines how the variable containing clusters is treated (default is one-hot)
 47            if `False`, then labels are used, without one-hot encoding
 48
 49        type_clust: str
 50            type of clustering method: currently k-means ('kmeans') or Gaussian Mixture Model ('gmm')
 51
 52        type_scaling: a tuple of 3 strings
 53            scaling methods for inputs, hidden layer, and clustering respectively
 54            (and when relevant).
 55            Currently available: standardization ('std') or MinMax scaling ('minmax')
 56
 57        seed: int
 58            reproducibility seed for nodes_sim=='uniform'
 59
 60        s: float
 61            std. dev. of regression parameters in Bayesian Ridge Regression
 62
 63        sigma: float
 64            std. dev. of residuals in Bayesian Ridge Regression
 65
 66        return_std: boolean
 67            if True, uncertainty around predictions is evaluated
 68
 69        backend: str
 70            "cpu" or "gpu" or "tpu"
 71
 72    Attributes:
 73
 74        beta_: array-like
 75            regression''s coefficients
 76
 77        Sigma_: array-like
 78            covariance of the distribution of fitted parameters
 79
 80        GCV_: float
 81            Generalized cross-validation error
 82
 83        y_mean_: float
 84            average response
 85
 86    Examples:
 87
 88    ```python
 89    TBD
 90    ```
 91
 92    """
 93
 94    # construct the object -----
 95
 96    def __init__(
 97        self,
 98        n_hidden_features=5,
 99        activation_name="relu",
100        a=0.01,
101        nodes_sim="sobol",
102        bias=True,
103        dropout=0,
104        direct_link=True,
105        n_clusters=2,
106        cluster_encode=True,
107        type_clust="kmeans",
108        type_scaling=("std", "std", "std"),
109        seed=123,
110        s=0.1,
111        sigma=0.05,
112        return_std=True,
113        backend="cpu",
114    ):
115        super().__init__(
116            n_hidden_features=n_hidden_features,
117            activation_name=activation_name,
118            a=a,
119            nodes_sim=nodes_sim,
120            bias=bias,
121            dropout=dropout,
122            direct_link=direct_link,
123            n_clusters=n_clusters,
124            cluster_encode=cluster_encode,
125            type_clust=type_clust,
126            type_scaling=type_scaling,
127            seed=seed,
128            backend=backend,
129        )
130        self.s = s
131        self.sigma = sigma
132        self.beta_ = None
133        self.Sigma_ = None
134        self.GCV_ = None
135        self.return_std = return_std
136
137    def fit(self, X, y, **kwargs):
138        """Fit BayesianRVFLRegressor to training data (X, y).
139
140        Parameters:
141
142            X: {array-like}, shape = [n_samples, n_features]
143                Training vectors, where n_samples is the number
144                of samples and n_features is the number of features.
145
146            y: array-like, shape = [n_samples]
147                Target values.
148
149            **kwargs: additional parameters to be passed to
150                    self.cook_training_set
151
152        Returns:
153
154            self: object
155
156        """
157
158        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
159
160        fit_obj = lmf.beta_Sigma_hat_rvfl(
161            X=scaled_Z,
162            y=centered_y,
163            s=self.s,
164            sigma=self.sigma,
165            fit_intercept=False,
166            return_cov=self.return_std,
167            backend=self.backend,
168        )
169
170        self.beta_ = fit_obj["beta_hat"]
171
172        if self.return_std == True:
173            self.Sigma_ = fit_obj["Sigma_hat"]
174
175        self.GCV_ = fit_obj["GCV"]
176
177        return self
178
179    def predict(self, X, return_std=False, **kwargs):
180        """Predict test data X.
181
182        Parameters:
183
184            X: {array-like}, shape = [n_samples, n_features]
185                Training vectors, where n_samples is the number
186                of samples and n_features is the number of features.
187
188            return_std: {boolean}, standard dev. is returned or not
189
190            **kwargs: additional parameters to be passed to
191                    self.cook_test_set
192
193        Returns:
194
195            model predictions: {array-like}
196
197        """
198
199        if len(X.shape) == 1:  # one observation in the test set only
200            n_features = X.shape[0]
201            new_X = mo.rbind(
202                x=X.reshape(1, n_features),
203                y=np.ones(n_features).reshape(1, n_features),
204                backend=self.backend,
205            )
206
207        self.return_std = return_std
208
209        if self.return_std == False:
210            if len(X.shape) == 1:
211                return (
212                    self.y_mean_
213                    + mo.safe_sparse_dot(
214                        a=self.cook_test_set(new_X, **kwargs),
215                        b=self.beta_,
216                        backend=self.backend,
217                    )
218                )[0]
219
220            return self.y_mean_ + mo.safe_sparse_dot(
221                a=self.cook_test_set(X, **kwargs),
222                b=self.beta_,
223                backend=self.backend,
224            )
225
226        else:  # confidence interval required for preds?
227            if len(X.shape) == 1:
228                Z = self.cook_test_set(new_X, **kwargs)
229
230                pred_obj = lmf.beta_Sigma_hat_rvfl(
231                    s=self.s,
232                    sigma=self.sigma,
233                    X_star=Z,
234                    return_cov=True,
235                    beta_hat_=self.beta_,
236                    Sigma_hat_=self.Sigma_,
237                    backend=self.backend,
238                )
239
240                return (
241                    self.y_mean_ + pred_obj["preds"][0],
242                    pred_obj["preds_std"][0],
243                )
244
245            Z = self.cook_test_set(X, **kwargs)
246
247            pred_obj = lmf.beta_Sigma_hat_rvfl(
248                s=self.s,
249                sigma=self.sigma,
250                X_star=Z,
251                return_cov=True,
252                beta_hat_=self.beta_,
253                Sigma_hat_=self.Sigma_,
254                backend=self.backend,
255            )
256
257            return (self.y_mean_ + pred_obj["preds"], pred_obj["preds_std"])

Bayesian Random Vector Functional Link Network regression with one prior

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton', 'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original features are included (True) in model''s fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

seed: int
    reproducibility seed for nodes_sim=='uniform'

s: float
    std. dev. of regression parameters in Bayesian Ridge Regression

sigma: float
    std. dev. of residuals in Bayesian Ridge Regression

return_std: boolean
    if True, uncertainty around predictions is evaluated

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

beta_: array-like
    regression''s coefficients

Sigma_: array-like
    covariance of the distribution of fitted parameters

GCV_: float
    Generalized cross-validation error

y_mean_: float
    average response

Examples:

TBD
def fit(self, X, y, **kwargs):
137    def fit(self, X, y, **kwargs):
138        """Fit BayesianRVFLRegressor to training data (X, y).
139
140        Parameters:
141
142            X: {array-like}, shape = [n_samples, n_features]
143                Training vectors, where n_samples is the number
144                of samples and n_features is the number of features.
145
146            y: array-like, shape = [n_samples]
147                Target values.
148
149            **kwargs: additional parameters to be passed to
150                    self.cook_training_set
151
152        Returns:
153
154            self: object
155
156        """
157
158        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
159
160        fit_obj = lmf.beta_Sigma_hat_rvfl(
161            X=scaled_Z,
162            y=centered_y,
163            s=self.s,
164            sigma=self.sigma,
165            fit_intercept=False,
166            return_cov=self.return_std,
167            backend=self.backend,
168        )
169
170        self.beta_ = fit_obj["beta_hat"]
171
172        if self.return_std == True:
173            self.Sigma_ = fit_obj["Sigma_hat"]
174
175        self.GCV_ = fit_obj["GCV"]
176
177        return self

Fit BayesianRVFLRegressor to training data (X, y).

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set

Returns:

self: object
def predict(self, X, return_std=False, **kwargs):
179    def predict(self, X, return_std=False, **kwargs):
180        """Predict test data X.
181
182        Parameters:
183
184            X: {array-like}, shape = [n_samples, n_features]
185                Training vectors, where n_samples is the number
186                of samples and n_features is the number of features.
187
188            return_std: {boolean}, standard dev. is returned or not
189
190            **kwargs: additional parameters to be passed to
191                    self.cook_test_set
192
193        Returns:
194
195            model predictions: {array-like}
196
197        """
198
199        if len(X.shape) == 1:  # one observation in the test set only
200            n_features = X.shape[0]
201            new_X = mo.rbind(
202                x=X.reshape(1, n_features),
203                y=np.ones(n_features).reshape(1, n_features),
204                backend=self.backend,
205            )
206
207        self.return_std = return_std
208
209        if self.return_std == False:
210            if len(X.shape) == 1:
211                return (
212                    self.y_mean_
213                    + mo.safe_sparse_dot(
214                        a=self.cook_test_set(new_X, **kwargs),
215                        b=self.beta_,
216                        backend=self.backend,
217                    )
218                )[0]
219
220            return self.y_mean_ + mo.safe_sparse_dot(
221                a=self.cook_test_set(X, **kwargs),
222                b=self.beta_,
223                backend=self.backend,
224            )
225
226        else:  # confidence interval required for preds?
227            if len(X.shape) == 1:
228                Z = self.cook_test_set(new_X, **kwargs)
229
230                pred_obj = lmf.beta_Sigma_hat_rvfl(
231                    s=self.s,
232                    sigma=self.sigma,
233                    X_star=Z,
234                    return_cov=True,
235                    beta_hat_=self.beta_,
236                    Sigma_hat_=self.Sigma_,
237                    backend=self.backend,
238                )
239
240                return (
241                    self.y_mean_ + pred_obj["preds"][0],
242                    pred_obj["preds_std"][0],
243                )
244
245            Z = self.cook_test_set(X, **kwargs)
246
247            pred_obj = lmf.beta_Sigma_hat_rvfl(
248                s=self.s,
249                sigma=self.sigma,
250                X_star=Z,
251                return_cov=True,
252                beta_hat_=self.beta_,
253                Sigma_hat_=self.Sigma_,
254                backend=self.backend,
255            )
256
257            return (self.y_mean_ + pred_obj["preds"], pred_obj["preds_std"])

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

return_std: {boolean}, standard dev. is returned or not

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
class BayesianRVFL2Regressor(nnetsauce.Base, sklearn.base.RegressorMixin):
 15class BayesianRVFL2Regressor(Base, RegressorMixin):
 16    """Bayesian Random Vector Functional Link Network regression with two priors
 17
 18    Parameters:
 19
 20        n_hidden_features: int
 21            number of nodes in the hidden layer
 22
 23        activation_name: str
 24            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 25
 26        a: float
 27            hyperparameter for 'prelu' or 'elu' activation function
 28
 29        nodes_sim: str
 30            type of simulation for the nodes: 'sobol', 'hammersley', 'halton', 'uniform'
 31
 32        bias: boolean
 33            indicates if the hidden layer contains a bias term (True) or not (False)
 34
 35        dropout: float
 36            regularization parameter; (random) percentage of nodes dropped out
 37            of the training
 38
 39        direct_link: boolean
 40            indicates if the original features are included (True) in model''s fitting or not (False)
 41
 42        n_clusters: int
 43            number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering)
 44
 45        cluster_encode: bool
 46            defines how the variable containing clusters is treated (default is one-hot)
 47            if `False`, then labels are used, without one-hot encoding
 48
 49        type_clust: str
 50            type of clustering method: currently k-means ('kmeans') or Gaussian Mixture Model ('gmm')
 51
 52        type_scaling: a tuple of 3 strings
 53            scaling methods for inputs, hidden layer, and clustering respectively
 54            (and when relevant).
 55            Currently available: standardization ('std') or MinMax scaling ('minmax')
 56
 57        seed: int
 58            reproducibility seed for nodes_sim=='uniform'
 59
 60        s1: float
 61            std. dev. of init. regression parameters in Bayesian Ridge Regression
 62
 63        s2: float
 64            std. dev. of augmented regression parameters in Bayesian Ridge Regression
 65
 66        sigma: float
 67            std. dev. of residuals in Bayesian Ridge Regression
 68
 69        return_std: boolean
 70            if True, uncertainty around predictions is evaluated
 71
 72        backend: str
 73            "cpu" or "gpu" or "tpu"
 74
 75    Attributes:
 76
 77        beta_: array-like
 78            regression''s coefficients
 79
 80        Sigma_: array-like
 81            covariance of the distribution of fitted parameters
 82
 83        GCV_: float
 84            Generalized cross-validation error
 85
 86        y_mean_: float
 87            average response
 88
 89    Examples:
 90
 91    ```python
 92    TBD
 93    ```
 94
 95    """
 96
 97    # construct the object -----
 98
 99    def __init__(
100        self,
101        n_hidden_features=5,
102        activation_name="relu",
103        a=0.01,
104        nodes_sim="sobol",
105        bias=True,
106        dropout=0,
107        direct_link=True,
108        n_clusters=0,
109        cluster_encode=True,
110        type_clust="kmeans",
111        type_scaling=("std", "std", "std"),
112        seed=123,
113        s1=0.1,
114        s2=0.1,
115        sigma=0.05,
116        return_std=True,
117        backend="cpu",
118    ):
119        super().__init__(
120            n_hidden_features=n_hidden_features,
121            activation_name=activation_name,
122            a=a,
123            nodes_sim=nodes_sim,
124            bias=bias,
125            dropout=dropout,
126            direct_link=direct_link,
127            n_clusters=n_clusters,
128            cluster_encode=cluster_encode,
129            type_clust=type_clust,
130            type_scaling=type_scaling,
131            seed=seed,
132            backend=backend,
133        )
134
135        self.s1 = s1
136        self.s2 = s2
137        self.sigma = sigma
138        self.beta_ = None
139        self.Sigma_ = None
140        self.GCV_ = None
141        self.return_std = return_std
142
143    def fit(self, X, y, **kwargs):
144        """Fit BayesianRVFL2Regressor to training data (X, y)
145
146        Parameters:
147
148            X: {array-like}, shape = [n_samples, n_features]
149                Training vectors, where n_samples is the number
150                of samples and n_features is the number of features
151
152            y: array-like, shape = [n_samples]
153                Target values
154
155            **kwargs: additional parameters to be passed to
156                    self.cook_training_set
157
158        Returns:
159
160            self: object
161
162        """
163
164        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
165
166        n, p = X.shape
167        q = self.n_hidden_features
168
169        if self.direct_link == True:
170            r = p + self.n_clusters
171
172            block11 = (self.s1**2) * np.eye(r)
173            block12 = np.zeros((r, q))
174            block21 = np.zeros((q, r))
175            block22 = (self.s2**2) * np.eye(q)
176
177            Sigma_prior = mo.rbind(
178                x=mo.cbind(x=block11, y=block12, backend=self.backend),
179                y=mo.cbind(x=block21, y=block22, backend=self.backend),
180                backend=self.backend,
181            )
182
183        else:
184            Sigma_prior = (self.s2**2) * np.eye(q)
185
186        fit_obj = lmf.beta_Sigma_hat_rvfl2(
187            X=scaled_Z,
188            y=centered_y,
189            Sigma=Sigma_prior,
190            sigma=self.sigma,
191            fit_intercept=False,
192            return_cov=self.return_std,
193            backend=self.backend,
194        )
195
196        self.beta_ = fit_obj["beta_hat"]
197
198        if self.return_std == True:
199            self.Sigma_ = fit_obj["Sigma_hat"]
200
201        self.GCV_ = fit_obj["GCV"]
202
203        return self
204
205    def predict(self, X, return_std=False, **kwargs):
206        """Predict test data X.
207
208        Parameters:
209
210            X: {array-like}, shape = [n_samples, n_features]
211                Training vectors, where n_samples is the number
212                of samples and n_features is the number of features.
213
214            return_std: {boolean}, standard dev. is returned or not
215
216            **kwargs: additional parameters to be passed to
217                    self.cook_test_set
218
219        Returns:
220
221            model predictions: {array-like}
222
223        """
224
225        if len(X.shape) == 1:  # one observation in the test set only
226            n_features = X.shape[0]
227            new_X = mo.rbind(
228                x=X.reshape(1, n_features),
229                y=np.ones(n_features).reshape(1, n_features),
230                backend=self.backend,
231            )
232
233        self.return_std = return_std
234
235        if self.return_std == False:
236            if len(X.shape) == 1:
237                return (
238                    self.y_mean_
239                    + mo.safe_sparse_dot(
240                        self.cook_test_set(new_X, **kwargs),
241                        self.beta_,
242                        backend=self.backend,
243                    )
244                )[0]
245
246            return self.y_mean_ + mo.safe_sparse_dot(
247                self.cook_test_set(X, **kwargs),
248                self.beta_,
249                backend=self.backend,
250            )
251
252        else:  # confidence interval required for preds?
253            if len(X.shape) == 1:
254                Z = self.cook_test_set(new_X, **kwargs)
255
256                pred_obj = lmf.beta_Sigma_hat_rvfl2(
257                    X_star=Z,
258                    return_cov=self.return_std,
259                    beta_hat_=self.beta_,
260                    Sigma_hat_=self.Sigma_,
261                    backend=self.backend,
262                )
263
264                return (
265                    self.y_mean_ + pred_obj["preds"][0],
266                    pred_obj["preds_std"][0],
267                )
268
269            Z = self.cook_test_set(X, **kwargs)
270
271            pred_obj = lmf.beta_Sigma_hat_rvfl2(
272                X_star=Z,
273                return_cov=self.return_std,
274                beta_hat_=self.beta_,
275                Sigma_hat_=self.Sigma_,
276                backend=self.backend,
277            )
278
279            return (self.y_mean_ + pred_obj["preds"], pred_obj["preds_std"])

Bayesian Random Vector Functional Link Network regression with two priors

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton', 'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original features are included (True) in model''s fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

seed: int
    reproducibility seed for nodes_sim=='uniform'

s1: float
    std. dev. of init. regression parameters in Bayesian Ridge Regression

s2: float
    std. dev. of augmented regression parameters in Bayesian Ridge Regression

sigma: float
    std. dev. of residuals in Bayesian Ridge Regression

return_std: boolean
    if True, uncertainty around predictions is evaluated

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

beta_: array-like
    regression''s coefficients

Sigma_: array-like
    covariance of the distribution of fitted parameters

GCV_: float
    Generalized cross-validation error

y_mean_: float
    average response

Examples:

TBD
def fit(self, X, y, **kwargs):
143    def fit(self, X, y, **kwargs):
144        """Fit BayesianRVFL2Regressor to training data (X, y)
145
146        Parameters:
147
148            X: {array-like}, shape = [n_samples, n_features]
149                Training vectors, where n_samples is the number
150                of samples and n_features is the number of features
151
152            y: array-like, shape = [n_samples]
153                Target values
154
155            **kwargs: additional parameters to be passed to
156                    self.cook_training_set
157
158        Returns:
159
160            self: object
161
162        """
163
164        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
165
166        n, p = X.shape
167        q = self.n_hidden_features
168
169        if self.direct_link == True:
170            r = p + self.n_clusters
171
172            block11 = (self.s1**2) * np.eye(r)
173            block12 = np.zeros((r, q))
174            block21 = np.zeros((q, r))
175            block22 = (self.s2**2) * np.eye(q)
176
177            Sigma_prior = mo.rbind(
178                x=mo.cbind(x=block11, y=block12, backend=self.backend),
179                y=mo.cbind(x=block21, y=block22, backend=self.backend),
180                backend=self.backend,
181            )
182
183        else:
184            Sigma_prior = (self.s2**2) * np.eye(q)
185
186        fit_obj = lmf.beta_Sigma_hat_rvfl2(
187            X=scaled_Z,
188            y=centered_y,
189            Sigma=Sigma_prior,
190            sigma=self.sigma,
191            fit_intercept=False,
192            return_cov=self.return_std,
193            backend=self.backend,
194        )
195
196        self.beta_ = fit_obj["beta_hat"]
197
198        if self.return_std == True:
199            self.Sigma_ = fit_obj["Sigma_hat"]
200
201        self.GCV_ = fit_obj["GCV"]
202
203        return self

Fit BayesianRVFL2Regressor to training data (X, y)

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

y: array-like, shape = [n_samples]
    Target values

**kwargs: additional parameters to be passed to
        self.cook_training_set

Returns:

self: object
def predict(self, X, return_std=False, **kwargs):
205    def predict(self, X, return_std=False, **kwargs):
206        """Predict test data X.
207
208        Parameters:
209
210            X: {array-like}, shape = [n_samples, n_features]
211                Training vectors, where n_samples is the number
212                of samples and n_features is the number of features.
213
214            return_std: {boolean}, standard dev. is returned or not
215
216            **kwargs: additional parameters to be passed to
217                    self.cook_test_set
218
219        Returns:
220
221            model predictions: {array-like}
222
223        """
224
225        if len(X.shape) == 1:  # one observation in the test set only
226            n_features = X.shape[0]
227            new_X = mo.rbind(
228                x=X.reshape(1, n_features),
229                y=np.ones(n_features).reshape(1, n_features),
230                backend=self.backend,
231            )
232
233        self.return_std = return_std
234
235        if self.return_std == False:
236            if len(X.shape) == 1:
237                return (
238                    self.y_mean_
239                    + mo.safe_sparse_dot(
240                        self.cook_test_set(new_X, **kwargs),
241                        self.beta_,
242                        backend=self.backend,
243                    )
244                )[0]
245
246            return self.y_mean_ + mo.safe_sparse_dot(
247                self.cook_test_set(X, **kwargs),
248                self.beta_,
249                backend=self.backend,
250            )
251
252        else:  # confidence interval required for preds?
253            if len(X.shape) == 1:
254                Z = self.cook_test_set(new_X, **kwargs)
255
256                pred_obj = lmf.beta_Sigma_hat_rvfl2(
257                    X_star=Z,
258                    return_cov=self.return_std,
259                    beta_hat_=self.beta_,
260                    Sigma_hat_=self.Sigma_,
261                    backend=self.backend,
262                )
263
264                return (
265                    self.y_mean_ + pred_obj["preds"][0],
266                    pred_obj["preds_std"][0],
267                )
268
269            Z = self.cook_test_set(X, **kwargs)
270
271            pred_obj = lmf.beta_Sigma_hat_rvfl2(
272                X_star=Z,
273                return_cov=self.return_std,
274                beta_hat_=self.beta_,
275                Sigma_hat_=self.Sigma_,
276                backend=self.backend,
277            )
278
279            return (self.y_mean_ + pred_obj["preds"], pred_obj["preds_std"])

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

return_std: {boolean}, standard dev. is returned or not

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
class ClassicalMTS(nnetsauce.Base):
 35class ClassicalMTS(Base):
 36    """Multivariate time series (FactorMTS) forecasting with Factor models
 37
 38    Parameters:
 39
 40        model: type of model: str.
 41            currently, 'VAR' or 'VECM'.
 42
 43    Attributes:
 44
 45        df_: data frame
 46            the input data frame, in case a data.frame is provided to `fit`
 47
 48        level_: int
 49            level of confidence for prediction intervals (default is 95)
 50
 51    Examples:
 52    See examples/classical_mts_timeseries.py
 53    """
 54
 55    # construct the object -----
 56
 57    def __init__(self, model="VAR"):
 58
 59        self.model = model
 60        if self.model == "VAR":
 61            self.obj = VAR
 62        elif self.model == "VECM":
 63            self.obj = VECM
 64        self.n_series = None
 65        self.mean_ = None
 66        self.upper_ = None
 67        self.lower_ = None
 68        self.output_dates_ = None
 69        self.alpha_ = None
 70        self.df_ = None
 71        self.residuals_ = []
 72        self.sims_ = None
 73        self.level_ = None
 74
 75    def fit(self, X, **kwargs):
 76        """Fit FactorMTS model to training data X, with optional regressors xreg
 77
 78        Parameters:
 79
 80        X: {array-like}, shape = [n_samples, n_features]
 81            Training time series, where n_samples is the number
 82            of samples and n_features is the number of features;
 83            X must be in increasing order (most recent observations last)
 84
 85        **kwargs: for now, additional parameters to be passed to for kernel density estimation, when needed (see sklearn.neighbors.KernelDensity)
 86
 87        Returns:
 88
 89        self: object
 90        """
 91
 92        self.n_series = X.shape[1]
 93
 94        if (
 95            isinstance(X, pd.DataFrame) is False
 96        ):  # input data set is a numpy array
 97            X = pd.DataFrame(X)
 98            self.series_names = ["series" + str(i) for i in range(X.shape[1])]
 99
100        else:  # input data set is a DataFrame with column names
101
102            X_index = None
103            if X.index is not None:
104                X_index = X.index
105                X = copy.deepcopy(mo.convert_df_to_numeric(X))
106            if X_index is not None:
107                X.index = X_index
108            self.series_names = X.columns.tolist()
109
110        if isinstance(X, pd.DataFrame):
111            self.df_ = X
112            X = X.values
113            self.df_.columns = self.series_names
114            self.input_dates = ts.compute_input_dates(self.df_)
115        else:
116            self.df_ = pd.DataFrame(X, columns=self.series_names)
117            self.input_dates = ts.compute_input_dates(self.df_)
118
119        self.obj = self.obj(X, **kwargs).fit(**kwargs)
120
121        return self
122
123    def predict(self, h=5, level=95, **kwargs):
124        """Forecast all the time series, h steps ahead
125
126        Parameters:
127
128        h: {integer}
129            Forecasting horizon
130
131        **kwargs: additional parameters to be passed to
132                self.cook_test_set
133
134        Returns:
135
136        model predictions for horizon = h: {array-like}
137
138        """
139
140        self.output_dates_, frequency = ts.compute_output_dates(self.df_, h)
141
142        self.level_ = level
143
144        self.lower_ = None  # do not remove (/!\)
145
146        self.upper_ = None  # do not remove (/!\)
147
148        self.sims_ = None  # do not remove (/!\)
149
150        self.level_ = level
151
152        self.alpha_ = 100 - level
153
154        # Named tuple for forecast results
155        DescribeResult = namedtuple(
156            "DescribeResult", ("mean", "lower", "upper")
157        )
158
159        if self.model == "VAR":
160            mean_forecast, lower_bound, upper_bound = (
161                self.obj.forecast_interval(
162                    self.obj.endog, steps=h, alpha=self.alpha_ / 100, **kwargs
163                )
164            )
165
166        elif self.model == "VECM":
167            forecast_result = self.obj.predict(steps=h)
168            mean_forecast = forecast_result
169            lower_bound, upper_bound = self._compute_confidence_intervals(
170                forecast_result, alpha=self.alpha_ / 100, **kwargs
171            )
172
173        self.mean_ = pd.DataFrame(mean_forecast, columns=self.series_names)
174        self.mean_.index = self.output_dates_
175        self.lower_ = pd.DataFrame(lower_bound, columns=self.series_names)
176        self.lower_.index = self.output_dates_
177        self.upper_ = pd.DataFrame(upper_bound, columns=self.series_names)
178        self.upper_.index = self.output_dates_
179
180        return DescribeResult(
181            mean=self.mean_, lower=self.lower_, upper=self.upper_
182        )
183
184    def _compute_confidence_intervals(self, forecast_result, alpha):
185        """
186        Compute confidence intervals for VECM forecasts.
187        Uses the covariance of residuals to approximate the confidence intervals.
188        """
189        residuals = self.obj.resid
190        cov_matrix = np.cov(residuals.T)  # Covariance matrix of residuals
191        std_errors = np.sqrt(np.diag(cov_matrix))  # Standard errors
192
193        z_value = norm.ppf(1 - alpha / 2)  # Z-score for the given alpha level
194        lower_bound = forecast_result - z_value * std_errors
195        upper_bound = forecast_result + z_value * std_errors
196
197        return lower_bound, upper_bound
198
199    def score(self, X, training_index, testing_index, scoring=None, **kwargs):
200        """Train on training_index, score on testing_index."""
201
202        assert (
203            bool(set(training_index).intersection(set(testing_index))) == False
204        ), "Non-overlapping 'training_index' and 'testing_index' required"
205
206        # Dimensions
207        try:
208            # multivariate time series
209            n, p = X.shape
210        except:
211            # univariate time series
212            n = X.shape[0]
213            p = 1
214
215        # Training and testing sets
216        if p > 1:
217            X_train = X[training_index, :]
218            X_test = X[testing_index, :]
219        else:
220            X_train = X[training_index]
221            X_test = X[testing_index]
222
223        # Horizon
224        h = len(testing_index)
225        assert (
226            len(training_index) + h
227        ) <= n, "Please check lengths of training and testing windows"
228
229        # Fit and predict
230        self.fit(X_train, **kwargs)
231        preds = self.predict(h=h, **kwargs)
232
233        if scoring is None:
234            scoring = "neg_root_mean_squared_error"
235
236        # check inputs
237        assert scoring in (
238            "explained_variance",
239            "neg_mean_absolute_error",
240            "neg_mean_squared_error",
241            "neg_root_mean_squared_error",
242            "neg_mean_squared_log_error",
243            "neg_median_absolute_error",
244            "r2",
245        ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
246                               'neg_mean_squared_error', 'neg_root_mean_squared_error', 'neg_mean_squared_log_error', \
247                               'neg_median_absolute_error', 'r2')"
248
249        scoring_options = {
250            "explained_variance": skm2.explained_variance_score,
251            "neg_mean_absolute_error": skm2.mean_absolute_error,
252            "neg_mean_squared_error": skm2.mean_squared_error,
253            "neg_root_mean_squared_error": lambda x, y: np.sqrt(
254                skm2.mean_squared_error(x, y)
255            ),
256            "neg_mean_squared_log_error": skm2.mean_squared_log_error,
257            "neg_median_absolute_error": skm2.median_absolute_error,
258            "r2": skm2.r2_score,
259        }
260
261        # if p > 1:
262        #     return tuple(
263        #         [
264        #             scoring_options[scoring](
265        #                 X_test[:, i], preds[:, i]#, **kwargs
266        #             )
267        #             for i in range(p)
268        #         ]
269        #     )
270        # else:
271        return scoring_options[scoring](X_test, preds)
272
273    def plot(self, series=None, type_axis="dates", type_plot="pi"):
274        """Plot time series forecast
275
276        Parameters:
277
278        series: {integer} or {string}
279            series index or name
280
281        """
282
283        assert all(
284            [
285                self.mean_ is not None,
286                self.lower_ is not None,
287                self.upper_ is not None,
288                self.output_dates_ is not None,
289            ]
290        ), "model forecasting must be obtained first (with predict)"
291
292        if series is None:
293            assert (
294                self.n_series == 1
295            ), "please specify series index or name (n_series > 1)"
296            series = 0
297
298        if isinstance(series, str):
299            assert (
300                series in self.series_names
301            ), f"series {series} doesn't exist in the input dataset"
302            series_idx = self.df_.columns.get_loc(series)
303        else:
304            assert isinstance(series, int) and (
305                0 <= series < self.n_series
306            ), f"check series index (< {self.n_series})"
307            series_idx = series
308
309        y_all = list(self.df_.iloc[:, series_idx]) + list(
310            self.mean_.iloc[:, series_idx]
311        )
312        y_test = list(self.mean_.iloc[:, series_idx])
313        n_points_all = len(y_all)
314        n_points_train = self.df_.shape[0]
315
316        if type_axis == "numeric":
317            x_all = [i for i in range(n_points_all)]
318            x_test = [i for i in range(n_points_train, n_points_all)]
319
320        if type_axis == "dates":  # use dates
321            x_all = np.concatenate(
322                (self.input_dates.values, self.output_dates_.values), axis=None
323            )
324            x_test = self.output_dates_.values
325
326        if type_plot == "pi":
327            fig, ax = plt.subplots()
328            ax.plot(x_all, y_all, "-")
329            ax.plot(x_test, y_test, "-", color="orange")
330            ax.fill_between(
331                x_test,
332                self.lower_.iloc[:, series_idx],
333                self.upper_.iloc[:, series_idx],
334                alpha=0.2,
335                color="orange",
336            )
337            if self.replications is None:
338                if self.n_series > 1:
339                    plt.title(
340                        f"prediction intervals for {series}",
341                        loc="left",
342                        fontsize=12,
343                        fontweight=0,
344                        color="black",
345                    )
346                else:
347                    plt.title(
348                        f"prediction intervals for input time series",
349                        loc="left",
350                        fontsize=12,
351                        fontweight=0,
352                        color="black",
353                    )
354                plt.show()
355            else:  # self.replications is not None
356                if self.n_series > 1:
357                    plt.title(
358                        f"prediction intervals for {self.replications} simulations of {series}",
359                        loc="left",
360                        fontsize=12,
361                        fontweight=0,
362                        color="black",
363                    )
364                else:
365                    plt.title(
366                        f"prediction intervals for {self.replications} simulations of input time series",
367                        loc="left",
368                        fontsize=12,
369                        fontweight=0,
370                        color="black",
371                    )
372                plt.show()
373
374        if type_plot == "spaghetti":
375            palette = plt.get_cmap("Set1")
376            sims_ix = getsims(self.sims_, series_idx)
377            plt.plot(x_all, y_all, "-")
378            for col_ix in range(
379                sims_ix.shape[1]
380            ):  # avoid this when there are thousands of simulations
381                plt.plot(
382                    x_test,
383                    sims_ix[:, col_ix],
384                    "-",
385                    color=palette(col_ix),
386                    linewidth=1,
387                    alpha=0.9,
388                )
389            plt.plot(x_all, y_all, "-", color="black")
390            plt.plot(x_test, y_test, "-", color="blue")
391            # Add titles
392            if self.n_series > 1:
393                plt.title(
394                    f"{self.replications} simulations of {series}",
395                    loc="left",
396                    fontsize=12,
397                    fontweight=0,
398                    color="black",
399                )
400            else:
401                plt.title(
402                    f"{self.replications} simulations of input time series",
403                    loc="left",
404                    fontsize=12,
405                    fontweight=0,
406                    color="black",
407                )
408            plt.xlabel("Time")
409            plt.ylabel("Values")
410            # Show the graph
411            plt.show()
412
413    def cross_val_score(
414        self,
415        X,
416        scoring="root_mean_squared_error",
417        n_jobs=None,
418        verbose=0,
419        xreg=None,
420        initial_window=5,
421        horizon=3,
422        fixed_window=False,
423        show_progress=True,
424        level=95,
425        **kwargs,
426    ):
427        """Evaluate a score by time series cross-validation.
428
429        Parameters:
430
431            X: {array-like, sparse matrix} of shape (n_samples, n_features)
432                The data to fit.
433
434            scoring: str or a function
435                A str in ('root_mean_squared_error', 'mean_squared_error', 'mean_error',
436                'mean_absolute_error', 'mean_error', 'mean_percentage_error',
437                'mean_absolute_percentage_error',  'winkler_score', 'coverage')
438                Or a function defined as 'coverage' and 'winkler_score' in `utils.timeseries`
439
440            n_jobs: int, default=None
441                Number of jobs to run in parallel.
442
443            verbose: int, default=0
444                The verbosity level.
445
446            xreg: array-like, optional (default=None)
447                Additional (external) regressors to be passed to `fit`
448                xreg must be in 'increasing' order (most recent observations last)
449
450            initial_window: int
451                initial number of consecutive values in each training set sample
452
453            horizon: int
454                number of consecutive values in test set sample
455
456            fixed_window: boolean
457                if False, all training samples start at index 0, and the training
458                window's size is increasing.
459                if True, the training window's size is fixed, and the window is
460                rolling forward
461
462            show_progress: boolean
463                if True, a progress bar is printed
464
465            **kwargs: dict
466                additional parameters to be passed to `fit` and `predict`
467
468        Returns:
469
470            A tuple: descriptive statistics or errors and raw errors
471
472        """
473        tscv = TimeSeriesSplit()
474
475        tscv_obj = tscv.split(
476            X,
477            initial_window=initial_window,
478            horizon=horizon,
479            fixed_window=fixed_window,
480        )
481
482        if isinstance(scoring, str):
483
484            assert scoring in (
485                "root_mean_squared_error",
486                "mean_squared_error",
487                "mean_error",
488                "mean_absolute_error",
489                "mean_percentage_error",
490                "mean_absolute_percentage_error",
491                "winkler_score",
492                "coverage",
493            ), "must have scoring in ('root_mean_squared_error', 'mean_squared_error', 'mean_error', 'mean_absolute_error', 'mean_error', 'mean_percentage_error', 'mean_absolute_percentage_error',  'winkler_score', 'coverage')"
494
495            def err_func(X_test, X_pred, scoring):
496                if (self.replications is not None) or (
497                    self.type_pi == "gaussian"
498                ):  # probabilistic
499                    if scoring == "winkler_score":
500                        return winkler_score(X_pred, X_test, level=level)
501                    elif scoring == "coverage":
502                        return coverage(X_pred, X_test, level=level)
503                    else:
504                        return mean_errors(
505                            pred=X_pred.mean, actual=X_test, scoring=scoring
506                        )
507                else:  # not probabilistic
508                    return mean_errors(
509                        pred=X_pred, actual=X_test, scoring=scoring
510                    )
511
512        else:  # isinstance(scoring, str) = False
513
514            err_func = scoring
515
516        errors = []
517
518        train_indices = []
519
520        test_indices = []
521
522        for train_index, test_index in tscv_obj:
523            train_indices.append(train_index)
524            test_indices.append(test_index)
525
526        if show_progress is True:
527            iterator = tqdm(
528                zip(train_indices, test_indices), total=len(train_indices)
529            )
530        else:
531            iterator = zip(train_indices, test_indices)
532
533        for train_index, test_index in iterator:
534
535            if verbose == 1:
536                print(f"TRAIN: {train_index}")
537                print(f"TEST: {test_index}")
538
539            if isinstance(X, pd.DataFrame):
540                self.fit(X.iloc[train_index, :], xreg=xreg, **kwargs)
541                X_test = X.iloc[test_index, :]
542            else:
543                self.fit(X[train_index, :], xreg=xreg, **kwargs)
544                X_test = X[test_index, :]
545            X_pred = self.predict(h=int(len(test_index)), level=level, **kwargs)
546
547            errors.append(err_func(X_test, X_pred, scoring))
548
549        res = np.asarray(errors)
550
551        return res, describe(res)

Multivariate time series (FactorMTS) forecasting with Factor models

Parameters:

model: type of model: str.
    currently, 'VAR' or 'VECM'.

Attributes:

df_: data frame
    the input data frame, in case a data.frame is provided to `fit`

level_: int
    level of confidence for prediction intervals (default is 95)

Examples: See examples/classical_mts_timeseries.py

def fit(self, X, **kwargs):
 75    def fit(self, X, **kwargs):
 76        """Fit FactorMTS model to training data X, with optional regressors xreg
 77
 78        Parameters:
 79
 80        X: {array-like}, shape = [n_samples, n_features]
 81            Training time series, where n_samples is the number
 82            of samples and n_features is the number of features;
 83            X must be in increasing order (most recent observations last)
 84
 85        **kwargs: for now, additional parameters to be passed to for kernel density estimation, when needed (see sklearn.neighbors.KernelDensity)
 86
 87        Returns:
 88
 89        self: object
 90        """
 91
 92        self.n_series = X.shape[1]
 93
 94        if (
 95            isinstance(X, pd.DataFrame) is False
 96        ):  # input data set is a numpy array
 97            X = pd.DataFrame(X)
 98            self.series_names = ["series" + str(i) for i in range(X.shape[1])]
 99
100        else:  # input data set is a DataFrame with column names
101
102            X_index = None
103            if X.index is not None:
104                X_index = X.index
105                X = copy.deepcopy(mo.convert_df_to_numeric(X))
106            if X_index is not None:
107                X.index = X_index
108            self.series_names = X.columns.tolist()
109
110        if isinstance(X, pd.DataFrame):
111            self.df_ = X
112            X = X.values
113            self.df_.columns = self.series_names
114            self.input_dates = ts.compute_input_dates(self.df_)
115        else:
116            self.df_ = pd.DataFrame(X, columns=self.series_names)
117            self.input_dates = ts.compute_input_dates(self.df_)
118
119        self.obj = self.obj(X, **kwargs).fit(**kwargs)
120
121        return self

Fit FactorMTS model to training data X, with optional regressors xreg

Parameters:

X: {array-like}, shape = [n_samples, n_features] Training time series, where n_samples is the number of samples and n_features is the number of features; X must be in increasing order (most recent observations last)

**kwargs: for now, additional parameters to be passed to for kernel density estimation, when needed (see sklearn.neighbors.KernelDensity)

Returns:

self: object

def predict(self, h=5, level=95, **kwargs):
123    def predict(self, h=5, level=95, **kwargs):
124        """Forecast all the time series, h steps ahead
125
126        Parameters:
127
128        h: {integer}
129            Forecasting horizon
130
131        **kwargs: additional parameters to be passed to
132                self.cook_test_set
133
134        Returns:
135
136        model predictions for horizon = h: {array-like}
137
138        """
139
140        self.output_dates_, frequency = ts.compute_output_dates(self.df_, h)
141
142        self.level_ = level
143
144        self.lower_ = None  # do not remove (/!\)
145
146        self.upper_ = None  # do not remove (/!\)
147
148        self.sims_ = None  # do not remove (/!\)
149
150        self.level_ = level
151
152        self.alpha_ = 100 - level
153
154        # Named tuple for forecast results
155        DescribeResult = namedtuple(
156            "DescribeResult", ("mean", "lower", "upper")
157        )
158
159        if self.model == "VAR":
160            mean_forecast, lower_bound, upper_bound = (
161                self.obj.forecast_interval(
162                    self.obj.endog, steps=h, alpha=self.alpha_ / 100, **kwargs
163                )
164            )
165
166        elif self.model == "VECM":
167            forecast_result = self.obj.predict(steps=h)
168            mean_forecast = forecast_result
169            lower_bound, upper_bound = self._compute_confidence_intervals(
170                forecast_result, alpha=self.alpha_ / 100, **kwargs
171            )
172
173        self.mean_ = pd.DataFrame(mean_forecast, columns=self.series_names)
174        self.mean_.index = self.output_dates_
175        self.lower_ = pd.DataFrame(lower_bound, columns=self.series_names)
176        self.lower_.index = self.output_dates_
177        self.upper_ = pd.DataFrame(upper_bound, columns=self.series_names)
178        self.upper_.index = self.output_dates_
179
180        return DescribeResult(
181            mean=self.mean_, lower=self.lower_, upper=self.upper_
182        )

Forecast all the time series, h steps ahead

Parameters:

h: {integer} Forecasting horizon

**kwargs: additional parameters to be passed to self.cook_test_set

Returns:

model predictions for horizon = h: {array-like}

def score(self, X, training_index, testing_index, scoring=None, **kwargs):
199    def score(self, X, training_index, testing_index, scoring=None, **kwargs):
200        """Train on training_index, score on testing_index."""
201
202        assert (
203            bool(set(training_index).intersection(set(testing_index))) == False
204        ), "Non-overlapping 'training_index' and 'testing_index' required"
205
206        # Dimensions
207        try:
208            # multivariate time series
209            n, p = X.shape
210        except:
211            # univariate time series
212            n = X.shape[0]
213            p = 1
214
215        # Training and testing sets
216        if p > 1:
217            X_train = X[training_index, :]
218            X_test = X[testing_index, :]
219        else:
220            X_train = X[training_index]
221            X_test = X[testing_index]
222
223        # Horizon
224        h = len(testing_index)
225        assert (
226            len(training_index) + h
227        ) <= n, "Please check lengths of training and testing windows"
228
229        # Fit and predict
230        self.fit(X_train, **kwargs)
231        preds = self.predict(h=h, **kwargs)
232
233        if scoring is None:
234            scoring = "neg_root_mean_squared_error"
235
236        # check inputs
237        assert scoring in (
238            "explained_variance",
239            "neg_mean_absolute_error",
240            "neg_mean_squared_error",
241            "neg_root_mean_squared_error",
242            "neg_mean_squared_log_error",
243            "neg_median_absolute_error",
244            "r2",
245        ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
246                               'neg_mean_squared_error', 'neg_root_mean_squared_error', 'neg_mean_squared_log_error', \
247                               'neg_median_absolute_error', 'r2')"
248
249        scoring_options = {
250            "explained_variance": skm2.explained_variance_score,
251            "neg_mean_absolute_error": skm2.mean_absolute_error,
252            "neg_mean_squared_error": skm2.mean_squared_error,
253            "neg_root_mean_squared_error": lambda x, y: np.sqrt(
254                skm2.mean_squared_error(x, y)
255            ),
256            "neg_mean_squared_log_error": skm2.mean_squared_log_error,
257            "neg_median_absolute_error": skm2.median_absolute_error,
258            "r2": skm2.r2_score,
259        }
260
261        # if p > 1:
262        #     return tuple(
263        #         [
264        #             scoring_options[scoring](
265        #                 X_test[:, i], preds[:, i]#, **kwargs
266        #             )
267        #             for i in range(p)
268        #         ]
269        #     )
270        # else:
271        return scoring_options[scoring](X_test, preds)

Train on training_index, score on testing_index.

class CustomClassifier(nnetsauce.custom.custom.Custom, sklearn.base.ClassifierMixin):
 14class CustomClassifier(Custom, ClassifierMixin):
 15    """Custom Classification model
 16
 17    Attributes:
 18
 19        obj: object
 20            any object containing a method fit (obj.fit()) and a method predict
 21            (obj.predict())
 22
 23        n_hidden_features: int
 24            number of nodes in the hidden layer
 25
 26        activation_name: str
 27            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 28
 29        a: float
 30            hyperparameter for 'prelu' or 'elu' activation function
 31
 32        nodes_sim: str
 33            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 34            'uniform'
 35
 36        bias: boolean
 37            indicates if the hidden layer contains a bias term (True) or not
 38            (False)
 39
 40        dropout: float
 41            regularization parameter; (random) percentage of nodes dropped out
 42            of the training
 43
 44        direct_link: boolean
 45            indicates if the original predictors are included (True) in model''s
 46            fitting or not (False)
 47
 48        n_clusters: int
 49            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 50                no clustering)
 51
 52        cluster_encode: bool
 53            defines how the variable containing clusters is treated (default is one-hot)
 54            if `False`, then labels are used, without one-hot encoding
 55
 56        type_clust: str
 57            type of clustering method: currently k-means ('kmeans') or Gaussian
 58            Mixture Model ('gmm')
 59
 60        type_scaling: a tuple of 3 strings
 61            scaling methods for inputs, hidden layer, and clustering respectively
 62            (and when relevant).
 63            Currently available: standardization ('std') or MinMax scaling ('minmax')
 64
 65        col_sample: float
 66            percentage of covariates randomly chosen for training
 67
 68        row_sample: float
 69            percentage of rows chosen for training, by stratified bootstrapping
 70
 71        level: float
 72            confidence level for prediction sets. Default is None.
 73
 74        pi_method: str
 75            method for constructing the prediction sets: 'icp', 'tcp' if level is not None. Default is 'icp'.
 76
 77        seed: int
 78            reproducibility seed for nodes_sim=='uniform'
 79
 80        backend: str
 81            "cpu" or "gpu" or "tpu"
 82
 83    Examples:
 84
 85    Note: it's better to use the `DeepClassifier` or `LazyDeepClassifier` classes directly
 86
 87    ```python
 88    import nnetsauce as ns
 89    from sklearn.ensemble import RandomForestClassifier
 90    from sklearn.model_selection import train_test_split
 91    from sklearn.datasets import load_digits
 92    from time import time
 93
 94    digits = load_digits()
 95    X = digits.data
 96    y = digits.target
 97    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
 98                                                        random_state=123)
 99
100    # layer 1 (base layer) ----
101    layer1_regr = RandomForestClassifier(n_estimators=10, random_state=123)
102
103    start = time()
104
105    layer1_regr.fit(X_train, y_train)
106
107    # Accuracy in layer 1
108    print(layer1_regr.score(X_test, y_test))
109
110    # layer 2 using layer 1 ----
111    layer2_regr = ns.CustomClassifier(obj = layer1_regr, n_hidden_features=5,
112                            direct_link=True, bias=True,
113                            nodes_sim='uniform', activation_name='relu',
114                            n_clusters=2, seed=123)
115    layer2_regr.fit(X_train, y_train)
116
117    # Accuracy in layer 2
118    print(layer2_regr.score(X_test, y_test))
119
120    # layer 3 using layer 2 ----
121    layer3_regr = ns.CustomClassifier(obj = layer2_regr, n_hidden_features=10,
122                            direct_link=True, bias=True, dropout=0.7,
123                            nodes_sim='uniform', activation_name='relu',
124                            n_clusters=2, seed=123)
125    layer3_regr.fit(X_train, y_train)
126
127    # Accuracy in layer 3
128    print(layer3_regr.score(X_test, y_test))
129
130    print(f"Elapsed {time() - start}")
131    ```
132
133    """
134
135    # construct the object -----
136
137    def __init__(
138        self,
139        obj,
140        n_hidden_features=5,
141        activation_name="relu",
142        a=0.01,
143        nodes_sim="sobol",
144        bias=True,
145        dropout=0,
146        direct_link=True,
147        n_clusters=2,
148        cluster_encode=True,
149        type_clust="kmeans",
150        type_scaling=("std", "std", "std"),
151        col_sample=1,
152        row_sample=1,
153        level=None,
154        pi_method="icp",
155        seed=123,
156        backend="cpu",
157    ):
158        super().__init__(
159            obj=obj,
160            n_hidden_features=n_hidden_features,
161            activation_name=activation_name,
162            a=a,
163            nodes_sim=nodes_sim,
164            bias=bias,
165            dropout=dropout,
166            direct_link=direct_link,
167            n_clusters=n_clusters,
168            cluster_encode=cluster_encode,
169            type_clust=type_clust,
170            type_scaling=type_scaling,
171            col_sample=col_sample,
172            row_sample=row_sample,
173            seed=seed,
174            backend=backend,
175        )
176        self.level = level
177        self.pi_method = pi_method
178        self.type_fit = "classification"
179        if self.level is not None:
180            self.obj = PredictionSet(
181                self.obj, level=self.level, method=self.pi_method
182            )
183
184    def fit(self, X, y, sample_weight=None, **kwargs):
185        """Fit custom model to training data (X, y).
186
187        Parameters:
188
189            X: {array-like}, shape = [n_samples, n_features]
190                Training vectors, where n_samples is the number
191                of samples and n_features is the number of features.
192
193            y: array-like, shape = [n_samples]
194                Target values.
195
196            sample_weight: array-like, shape = [n_samples]
197                Sample weights.
198
199            **kwargs: additional parameters to be passed to
200                        self.cook_training_set or self.obj.fit
201
202        Returns:
203
204            self: object
205        """
206
207        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
208        self.n_classes_ = len(np.unique(y))  # for compatibility with sklearn
209
210        if self.level is not None:
211            self.obj = PredictionSet(
212                obj=self.obj, method=self.pi_method, level=self.level
213            )
214
215        # if sample_weights, else: (must use self.row_index)
216        if sample_weight is not None:
217            self.obj.fit(
218                scaled_Z,
219                output_y,
220                sample_weight=sample_weight[self.index_row_].ravel(),
221                # **kwargs
222            )
223
224            return self
225
226        # if sample_weight is None:
227        self.obj.fit(scaled_Z, output_y)
228        self.classes_ = np.unique(y)  # for compatibility with sklearn
229        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
230
231        return self
232
233    def partial_fit(self, X, y, sample_weight=None, **kwargs):
234        """Partial fit custom model to training data (X, y).
235
236        Parameters:
237
238            X: {array-like}, shape = [n_samples, n_features]
239                Subset of training vectors, where n_samples is the number
240                of samples and n_features is the number of features.
241
242            y: array-like, shape = [n_samples]
243                Subset of target values.
244
245            sample_weight: array-like, shape = [n_samples]
246                Sample weights.
247
248            **kwargs: additional parameters to be passed to
249                        self.cook_training_set or self.obj.fit
250
251        Returns:
252
253            self: object
254        """
255
256        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
257        self.n_classes_ = len(np.unique(y))  # for compatibility with sklearn
258
259        # if sample_weights, else: (must use self.row_index)
260        if sample_weight is not None:
261            try:
262                self.obj.partial_fit(
263                    scaled_Z,
264                    output_y,
265                    sample_weight=sample_weight[self.index_row_].ravel(),
266                    # **kwargs
267                )
268            except:
269                NotImplementedError
270
271            return self
272
273        # if sample_weight is None:
274        try:
275            self.obj.fit(scaled_Z, output_y)
276        except:
277            raise NotImplementedError
278
279        self.classes_ = np.unique(y)  # for compatibility with sklearn
280        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
281
282        return self
283
284    def predict(self, X, **kwargs):
285        """Predict test data X.
286
287        Parameters:
288
289            X: {array-like}, shape = [n_samples, n_features]
290                Training vectors, where n_samples is the number
291                of samples and n_features is the number of features.
292
293            **kwargs: additional parameters to be passed to
294                    self.cook_test_set
295
296        Returns:
297
298            model predictions: {array-like}
299        """
300
301        if len(X.shape) == 1:
302            n_features = X.shape[0]
303            new_X = mo.rbind(
304                X.reshape(1, n_features),
305                np.ones(n_features).reshape(1, n_features),
306            )
307
308            return (
309                self.obj.predict(self.cook_test_set(new_X, **kwargs), **kwargs)
310            )[0]
311
312        return self.obj.predict(self.cook_test_set(X, **kwargs), **kwargs)
313
314    def predict_proba(self, X, **kwargs):
315        """Predict probabilities for test data X.
316
317        Args:
318
319            X: {array-like}, shape = [n_samples, n_features]
320                Training vectors, where n_samples is the number
321                of samples and n_features is the number of features.
322
323            **kwargs: additional parameters to be passed to
324                    self.cook_test_set
325
326        Returns:
327
328            probability estimates for test data: {array-like}
329        """
330
331        if len(X.shape) == 1:
332            n_features = X.shape[0]
333            new_X = mo.rbind(
334                X.reshape(1, n_features),
335                np.ones(n_features).reshape(1, n_features),
336            )
337
338            return (
339                self.obj.predict_proba(
340                    self.cook_test_set(new_X, **kwargs), **kwargs
341                )
342            )[0]
343
344        return self.obj.predict_proba(self.cook_test_set(X, **kwargs), **kwargs)

Custom Classification model

Attributes:

obj: object
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict())

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model''s
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

col_sample: float
    percentage of covariates randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

level: float
    confidence level for prediction sets. Default is None.

pi_method: str
    method for constructing the prediction sets: 'icp', 'tcp' if level is not None. Default is 'icp'.

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    "cpu" or "gpu" or "tpu"

Examples:

Note: it's better to use the DeepClassifier or LazyDeepClassifier classes directly

import nnetsauce as ns
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_digits
from time import time

digits = load_digits()
X = digits.data
y = digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
                                                    random_state=123)

# layer 1 (base layer) ----
layer1_regr = RandomForestClassifier(n_estimators=10, random_state=123)

start = time()

layer1_regr.fit(X_train, y_train)

# Accuracy in layer 1
print(layer1_regr.score(X_test, y_test))

# layer 2 using layer 1 ----
layer2_regr = ns.CustomClassifier(obj = layer1_regr, n_hidden_features=5,
                        direct_link=True, bias=True,
                        nodes_sim='uniform', activation_name='relu',
                        n_clusters=2, seed=123)
layer2_regr.fit(X_train, y_train)

# Accuracy in layer 2
print(layer2_regr.score(X_test, y_test))

# layer 3 using layer 2 ----
layer3_regr = ns.CustomClassifier(obj = layer2_regr, n_hidden_features=10,
                        direct_link=True, bias=True, dropout=0.7,
                        nodes_sim='uniform', activation_name='relu',
                        n_clusters=2, seed=123)
layer3_regr.fit(X_train, y_train)

# Accuracy in layer 3
print(layer3_regr.score(X_test, y_test))

print(f"Elapsed {time() - start}")
def fit(self, X, y, sample_weight=None, **kwargs):
184    def fit(self, X, y, sample_weight=None, **kwargs):
185        """Fit custom model to training data (X, y).
186
187        Parameters:
188
189            X: {array-like}, shape = [n_samples, n_features]
190                Training vectors, where n_samples is the number
191                of samples and n_features is the number of features.
192
193            y: array-like, shape = [n_samples]
194                Target values.
195
196            sample_weight: array-like, shape = [n_samples]
197                Sample weights.
198
199            **kwargs: additional parameters to be passed to
200                        self.cook_training_set or self.obj.fit
201
202        Returns:
203
204            self: object
205        """
206
207        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
208        self.n_classes_ = len(np.unique(y))  # for compatibility with sklearn
209
210        if self.level is not None:
211            self.obj = PredictionSet(
212                obj=self.obj, method=self.pi_method, level=self.level
213            )
214
215        # if sample_weights, else: (must use self.row_index)
216        if sample_weight is not None:
217            self.obj.fit(
218                scaled_Z,
219                output_y,
220                sample_weight=sample_weight[self.index_row_].ravel(),
221                # **kwargs
222            )
223
224            return self
225
226        # if sample_weight is None:
227        self.obj.fit(scaled_Z, output_y)
228        self.classes_ = np.unique(y)  # for compatibility with sklearn
229        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
230
231        return self

Fit custom model to training data (X, y).

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

sample_weight: array-like, shape = [n_samples]
    Sample weights.

**kwargs: additional parameters to be passed to
            self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
284    def predict(self, X, **kwargs):
285        """Predict test data X.
286
287        Parameters:
288
289            X: {array-like}, shape = [n_samples, n_features]
290                Training vectors, where n_samples is the number
291                of samples and n_features is the number of features.
292
293            **kwargs: additional parameters to be passed to
294                    self.cook_test_set
295
296        Returns:
297
298            model predictions: {array-like}
299        """
300
301        if len(X.shape) == 1:
302            n_features = X.shape[0]
303            new_X = mo.rbind(
304                X.reshape(1, n_features),
305                np.ones(n_features).reshape(1, n_features),
306            )
307
308            return (
309                self.obj.predict(self.cook_test_set(new_X, **kwargs), **kwargs)
310            )[0]
311
312        return self.obj.predict(self.cook_test_set(X, **kwargs), **kwargs)

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
314    def predict_proba(self, X, **kwargs):
315        """Predict probabilities for test data X.
316
317        Args:
318
319            X: {array-like}, shape = [n_samples, n_features]
320                Training vectors, where n_samples is the number
321                of samples and n_features is the number of features.
322
323            **kwargs: additional parameters to be passed to
324                    self.cook_test_set
325
326        Returns:
327
328            probability estimates for test data: {array-like}
329        """
330
331        if len(X.shape) == 1:
332            n_features = X.shape[0]
333            new_X = mo.rbind(
334                X.reshape(1, n_features),
335                np.ones(n_features).reshape(1, n_features),
336            )
337
338            return (
339                self.obj.predict_proba(
340                    self.cook_test_set(new_X, **kwargs), **kwargs
341                )
342            )[0]
343
344        return self.obj.predict_proba(self.cook_test_set(X, **kwargs), **kwargs)

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class CustomRegressor(nnetsauce.custom.custom.Custom, sklearn.base.RegressorMixin):
 16class CustomRegressor(Custom, RegressorMixin):
 17    """Custom Regression model
 18
 19    This class is used to 'augment' any regression model with transformed features.
 20
 21    Parameters:
 22
 23        obj: object
 24            any object containing a method fit (obj.fit()) and a method predict
 25            (obj.predict())
 26
 27        n_hidden_features: int
 28            number of nodes in the hidden layer
 29
 30        activation_name: str
 31            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 32
 33        a: float
 34            hyperparameter for 'prelu' or 'elu' activation function
 35
 36        nodes_sim: str
 37            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 38            'uniform'
 39
 40        bias: boolean
 41            indicates if the hidden layer contains a bias term (True) or not
 42            (False)
 43
 44        dropout: float
 45            regularization parameter; (random) percentage of nodes dropped out
 46            of the training
 47
 48        direct_link: boolean
 49            indicates if the original predictors are included (True) in model's
 50            fitting or not (False)
 51
 52        n_clusters: int
 53            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 54                no clustering)
 55
 56        cluster_encode: bool
 57            defines how the variable containing clusters is treated (default is one-hot)
 58            if `False`, then labels are used, without one-hot encoding
 59
 60        type_clust: str
 61            type of clustering method: currently k-means ('kmeans') or Gaussian
 62            Mixture Model ('gmm')
 63
 64        type_scaling: a tuple of 3 strings
 65            scaling methods for inputs, hidden layer, and clustering respectively
 66            (and when relevant).
 67            Currently available: standardization ('std') or MinMax scaling ('minmax')
 68
 69        type_pi: str.
 70            type of prediction interval; currently "kde" (default).
 71            Used only in `self.predict`, for `self.replications` > 0 and `self.kernel`
 72            in ('gaussian', 'tophat'). Default is `None`.
 73
 74        replications: int.
 75            number of replications (if needed) for predictive simulation.
 76            Used only in `self.predict`, for `self.kernel` in ('gaussian',
 77            'tophat') and `self.type_pi = 'kde'`. Default is `None`.
 78
 79        kernel: str.
 80            the kernel to use for kernel density estimation (used for predictive
 81            simulation in `self.predict`, with `method='splitconformal'` and
 82            `type_pi = 'kde'`). Currently, either 'gaussian' or 'tophat'.
 83
 84        type_split: str.
 85            Type of splitting for conformal prediction. None (default), or
 86            "random" (random split of data) or "sequential" (sequential split of data)
 87
 88        col_sample: float
 89            percentage of covariates randomly chosen for training
 90
 91        row_sample: float
 92            percentage of rows chosen for training, by stratified bootstrapping
 93
 94        level: float
 95            confidence level for prediction intervals
 96
 97        pi_method: str
 98            method for prediction intervals: 'splitconformal' or 'localconformal'
 99
100        seed: int
101            reproducibility seed for nodes_sim=='uniform'
102
103        type_fit: str
104            'regression'
105
106        backend: str
107            "cpu" or "gpu" or "tpu"
108
109    Examples:
110
111    See [https://thierrymoudiki.github.io/blog/2024/03/18/python/conformal-and-bayesian-regression](https://thierrymoudiki.github.io/blog/2024/03/18/python/conformal-and-bayesian-regression)
112
113    """
114
115    # construct the object -----
116
117    def __init__(
118        self,
119        obj,
120        n_hidden_features=5,
121        activation_name="relu",
122        a=0.01,
123        nodes_sim="sobol",
124        bias=True,
125        dropout=0,
126        direct_link=True,
127        n_clusters=2,
128        cluster_encode=True,
129        type_clust="kmeans",
130        type_scaling=("std", "std", "std"),
131        type_pi=None,
132        replications=None,
133        kernel=None,
134        type_split=None,
135        col_sample=1,
136        row_sample=1,
137        level=None,
138        pi_method=None,
139        seed=123,
140        backend="cpu",
141    ):
142        super().__init__(
143            obj=obj,
144            n_hidden_features=n_hidden_features,
145            activation_name=activation_name,
146            a=a,
147            nodes_sim=nodes_sim,
148            bias=bias,
149            dropout=dropout,
150            direct_link=direct_link,
151            n_clusters=n_clusters,
152            cluster_encode=cluster_encode,
153            type_clust=type_clust,
154            type_scaling=type_scaling,
155            col_sample=col_sample,
156            row_sample=row_sample,
157            seed=seed,
158            backend=backend,
159        )
160
161        self.type_fit = "regression"
162        self.type_pi = type_pi
163        self.replications = replications
164        self.kernel = kernel
165        self.type_split = type_split
166        self.level = level
167        self.pi_method = pi_method
168
169    def fit(self, X, y, sample_weight=None, **kwargs):
170        """Fit custom model to training data (X, y).
171
172        Parameters:
173
174            X: {array-like}, shape = [n_samples, n_features]
175                Training vectors, where n_samples is the number
176                of samples and n_features is the number of features.
177
178            y: array-like, shape = [n_samples]
179                Target values.
180
181            sample_weight: array-like, shape = [n_samples]
182                Sample weights.
183
184            **kwargs: additional parameters to be passed to
185                self.cook_training_set or self.obj.fit
186
187        Returns:
188
189            self: object
190
191        """
192
193        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
194
195        if self.level is not None:
196            self.obj = PredictionInterval(
197                obj=self.obj, method=self.pi_method, level=self.level
198            )
199
200        # if sample_weights, else: (must use self.row_index)
201        if sample_weight is not None:
202            self.obj.fit(
203                scaled_Z,
204                centered_y,
205                sample_weight=sample_weight[self.index_row_].ravel(),
206                **kwargs
207            )
208
209            return self
210
211        self.obj.fit(scaled_Z, centered_y, **kwargs)
212
213        self.X_ = X
214
215        self.y_ = y
216
217        return self
218
219    def partial_fit(self, X, y, sample_weight=None, **kwargs):
220        """Partial fit custom model to training data (X, y).
221
222        Parameters:
223
224            X: {array-like}, shape = [n_samples, n_features]
225                Subset of training vectors, where n_samples is the number
226                of samples and n_features is the number of features.
227
228            y: array-like, shape = [n_samples]
229                Subset of target values.
230
231            sample_weight: array-like, shape = [n_samples]
232                Sample weights.
233
234            **kwargs: additional parameters to be passed to
235                self.cook_training_set or self.obj.fit
236
237        Returns:
238
239            self: object
240
241        """
242
243        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
244
245        # if sample_weights, else: (must use self.row_index)
246        if sample_weight is not None:
247            try:
248                self.obj.partial_fit(
249                    scaled_Z,
250                    centered_y,
251                    sample_weight=sample_weight[self.index_row_].ravel(),
252                    **kwargs
253                )
254            except:
255                raise NotImplementedError
256
257            return self
258
259        try:
260            self.obj.partial_fit(scaled_Z, centered_y, **kwargs)
261        except:
262            raise NotImplementedError
263
264        self.X_ = X
265
266        self.y_ = y
267
268        return self
269
270    def predict(self, X, level=95, method=None, **kwargs):
271        """Predict test data X.
272
273        Parameters:
274
275            X: {array-like}, shape = [n_samples, n_features]
276                Training vectors, where n_samples is the number
277                of samples and n_features is the number of features.
278
279            level: int
280                Level of confidence (default = 95)
281
282            method: str
283                `None`, or 'splitconformal', 'localconformal'
284                prediction (if you specify `return_pi = True`)
285
286            **kwargs: additional parameters
287                    `return_pi = True` for conformal prediction,
288                    with `method` in ('splitconformal', 'localconformal')
289                    or `return_std = True` for `self.obj` in
290                    (`sklearn.linear_model.BayesianRidge`,
291                    `sklearn.linear_model.ARDRegressor`,
292                    `sklearn.gaussian_process.GaussianProcessRegressor`)`
293
294        Returns:
295
296            model predictions:
297                an array if uncertainty quantification is not requested,
298                  or a tuple if with prediction intervals and simulations
299                  if `return_std = True` (mean, standard deviation,
300                  lower and upper prediction interval) or `return_pi = True`
301                  ()
302
303        """
304
305        if "return_std" in kwargs:
306
307            alpha = 100 - level
308            pi_multiplier = norm.ppf(1 - alpha / 200)
309
310            if len(X.shape) == 1:
311
312                n_features = X.shape[0]
313                new_X = mo.rbind(
314                    X.reshape(1, n_features),
315                    np.ones(n_features).reshape(1, n_features),
316                )
317
318                mean_, std_ = self.obj.predict(
319                    self.cook_test_set(new_X, **kwargs), return_std=True
320                )[0]
321
322                preds = self.y_mean_ + mean_
323                lower = self.y_mean_ + (mean_ - pi_multiplier * std_)
324                upper = self.y_mean_ + (mean_ + pi_multiplier * std_)
325
326                return preds, std_, lower, upper
327
328            # len(X.shape) > 1
329            mean_, std_ = self.obj.predict(
330                self.cook_test_set(X, **kwargs), return_std=True
331            )
332
333            preds = self.y_mean_ + mean_
334            lower = self.y_mean_ + (mean_ - pi_multiplier * std_)
335            upper = self.y_mean_ + (mean_ + pi_multiplier * std_)
336
337            return preds, std_, lower, upper
338
339        if "return_pi" in kwargs:
340            assert method in (
341                "splitconformal",
342                "localconformal",
343            ), "method must be in ('splitconformal', 'localconformal')"
344            self.pi = PredictionInterval(
345                obj=self,
346                method=method,
347                level=level,
348                type_pi=self.type_pi,
349                replications=self.replications,
350                kernel=self.kernel,
351            )
352            self.pi.fit(self.X_, self.y_)
353            self.X_ = None
354            self.y_ = None
355            preds = self.pi.predict(X, return_pi=True)
356            return preds
357
358        # "return_std" not in kwargs
359        if len(X.shape) == 1:
360
361            n_features = X.shape[0]
362            new_X = mo.rbind(
363                X.reshape(1, n_features),
364                np.ones(n_features).reshape(1, n_features),
365            )
366
367            return (
368                self.y_mean_
369                + self.obj.predict(
370                    self.cook_test_set(new_X, **kwargs), **kwargs
371                )
372            )[0]
373
374        # len(X.shape) > 1
375        return self.y_mean_ + self.obj.predict(
376            self.cook_test_set(X, **kwargs), **kwargs
377        )

Custom Regression model

This class is used to 'augment' any regression model with transformed features.

Parameters:

obj: object
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict())

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

type_pi: str.
    type of prediction interval; currently "kde" (default).
    Used only in `self.predict`, for `self.replications` > 0 and `self.kernel`
    in ('gaussian', 'tophat'). Default is `None`.

replications: int.
    number of replications (if needed) for predictive simulation.
    Used only in `self.predict`, for `self.kernel` in ('gaussian',
    'tophat') and `self.type_pi = 'kde'`. Default is `None`.

kernel: str.
    the kernel to use for kernel density estimation (used for predictive
    simulation in `self.predict`, with `method='splitconformal'` and
    `type_pi = 'kde'`). Currently, either 'gaussian' or 'tophat'.

type_split: str.
    Type of splitting for conformal prediction. None (default), or
    "random" (random split of data) or "sequential" (sequential split of data)

col_sample: float
    percentage of covariates randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

level: float
    confidence level for prediction intervals

pi_method: str
    method for prediction intervals: 'splitconformal' or 'localconformal'

seed: int
    reproducibility seed for nodes_sim=='uniform'

type_fit: str
    'regression'

backend: str
    "cpu" or "gpu" or "tpu"

Examples:

See https://thierrymoudiki.github.io/blog/2024/03/18/python/conformal-and-bayesian-regression

def fit(self, X, y, sample_weight=None, **kwargs):
169    def fit(self, X, y, sample_weight=None, **kwargs):
170        """Fit custom model to training data (X, y).
171
172        Parameters:
173
174            X: {array-like}, shape = [n_samples, n_features]
175                Training vectors, where n_samples is the number
176                of samples and n_features is the number of features.
177
178            y: array-like, shape = [n_samples]
179                Target values.
180
181            sample_weight: array-like, shape = [n_samples]
182                Sample weights.
183
184            **kwargs: additional parameters to be passed to
185                self.cook_training_set or self.obj.fit
186
187        Returns:
188
189            self: object
190
191        """
192
193        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
194
195        if self.level is not None:
196            self.obj = PredictionInterval(
197                obj=self.obj, method=self.pi_method, level=self.level
198            )
199
200        # if sample_weights, else: (must use self.row_index)
201        if sample_weight is not None:
202            self.obj.fit(
203                scaled_Z,
204                centered_y,
205                sample_weight=sample_weight[self.index_row_].ravel(),
206                **kwargs
207            )
208
209            return self
210
211        self.obj.fit(scaled_Z, centered_y, **kwargs)
212
213        self.X_ = X
214
215        self.y_ = y
216
217        return self

Fit custom model to training data (X, y).

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

sample_weight: array-like, shape = [n_samples]
    Sample weights.

**kwargs: additional parameters to be passed to
    self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, level=95, method=None, **kwargs):
270    def predict(self, X, level=95, method=None, **kwargs):
271        """Predict test data X.
272
273        Parameters:
274
275            X: {array-like}, shape = [n_samples, n_features]
276                Training vectors, where n_samples is the number
277                of samples and n_features is the number of features.
278
279            level: int
280                Level of confidence (default = 95)
281
282            method: str
283                `None`, or 'splitconformal', 'localconformal'
284                prediction (if you specify `return_pi = True`)
285
286            **kwargs: additional parameters
287                    `return_pi = True` for conformal prediction,
288                    with `method` in ('splitconformal', 'localconformal')
289                    or `return_std = True` for `self.obj` in
290                    (`sklearn.linear_model.BayesianRidge`,
291                    `sklearn.linear_model.ARDRegressor`,
292                    `sklearn.gaussian_process.GaussianProcessRegressor`)`
293
294        Returns:
295
296            model predictions:
297                an array if uncertainty quantification is not requested,
298                  or a tuple if with prediction intervals and simulations
299                  if `return_std = True` (mean, standard deviation,
300                  lower and upper prediction interval) or `return_pi = True`
301                  ()
302
303        """
304
305        if "return_std" in kwargs:
306
307            alpha = 100 - level
308            pi_multiplier = norm.ppf(1 - alpha / 200)
309
310            if len(X.shape) == 1:
311
312                n_features = X.shape[0]
313                new_X = mo.rbind(
314                    X.reshape(1, n_features),
315                    np.ones(n_features).reshape(1, n_features),
316                )
317
318                mean_, std_ = self.obj.predict(
319                    self.cook_test_set(new_X, **kwargs), return_std=True
320                )[0]
321
322                preds = self.y_mean_ + mean_
323                lower = self.y_mean_ + (mean_ - pi_multiplier * std_)
324                upper = self.y_mean_ + (mean_ + pi_multiplier * std_)
325
326                return preds, std_, lower, upper
327
328            # len(X.shape) > 1
329            mean_, std_ = self.obj.predict(
330                self.cook_test_set(X, **kwargs), return_std=True
331            )
332
333            preds = self.y_mean_ + mean_
334            lower = self.y_mean_ + (mean_ - pi_multiplier * std_)
335            upper = self.y_mean_ + (mean_ + pi_multiplier * std_)
336
337            return preds, std_, lower, upper
338
339        if "return_pi" in kwargs:
340            assert method in (
341                "splitconformal",
342                "localconformal",
343            ), "method must be in ('splitconformal', 'localconformal')"
344            self.pi = PredictionInterval(
345                obj=self,
346                method=method,
347                level=level,
348                type_pi=self.type_pi,
349                replications=self.replications,
350                kernel=self.kernel,
351            )
352            self.pi.fit(self.X_, self.y_)
353            self.X_ = None
354            self.y_ = None
355            preds = self.pi.predict(X, return_pi=True)
356            return preds
357
358        # "return_std" not in kwargs
359        if len(X.shape) == 1:
360
361            n_features = X.shape[0]
362            new_X = mo.rbind(
363                X.reshape(1, n_features),
364                np.ones(n_features).reshape(1, n_features),
365            )
366
367            return (
368                self.y_mean_
369                + self.obj.predict(
370                    self.cook_test_set(new_X, **kwargs), **kwargs
371                )
372            )[0]
373
374        # len(X.shape) > 1
375        return self.y_mean_ + self.obj.predict(
376            self.cook_test_set(X, **kwargs), **kwargs
377        )

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

level: int
    Level of confidence (default = 95)

method: str
    `None`, or 'splitconformal', 'localconformal'
    prediction (if you specify `return_pi = True`)

**kwargs: additional parameters
        `return_pi = True` for conformal prediction,
        with `method` in ('splitconformal', 'localconformal')
        or `return_std = True` for `self.obj` in
        (`sklearn.linear_model.BayesianRidge`,
        `sklearn.linear_model.ARDRegressor`,
        `sklearn.gaussian_process.GaussianProcessRegressor`)`

Returns:

model predictions:
    an array if uncertainty quantification is not requested,
      or a tuple if with prediction intervals and simulations
      if `return_std = True` (mean, standard deviation,
      lower and upper prediction interval) or `return_pi = True`
      ()
class DeepClassifier(nnetsauce.CustomClassifier, sklearn.base.ClassifierMixin):
 26class DeepClassifier(CustomClassifier, ClassifierMixin):
 27    """
 28    Deep Classifier
 29
 30    Parameters:
 31
 32        obj: an object
 33            A base learner, see also https://www.researchgate.net/publication/380701207_Deep_Quasi-Randomized_neural_Networks_for_classification
 34
 35        n_layers: int (default=3)
 36            Number of layers. `n_layers = 1` is a simple `CustomClassifier`
 37
 38        verbose : int, optional (default=0)
 39            Monitor progress when fitting.
 40
 41        All the other parameters are nnetsauce `CustomClassifier`'s
 42
 43    Examples:
 44
 45        ```python
 46        import nnetsauce as ns
 47        from sklearn.datasets import load_breast_cancer
 48        from sklearn.model_selection import train_test_split
 49        from sklearn.linear_model import LogisticRegressionCV
 50        data = load_breast_cancer()
 51        X = data.data
 52        y= data.target
 53        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=123)
 54        obj = LogisticRegressionCV()
 55        clf = ns.DeepClassifier(obj)
 56        clf.fit(X_train, y_train)
 57        print(clf.score(clf.predict(X_test), y_test))
 58        ```
 59    """
 60
 61    def __init__(
 62        self,
 63        obj,
 64        # Defining depth
 65        n_layers=3,
 66        verbose=0,
 67        # CustomClassifier attributes
 68        n_hidden_features=5,
 69        activation_name="relu",
 70        a=0.01,
 71        nodes_sim="sobol",
 72        bias=True,
 73        dropout=0,
 74        direct_link=True,
 75        n_clusters=2,
 76        cluster_encode=True,
 77        type_clust="kmeans",
 78        type_scaling=("std", "std", "std"),
 79        col_sample=1,
 80        row_sample=1,
 81        level=None,
 82        pi_method="icp",
 83        seed=123,
 84        backend="cpu",
 85    ):
 86        super().__init__(
 87            obj=obj,
 88            n_hidden_features=n_hidden_features,
 89            activation_name=activation_name,
 90            a=a,
 91            nodes_sim=nodes_sim,
 92            bias=bias,
 93            dropout=dropout,
 94            direct_link=direct_link,
 95            n_clusters=n_clusters,
 96            cluster_encode=cluster_encode,
 97            type_clust=type_clust,
 98            type_scaling=type_scaling,
 99            col_sample=col_sample,
100            row_sample=row_sample,
101            level=level,
102            pi_method=pi_method,
103            seed=seed,
104            backend=backend,
105        )
106
107        assert n_layers >= 1, "must have n_layers >= 1"
108
109        self.stacked_obj = obj
110        self.verbose = verbose
111        self.n_layers = n_layers
112
113    def fit(self, X, y, sample_weight=None, **kwargs):
114        """Fit Classification algorithms to X and y.
115        Parameters
116        ----------
117        X : array-like,
118            Training vectors, where rows is the number of samples
119            and columns is the number of features.
120        y : array-like,
121            Training vectors, where rows is the number of samples
122            and columns is the number of features.
123        sample_weight: array-like, shape = [n_samples]
124                Sample weights.
125        Returns
126        -------
127        A fitted object
128        """
129
130        if isinstance(X, np.ndarray):
131            X = pd.DataFrame(X)
132
133        # init layer
134        self.stacked_obj = CustomClassifier(
135            obj=self.stacked_obj,
136            n_hidden_features=self.n_hidden_features,
137            activation_name=self.activation_name,
138            a=self.a,
139            nodes_sim=self.nodes_sim,
140            bias=self.bias,
141            dropout=self.dropout,
142            direct_link=self.direct_link,
143            n_clusters=self.n_clusters,
144            cluster_encode=self.cluster_encode,
145            type_clust=self.type_clust,
146            type_scaling=self.type_scaling,
147            col_sample=self.col_sample,
148            row_sample=self.row_sample,
149            seed=self.seed,
150            backend=self.backend,
151        )
152
153        if self.verbose > 0:
154            iterator = tqdm(range(self.n_layers - 1))
155        else:
156            iterator = range(self.n_layers - 1)
157
158        for _ in iterator:
159            self.stacked_obj = deepcopy(
160                CustomClassifier(
161                    obj=self.stacked_obj,
162                    n_hidden_features=self.n_hidden_features,
163                    activation_name=self.activation_name,
164                    a=self.a,
165                    nodes_sim=self.nodes_sim,
166                    bias=self.bias,
167                    dropout=self.dropout,
168                    direct_link=self.direct_link,
169                    n_clusters=self.n_clusters,
170                    cluster_encode=self.cluster_encode,
171                    type_clust=self.type_clust,
172                    type_scaling=self.type_scaling,
173                    col_sample=self.col_sample,
174                    row_sample=self.row_sample,
175                    seed=self.seed,
176                    backend=self.backend,
177                )
178            )
179
180        if self.level is not None:
181            self.stacked_obj = PredictionSet(
182                obj=self.stacked_obj, method=self.pi_method, level=self.level
183            )
184
185        try:
186            self.stacked_obj.fit(X, y, sample_weight=sample_weight, **kwargs)
187        except Exception as e:
188            self.stacked_obj.fit(X, y)
189
190        self.obj = deepcopy(self.stacked_obj)
191
192        return self.obj
193
194    def predict(self, X):
195        return self.obj.predict(X)
196
197    def predict_proba(self, X):
198        return self.obj.predict_proba(X)
199
200    def score(self, X, y, scoring=None):
201        return self.obj.score(X, y, scoring)
202
203    def cross_val_optim(
204        self,
205        X_train,
206        y_train,
207        X_test=None,
208        y_test=None,
209        scoring="accuracy",
210        surrogate_obj=None,
211        cv=5,
212        n_jobs=None,
213        n_init=10,
214        n_iter=190,
215        abs_tol=1e-3,
216        verbose=2,
217        seed=123,
218        **kwargs,
219    ):
220        """Cross-validation function and hyperparameters' search
221
222        Parameters:
223
224            X_train: array-like,
225                Training vectors, where rows is the number of samples
226                and columns is the number of features.
227
228            y_train: array-like,
229                Training vectors, where rows is the number of samples
230                and columns is the number of features.
231
232            X_test: array-like,
233                Testing vectors, where rows is the number of samples
234                and columns is the number of features.
235
236            y_test: array-like,
237                Testing vectors, where rows is the number of samples
238                and columns is the number of features.
239
240            scoring: str
241                scoring metric; see https://scikit-learn.org/stable/modules/model_evaluation.html#the-scoring-parameter-defining-model-evaluation-rules
242
243            surrogate_obj: an object;
244                An ML model for estimating the uncertainty around the objective function
245
246            cv: int;
247                number of cross-validation folds
248
249            n_jobs: int;
250                number of jobs for parallel execution
251
252            n_init: an integer;
253                number of points in the initial setting, when `x_init` and `y_init` are not provided
254
255            n_iter: an integer;
256                number of iterations of the minimization algorithm
257
258            abs_tol: a float;
259                tolerance for convergence of the optimizer (early stopping based on acquisition function)
260
261            verbose: int
262                controls verbosity
263
264            seed: int
265                reproducibility seed
266
267            **kwargs: dict
268                additional parameters to be passed to the estimator
269
270        Examples:
271
272            ```python
273            ```
274        """
275
276        num_to_activation_name = {1: "relu", 2: "sigmoid", 3: "tanh"}
277        num_to_nodes_sim = {1: "sobol", 2: "uniform", 3: "hammersley"}
278        num_to_type_clust = {1: "kmeans", 2: "gmm"}
279
280        def deepclassifier_cv(
281            X_train,
282            y_train,
283            # Defining depth
284            n_layers=3,
285            # CustomClassifier attributes
286            n_hidden_features=5,
287            activation_name="relu",
288            nodes_sim="sobol",
289            dropout=0,
290            n_clusters=2,
291            type_clust="kmeans",
292            cv=5,
293            n_jobs=None,
294            scoring="accuracy",
295            seed=123,
296        ):
297            self.set_params(
298                **{
299                    "n_layers": n_layers,
300                    # CustomClassifier attributes
301                    "n_hidden_features": n_hidden_features,
302                    "activation_name": activation_name,
303                    "nodes_sim": nodes_sim,
304                    "dropout": dropout,
305                    "n_clusters": n_clusters,
306                    "type_clust": type_clust,
307                    **kwargs,
308                }
309            )
310            return -cross_val_score(
311                estimator=self,
312                X=X_train,
313                y=y_train,
314                scoring=scoring,
315                cv=cv,
316                n_jobs=n_jobs,
317                verbose=0,
318            ).mean()
319
320        # objective function for hyperparams tuning
321        def crossval_objective(xx):
322            return deepclassifier_cv(
323                X_train=X_train,
324                y_train=y_train,
325                # Defining depth
326                n_layers=int(np.ceil(xx[0])),
327                # CustomClassifier attributes
328                n_hidden_features=int(np.ceil(xx[1])),
329                activation_name=num_to_activation_name[np.ceil(xx[2])],
330                nodes_sim=num_to_nodes_sim[int(np.ceil(xx[3]))],
331                dropout=xx[4],
332                n_clusters=int(np.ceil(xx[5])),
333                type_clust=num_to_type_clust[int(np.ceil(xx[6]))],
334                cv=cv,
335                n_jobs=n_jobs,
336                scoring=scoring,
337                seed=seed,
338            )
339
340        if surrogate_obj is None:
341            gp_opt = gp.GPOpt(
342                objective_func=crossval_objective,
343                lower_bound=np.array([0, 3, 0, 0, 0.0, 0, 0]),
344                upper_bound=np.array([5, 100, 3, 3, 0.4, 5, 2]),
345                params_names=[
346                    "n_layers",
347                    # CustomClassifier attributes
348                    "n_hidden_features",
349                    "activation_name",
350                    "nodes_sim",
351                    "dropout",
352                    "n_clusters",
353                    "type_clust",
354                ],
355                method="bayesian",
356                n_init=n_init,
357                n_iter=n_iter,
358                seed=seed,
359            )
360        else:
361            gp_opt = gp.GPOpt(
362                objective_func=crossval_objective,
363                lower_bound=np.array([0, 3, 0, 0, 0.0, 0, 0]),
364                upper_bound=np.array([5, 100, 3, 3, 0.4, 5, 2]),
365                params_names=[
366                    "n_layers",
367                    # CustomClassifier attributes
368                    "n_hidden_features",
369                    "activation_name",
370                    "nodes_sim",
371                    "dropout",
372                    "n_clusters",
373                    "type_clust",
374                ],
375                acquisition="ucb",
376                method="splitconformal",
377                surrogate_obj=ns.PredictionInterval(
378                    obj=surrogate_obj, method="splitconformal"
379                ),
380                n_init=n_init,
381                n_iter=n_iter,
382                seed=seed,
383            )
384
385        res = gp_opt.optimize(verbose=verbose, abs_tol=abs_tol)
386        res.best_params["n_layers"] = int(np.ceil(res.best_params["n_layers"]))
387        res.best_params["n_hidden_features"] = int(
388            np.ceil(res.best_params["n_hidden_features"])
389        )
390        res.best_params["activation_name"] = num_to_activation_name[
391            np.ceil(res.best_params["activation_name"])
392        ]
393        res.best_params["nodes_sim"] = num_to_nodes_sim[
394            int(np.ceil(res.best_params["nodes_sim"]))
395        ]
396        res.best_params["dropout"] = res.best_params["dropout"]
397        res.best_params["n_clusters"] = int(
398            np.ceil(res.best_params["n_clusters"])
399        )
400        res.best_params["type_clust"] = num_to_type_clust[
401            int(np.ceil(res.best_params["type_clust"]))
402        ]
403
404        # out-of-sample error
405        if X_test is not None and y_test is not None:
406            self.set_params(**res.best_params, verbose=0, seed=seed)
407            preds = self.fit(X_train, y_train).predict(X_test)
408            # check error on y_test
409            oos_err = getattr(metrics, scoring + "_score")(
410                y_true=y_test, y_pred=preds
411            )
412            result = namedtuple("result", res._fields + ("test_" + scoring,))
413            return result(*res, oos_err)
414        else:
415            return res
416
417    def lazy_cross_val_optim(
418        self,
419        X_train,
420        y_train,
421        X_test=None,
422        y_test=None,
423        scoring="accuracy",
424        surrogate_objs=None,
425        customize=False,
426        cv=5,
427        n_jobs=None,
428        n_init=10,
429        n_iter=190,
430        abs_tol=1e-3,
431        verbose=1,
432        seed=123,
433    ):
434        """Automated Cross-validation function and hyperparameters' search using multiple surrogates
435
436        Parameters:
437
438            X_train: array-like,
439                Training vectors, where rows is the number of samples
440                and columns is the number of features.
441
442            y_train: array-like,
443                Training vectors, where rows is the number of samples
444                and columns is the number of features.
445
446            X_test: array-like,
447                Testing vectors, where rows is the number of samples
448                and columns is the number of features.
449
450            y_test: array-like,
451                Testing vectors, where rows is the number of samples
452                and columns is the number of features.
453
454            scoring: str
455                scoring metric; see https://scikit-learn.org/stable/modules/model_evaluation.html#the-scoring-parameter-defining-model-evaluation-rules
456
457            surrogate_objs: object names as a list of strings;
458                ML models for estimating the uncertainty around the objective function
459
460            customize: boolean
461                if True, the surrogate is transformed into a quasi-randomized network (default is False)
462
463            cv: int;
464                number of cross-validation folds
465
466            n_jobs: int;
467                number of jobs for parallel execution
468
469            n_init: an integer;
470                number of points in the initial setting, when `x_init` and `y_init` are not provided
471
472            n_iter: an integer;
473                number of iterations of the minimization algorithm
474
475            abs_tol: a float;
476                tolerance for convergence of the optimizer (early stopping based on acquisition function)
477
478            verbose: int
479                controls verbosity
480
481            seed: int
482                reproducibility seed
483
484        Examples:
485
486            ```python
487            ```
488        """
489
490        removed_regressors = [
491            "TheilSenRegressor",
492            "ARDRegression",
493            "CCA",
494            "GaussianProcessRegressor",
495            "GradientBoostingRegressor",
496            "HistGradientBoostingRegressor",
497            "IsotonicRegression",
498            "MultiOutputRegressor",
499            "MultiTaskElasticNet",
500            "MultiTaskElasticNetCV",
501            "MultiTaskLasso",
502            "MultiTaskLassoCV",
503            "OrthogonalMatchingPursuit",
504            "OrthogonalMatchingPursuitCV",
505            "PLSCanonical",
506            "PLSRegression",
507            "RadiusNeighborsRegressor",
508            "RegressorChain",
509            "StackingRegressor",
510            "VotingRegressor",
511        ]
512
513        results = []
514
515        for est in all_estimators():
516
517            if surrogate_objs is None:
518
519                if issubclass(est[1], RegressorMixin) and (
520                    est[0] not in removed_regressors
521                ):
522                    try:
523                        if customize == True:
524                            print(f"\n surrogate: CustomClassifier({est[0]})")
525                            surr_obj = ns.CustomClassifier(obj=est[1]())
526                        else:
527                            print(f"\n surrogate: {est[0]}")
528                            surr_obj = est[1]()
529                        res = self.cross_val_optim(
530                            X_train=X_train,
531                            y_train=y_train,
532                            X_test=X_test,
533                            y_test=y_test,
534                            surrogate_obj=surr_obj,
535                            cv=cv,
536                            n_jobs=n_jobs,
537                            scoring=scoring,
538                            n_init=n_init,
539                            n_iter=n_iter,
540                            abs_tol=abs_tol,
541                            verbose=verbose,
542                            seed=seed,
543                        )
544                        print(f"\n result: {res}")
545                        if customize == True:
546                            results.append((f"CustomClassifier({est[0]})", res))
547                        else:
548                            results.append((est[0], res))
549                    except:
550                        pass
551
552            else:
553
554                if (
555                    issubclass(est[1], RegressorMixin)
556                    and (est[0] not in removed_regressors)
557                    and est[0] in surrogate_objs
558                ):
559                    try:
560                        if customize == True:
561                            print(f"\n surrogate: CustomClassifier({est[0]})")
562                            surr_obj = ns.CustomClassifier(obj=est[1]())
563                        else:
564                            print(f"\n surrogate: {est[0]}")
565                            surr_obj = est[1]()
566                        res = self.cross_val_optim(
567                            X_train=X_train,
568                            y_train=y_train,
569                            X_test=X_test,
570                            y_test=y_test,
571                            surrogate_obj=surr_obj,
572                            cv=cv,
573                            n_jobs=n_jobs,
574                            scoring=scoring,
575                            n_init=n_init,
576                            n_iter=n_iter,
577                            abs_tol=abs_tol,
578                            verbose=verbose,
579                            seed=seed,
580                        )
581                        print(f"\n result: {res}")
582                        if customize == True:
583                            results.append((f"CustomClassifier({est[0]})", res))
584                        else:
585                            results.append((est[0], res))
586                    except:
587                        pass
588
589        return results

Deep Classifier

Parameters:

obj: an object
    A base learner, see also https://www.researchgate.net/publication/380701207_Deep_Quasi-Randomized_neural_Networks_for_classification

n_layers: int (default=3)
    Number of layers. `n_layers = 1` is a simple `CustomClassifier`

verbose : int, optional (default=0)
    Monitor progress when fitting.

All the other parameters are nnetsauce `CustomClassifier`'s

Examples:

import nnetsauce as ns
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegressionCV
    data = load_breast_cancer()
    X = data.data
    y= data.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=123)
    obj = LogisticRegressionCV()
    clf = ns.DeepClassifier(obj)
    clf.fit(X_train, y_train)
    print(clf.score(clf.predict(X_test), y_test))
    

def fit(self, X, y, sample_weight=None, **kwargs):
113    def fit(self, X, y, sample_weight=None, **kwargs):
114        """Fit Classification algorithms to X and y.
115        Parameters
116        ----------
117        X : array-like,
118            Training vectors, where rows is the number of samples
119            and columns is the number of features.
120        y : array-like,
121            Training vectors, where rows is the number of samples
122            and columns is the number of features.
123        sample_weight: array-like, shape = [n_samples]
124                Sample weights.
125        Returns
126        -------
127        A fitted object
128        """
129
130        if isinstance(X, np.ndarray):
131            X = pd.DataFrame(X)
132
133        # init layer
134        self.stacked_obj = CustomClassifier(
135            obj=self.stacked_obj,
136            n_hidden_features=self.n_hidden_features,
137            activation_name=self.activation_name,
138            a=self.a,
139            nodes_sim=self.nodes_sim,
140            bias=self.bias,
141            dropout=self.dropout,
142            direct_link=self.direct_link,
143            n_clusters=self.n_clusters,
144            cluster_encode=self.cluster_encode,
145            type_clust=self.type_clust,
146            type_scaling=self.type_scaling,
147            col_sample=self.col_sample,
148            row_sample=self.row_sample,
149            seed=self.seed,
150            backend=self.backend,
151        )
152
153        if self.verbose > 0:
154            iterator = tqdm(range(self.n_layers - 1))
155        else:
156            iterator = range(self.n_layers - 1)
157
158        for _ in iterator:
159            self.stacked_obj = deepcopy(
160                CustomClassifier(
161                    obj=self.stacked_obj,
162                    n_hidden_features=self.n_hidden_features,
163                    activation_name=self.activation_name,
164                    a=self.a,
165                    nodes_sim=self.nodes_sim,
166                    bias=self.bias,
167                    dropout=self.dropout,
168                    direct_link=self.direct_link,
169                    n_clusters=self.n_clusters,
170                    cluster_encode=self.cluster_encode,
171                    type_clust=self.type_clust,
172                    type_scaling=self.type_scaling,
173                    col_sample=self.col_sample,
174                    row_sample=self.row_sample,
175                    seed=self.seed,
176                    backend=self.backend,
177                )
178            )
179
180        if self.level is not None:
181            self.stacked_obj = PredictionSet(
182                obj=self.stacked_obj, method=self.pi_method, level=self.level
183            )
184
185        try:
186            self.stacked_obj.fit(X, y, sample_weight=sample_weight, **kwargs)
187        except Exception as e:
188            self.stacked_obj.fit(X, y)
189
190        self.obj = deepcopy(self.stacked_obj)
191
192        return self.obj

Fit Classification algorithms to X and y.

Parameters

X : array-like, Training vectors, where rows is the number of samples and columns is the number of features. y : array-like, Training vectors, where rows is the number of samples and columns is the number of features. sample_weight: array-like, shape = [n_samples] Sample weights.

Returns

A fitted object

def predict(self, X):
194    def predict(self, X):
195        return self.obj.predict(X)

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X):
197    def predict_proba(self, X):
198        return self.obj.predict_proba(X)

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
def score(self, X, y, scoring=None):
200    def score(self, X, y, scoring=None):
201        return self.obj.score(X, y, scoring)

Score the model on test set features X and response y.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

y: array-like, shape = [n_samples]
    Target values

scoring: str
    must be in ('explained_variance', 'neg_mean_absolute_error',
                'neg_mean_squared_error', 'neg_mean_squared_log_error',
                'neg_median_absolute_error', 'r2')

**kwargs: additional parameters to be passed to scoring functions

Returns:

model scores: {array-like}

class DeepRegressor(nnetsauce.CustomRegressor, sklearn.base.RegressorMixin):
 13class DeepRegressor(CustomRegressor, RegressorMixin):
 14    """
 15    Deep Regressor
 16
 17    Parameters:
 18
 19        obj: an object
 20            A base learner, see also https://www.researchgate.net/publication/380701207_Deep_Quasi-Randomized_neural_Networks_for_classification
 21
 22        verbose : int, optional (default=0)
 23            Monitor progress when fitting.
 24
 25        n_layers: int (default=3)
 26            Number of layers. `n_layers = 1` is a simple `CustomRegressor`
 27
 28        All the other parameters are nnetsauce `CustomRegressor`'s
 29
 30    Examples:
 31
 32        ```python
 33        import nnetsauce as ns
 34        from sklearn.datasets import load_diabetes
 35        from sklearn.model_selection import train_test_split
 36        from sklearn.linear_model import RidgeCV
 37        data = load_diabetes()
 38        X = data.data
 39        y= data.target
 40        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=123)
 41        obj = RidgeCV()
 42        clf = ns.DeepRegressor(obj)
 43        clf.fit(X_train, y_train)
 44        print(clf.score(clf.predict(X_test), y_test))
 45        ```
 46
 47    """
 48
 49    def __init__(
 50        self,
 51        obj,
 52        # Defining depth
 53        n_layers=3,
 54        verbose=0,
 55        # CustomRegressor attributes
 56        n_hidden_features=5,
 57        activation_name="relu",
 58        a=0.01,
 59        nodes_sim="sobol",
 60        bias=True,
 61        dropout=0,
 62        direct_link=True,
 63        n_clusters=2,
 64        cluster_encode=True,
 65        type_clust="kmeans",
 66        type_scaling=("std", "std", "std"),
 67        col_sample=1,
 68        row_sample=1,
 69        level=None,
 70        pi_method="splitconformal",
 71        seed=123,
 72        backend="cpu",
 73    ):
 74        super().__init__(
 75            obj=obj,
 76            n_hidden_features=n_hidden_features,
 77            activation_name=activation_name,
 78            a=a,
 79            nodes_sim=nodes_sim,
 80            bias=bias,
 81            dropout=dropout,
 82            direct_link=direct_link,
 83            n_clusters=n_clusters,
 84            cluster_encode=cluster_encode,
 85            type_clust=type_clust,
 86            type_scaling=type_scaling,
 87            col_sample=col_sample,
 88            row_sample=row_sample,
 89            level=level,
 90            pi_method=pi_method,
 91            seed=seed,
 92            backend=backend,
 93        )
 94
 95        assert n_layers >= 1, "must have n_layers >= 1"
 96
 97        self.stacked_obj = obj
 98        self.verbose = verbose
 99        self.n_layers = n_layers
100        self.level = level
101        self.pi_method = pi_method
102
103    def fit(self, X, y, sample_weight=None, **kwargs):
104        """Fit Regression algorithms to X and y.
105        Parameters
106        ----------
107        X : array-like,
108            Training vectors, where rows is the number of samples
109            and columns is the number of features.
110        y : array-like,
111            Training vectors, where rows is the number of samples
112            and columns is the number of features.
113        sample_weight: array-like, shape = [n_samples]
114                Sample weights.
115        Returns
116        -------
117        A fitted object
118        """
119
120        if isinstance(X, np.ndarray):
121            X = pd.DataFrame(X)
122
123        # init layer
124        self.stacked_obj = CustomRegressor(
125            obj=self.stacked_obj,
126            n_hidden_features=self.n_hidden_features,
127            activation_name=self.activation_name,
128            a=self.a,
129            nodes_sim=self.nodes_sim,
130            bias=self.bias,
131            dropout=self.dropout,
132            direct_link=self.direct_link,
133            n_clusters=self.n_clusters,
134            cluster_encode=self.cluster_encode,
135            type_clust=self.type_clust,
136            type_scaling=self.type_scaling,
137            col_sample=self.col_sample,
138            row_sample=self.row_sample,
139            seed=self.seed,
140            backend=self.backend,
141        )
142
143        if self.verbose > 0:
144            iterator = tqdm(range(self.n_layers - 1))
145        else:
146            iterator = range(self.n_layers - 1)
147
148        for _ in iterator:
149            self.stacked_obj = deepcopy(
150                CustomRegressor(
151                    obj=self.stacked_obj,
152                    n_hidden_features=self.n_hidden_features,
153                    activation_name=self.activation_name,
154                    a=self.a,
155                    nodes_sim=self.nodes_sim,
156                    bias=self.bias,
157                    dropout=self.dropout,
158                    direct_link=self.direct_link,
159                    n_clusters=self.n_clusters,
160                    cluster_encode=self.cluster_encode,
161                    type_clust=self.type_clust,
162                    type_scaling=self.type_scaling,
163                    col_sample=self.col_sample,
164                    row_sample=self.row_sample,
165                    seed=self.seed,
166                    backend=self.backend,
167                )
168            )
169
170        if self.level is not None:
171            self.stacked_obj = PredictionInterval(
172                obj=self.stacked_obj, method=self.pi_method, level=self.level
173            )
174
175        try:
176            self.stacked_obj.fit(X, y, sample_weight=sample_weight, **kwargs)
177        except Exception as e:
178            self.stacked_obj.fit(X, y)
179
180        self.obj = deepcopy(self.stacked_obj)
181
182        return self.obj
183
184    def predict(self, X, **kwargs):
185        if self.level is not None:
186            return self.obj.predict(X, return_pi=True)
187        return self.obj.predict(X, **kwargs)
188
189    def score(self, X, y, scoring=None):
190        return self.obj.score(X, y, scoring)

Deep Regressor

Parameters:

obj: an object
    A base learner, see also https://www.researchgate.net/publication/380701207_Deep_Quasi-Randomized_neural_Networks_for_classification

verbose : int, optional (default=0)
    Monitor progress when fitting.

n_layers: int (default=3)
    Number of layers. `n_layers = 1` is a simple `CustomRegressor`

All the other parameters are nnetsauce `CustomRegressor`'s

Examples:

import nnetsauce as ns
    from sklearn.datasets import load_diabetes
    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import RidgeCV
    data = load_diabetes()
    X = data.data
    y= data.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=123)
    obj = RidgeCV()
    clf = ns.DeepRegressor(obj)
    clf.fit(X_train, y_train)
    print(clf.score(clf.predict(X_test), y_test))
    

def fit(self, X, y, sample_weight=None, **kwargs):
103    def fit(self, X, y, sample_weight=None, **kwargs):
104        """Fit Regression algorithms to X and y.
105        Parameters
106        ----------
107        X : array-like,
108            Training vectors, where rows is the number of samples
109            and columns is the number of features.
110        y : array-like,
111            Training vectors, where rows is the number of samples
112            and columns is the number of features.
113        sample_weight: array-like, shape = [n_samples]
114                Sample weights.
115        Returns
116        -------
117        A fitted object
118        """
119
120        if isinstance(X, np.ndarray):
121            X = pd.DataFrame(X)
122
123        # init layer
124        self.stacked_obj = CustomRegressor(
125            obj=self.stacked_obj,
126            n_hidden_features=self.n_hidden_features,
127            activation_name=self.activation_name,
128            a=self.a,
129            nodes_sim=self.nodes_sim,
130            bias=self.bias,
131            dropout=self.dropout,
132            direct_link=self.direct_link,
133            n_clusters=self.n_clusters,
134            cluster_encode=self.cluster_encode,
135            type_clust=self.type_clust,
136            type_scaling=self.type_scaling,
137            col_sample=self.col_sample,
138            row_sample=self.row_sample,
139            seed=self.seed,
140            backend=self.backend,
141        )
142
143        if self.verbose > 0:
144            iterator = tqdm(range(self.n_layers - 1))
145        else:
146            iterator = range(self.n_layers - 1)
147
148        for _ in iterator:
149            self.stacked_obj = deepcopy(
150                CustomRegressor(
151                    obj=self.stacked_obj,
152                    n_hidden_features=self.n_hidden_features,
153                    activation_name=self.activation_name,
154                    a=self.a,
155                    nodes_sim=self.nodes_sim,
156                    bias=self.bias,
157                    dropout=self.dropout,
158                    direct_link=self.direct_link,
159                    n_clusters=self.n_clusters,
160                    cluster_encode=self.cluster_encode,
161                    type_clust=self.type_clust,
162                    type_scaling=self.type_scaling,
163                    col_sample=self.col_sample,
164                    row_sample=self.row_sample,
165                    seed=self.seed,
166                    backend=self.backend,
167                )
168            )
169
170        if self.level is not None:
171            self.stacked_obj = PredictionInterval(
172                obj=self.stacked_obj, method=self.pi_method, level=self.level
173            )
174
175        try:
176            self.stacked_obj.fit(X, y, sample_weight=sample_weight, **kwargs)
177        except Exception as e:
178            self.stacked_obj.fit(X, y)
179
180        self.obj = deepcopy(self.stacked_obj)
181
182        return self.obj

Fit Regression algorithms to X and y.

Parameters

X : array-like, Training vectors, where rows is the number of samples and columns is the number of features. y : array-like, Training vectors, where rows is the number of samples and columns is the number of features. sample_weight: array-like, shape = [n_samples] Sample weights.

Returns

A fitted object

def predict(self, X, **kwargs):
184    def predict(self, X, **kwargs):
185        if self.level is not None:
186            return self.obj.predict(X, return_pi=True)
187        return self.obj.predict(X, **kwargs)

Predict test data X.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

level: int
    Level of confidence (default = 95)

method: str
    `None`, or 'splitconformal', 'localconformal'
    prediction (if you specify `return_pi = True`)

**kwargs: additional parameters
        `return_pi = True` for conformal prediction,
        with `method` in ('splitconformal', 'localconformal')
        or `return_std = True` for `self.obj` in
        (`sklearn.linear_model.BayesianRidge`,
        `sklearn.linear_model.ARDRegressor`,
        `sklearn.gaussian_process.GaussianProcessRegressor`)`

Returns:

model predictions:
    an array if uncertainty quantification is not requested,
      or a tuple if with prediction intervals and simulations
      if `return_std = True` (mean, standard deviation,
      lower and upper prediction interval) or `return_pi = True`
      ()
def score(self, X, y, scoring=None):
189    def score(self, X, y, scoring=None):
190        return self.obj.score(X, y, scoring)

Score the model on test set features X and response y.

Parameters:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features

y: array-like, shape = [n_samples]
    Target values

scoring: str
    must be in ('explained_variance', 'neg_mean_absolute_error',
                'neg_mean_squared_error', 'neg_mean_squared_log_error',
                'neg_median_absolute_error', 'r2')

**kwargs: additional parameters to be passed to scoring functions

Returns:

model scores: {array-like}

class DeepMTS(nnetsauce.MTS):
 10class DeepMTS(MTS):
 11    """Univariate and multivariate time series (DeepMTS) forecasting with Quasi-Randomized networks (Work in progress /!\)
 12
 13    Parameters:
 14
 15        obj: object.
 16            any object containing a method fit (obj.fit()) and a method predict
 17            (obj.predict()).
 18
 19        n_layers: int.
 20            number of layers in the neural network.
 21
 22        n_hidden_features: int.
 23            number of nodes in the hidden layer.
 24
 25        activation_name: str.
 26            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'.
 27
 28        a: float.
 29            hyperparameter for 'prelu' or 'elu' activation function.
 30
 31        nodes_sim: str.
 32            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 33            'uniform'.
 34
 35        bias: boolean.
 36            indicates if the hidden layer contains a bias term (True) or not
 37            (False).
 38
 39        dropout: float.
 40            regularization parameter; (random) percentage of nodes dropped out
 41            of the training.
 42
 43        direct_link: boolean.
 44            indicates if the original predictors are included (True) in model's fitting or not (False).
 45
 46        n_clusters: int.
 47            number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering).
 48
 49        cluster_encode: bool.
 50            defines how the variable containing clusters is treated (default is one-hot)
 51            if `False`, then labels are used, without one-hot encoding.
 52
 53        type_clust: str.
 54            type of clustering method: currently k-means ('kmeans') or Gaussian
 55            Mixture Model ('gmm').
 56
 57        type_scaling: a tuple of 3 strings.
 58            scaling methods for inputs, hidden layer, and clustering respectively
 59            (and when relevant).
 60            Currently available: standardization ('std') or MinMax scaling ('minmax').
 61
 62        lags: int.
 63            number of lags used for each time series.
 64
 65        type_pi: str.
 66            type of prediction interval; currently:
 67            - "gaussian": simple, fast, but: assumes stationarity of Gaussian in-sample residuals and independence in the multivariate case
 68            - "kde": based on Kernel Density Estimation of in-sample residuals
 69            - "bootstrap": based on independent bootstrap of in-sample residuals
 70            - "block-bootstrap": based on basic block bootstrap of in-sample residuals
 71            - "scp-kde": Sequential split conformal prediction with Kernel Density Estimation of calibrated residuals
 72            - "scp-bootstrap": Sequential split conformal prediction with independent bootstrap of calibrated residuals
 73            - "scp-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of calibrated residuals
 74            - "scp2-kde": Sequential split conformal prediction with Kernel Density Estimation of standardized calibrated residuals
 75            - "scp2-bootstrap": Sequential split conformal prediction with independent bootstrap of standardized calibrated residuals
 76            - "scp2-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of standardized calibrated residuals
 77
 78        block_size: int.
 79            size of block for 'type_pi' in ("block-bootstrap", "scp-block-bootstrap", "scp2-block-bootstrap").
 80            Default is round(3.15*(n_residuals^1/3))
 81
 82        replications: int.
 83            number of replications (if needed, for predictive simulation). Default is 'None'.
 84
 85        kernel: str.
 86            the kernel to use for residuals density estimation (used for predictive simulation). Currently, either 'gaussian' or 'tophat'.
 87
 88        agg: str.
 89            either "mean" or "median" for simulation of bootstrap aggregating
 90
 91        seed: int.
 92            reproducibility seed for nodes_sim=='uniform' or predictive simulation.
 93
 94        backend: str.
 95            "cpu" or "gpu" or "tpu".
 96
 97        verbose: int.
 98            0: not printing; 1: printing
 99
100        show_progress: bool.
101            True: progress bar when fitting each series; False: no progress bar when fitting each series
102
103    Attributes:
104
105        fit_objs_: dict
106            objects adjusted to each individual time series
107
108        y_: {array-like}
109            DeepMTS responses (most recent observations first)
110
111        X_: {array-like}
112            DeepMTS lags
113
114        xreg_: {array-like}
115            external regressors
116
117        y_means_: dict
118            a dictionary of each series mean values
119
120        preds_: {array-like}
121            successive model predictions
122
123        preds_std_: {array-like}
124            standard deviation around the predictions
125
126        return_std_: boolean
127            return uncertainty or not (set in predict)
128
129        df_: data frame
130            the input data frame, in case a data.frame is provided to `fit`
131
132    Examples:
133
134    Example 1:
135
136        ```python
137        import nnetsauce as ns
138        import numpy as np
139        from sklearn import linear_model
140        np.random.seed(123)
141
142        M = np.random.rand(10, 3)
143        M[:,0] = 10*M[:,0]
144        M[:,2] = 25*M[:,2]
145        print(M)
146
147        # Adjust Bayesian Ridge
148        regr4 = linear_model.BayesianRidge()
149        obj_DeepMTS = ns.DeepMTS(regr4, lags = 1, n_hidden_features=5)
150        obj_DeepMTS.fit(M)
151        print(obj_DeepMTS.predict())
152
153        # with credible intervals
154        print(obj_DeepMTS.predict(return_std=True, level=80))
155
156        print(obj_DeepMTS.predict(return_std=True, level=95))
157        ```
158
159    Example 2:
160
161        ```python
162        import nnetsauce as ns
163        import numpy as np
164        from sklearn import linear_model
165
166        dataset = {
167        'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'],
168        'series1' : [34, 30, 35.6, 33.3, 38.1],
169        'series2' : [4, 5.5, 5.6, 6.3, 5.1],
170        'series3' : [100, 100.5, 100.6, 100.2, 100.1]}
171        df = pd.DataFrame(dataset).set_index('date')
172        print(df)
173
174        # Adjust Bayesian Ridge
175        regr5 = linear_model.BayesianRidge()
176        obj_DeepMTS = ns.DeepMTS(regr5, lags = 1, n_hidden_features=5)
177        obj_DeepMTS.fit(df)
178        print(obj_DeepMTS.predict())
179
180        # with credible intervals
181        print(obj_DeepMTS.predict(return_std=True, level=80))
182
183        print(obj_DeepMTS.predict(return_std=True, level=95))
184        ```
185
186    """
187
188    # construct the object -----
189
190    def __init__(
191        self,
192        obj,
193        n_layers=3,
194        n_hidden_features=5,
195        activation_name="relu",
196        a=0.01,
197        nodes_sim="sobol",
198        bias=True,
199        dropout=0,
200        direct_link=True,
201        n_clusters=2,
202        cluster_encode=True,
203        type_clust="kmeans",
204        type_scaling=("std", "std", "std"),
205        lags=1,
206        type_pi="kde",
207        block_size=None,
208        replications=None,
209        kernel=None,
210        agg="mean",
211        seed=123,
212        backend="cpu",
213        verbose=0,
214        show_progress=True,
215    ):
216        assert int(lags) == lags, "parameter 'lags' should be an integer"
217        assert n_layers >= 1, "must have n_layers >= 1"
218        self.n_layers = int(n_layers)
219
220        self.obj = DeepRegressor(
221            obj=obj,
222            verbose=0,
223            n_layers=self.n_layers,
224            n_hidden_features=n_hidden_features,
225            activation_name=activation_name,
226            a=a,
227            nodes_sim=nodes_sim,
228            bias=bias,
229            dropout=dropout,
230            direct_link=direct_link,
231            n_clusters=n_clusters,
232            cluster_encode=cluster_encode,
233            type_clust=type_clust,
234            type_scaling=type_scaling,
235            seed=seed,
236            backend=backend,
237        )
238
239        super().__init__(
240            obj=self.obj,
241            n_hidden_features=n_hidden_features,
242            activation_name=activation_name,
243            a=a,
244            nodes_sim=nodes_sim,
245            bias=bias,
246            dropout=dropout,
247            direct_link=direct_link,
248            n_clusters=n_clusters,
249            cluster_encode=cluster_encode,
250            type_clust=type_clust,
251            type_scaling=type_scaling,
252            seed=seed,
253            type_pi=type_pi,
254            block_size=block_size,
255            replications=replications,
256            kernel=kernel,
257            agg=agg,
258            backend=backend,
259            verbose=verbose,
260            show_progress=show_progress,
261        )

Univariate and multivariate time series (DeepMTS) forecasting with Quasi-Randomized networks (Work in progress /!)

Parameters:

obj: object.
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict()).

n_layers: int.
    number of layers in the neural network.

n_hidden_features: int.
    number of nodes in the hidden layer.

activation_name: str.
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'.

a: float.
    hyperparameter for 'prelu' or 'elu' activation function.

nodes_sim: str.
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'.

bias: boolean.
    indicates if the hidden layer contains a bias term (True) or not
    (False).

dropout: float.
    regularization parameter; (random) percentage of nodes dropped out
    of the training.

direct_link: boolean.
    indicates if the original predictors are included (True) in model's fitting or not (False).

n_clusters: int.
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering).

cluster_encode: bool.
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding.

type_clust: str.
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm').

type_scaling: a tuple of 3 strings.
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax').

lags: int.
    number of lags used for each time series.

type_pi: str.
    type of prediction interval; currently:
    - "gaussian": simple, fast, but: assumes stationarity of Gaussian in-sample residuals and independence in the multivariate case
    - "kde": based on Kernel Density Estimation of in-sample residuals
    - "bootstrap": based on independent bootstrap of in-sample residuals
    - "block-bootstrap": based on basic block bootstrap of in-sample residuals
    - "scp-kde": Sequential split conformal prediction with Kernel Density Estimation of calibrated residuals
    - "scp-bootstrap": Sequential split conformal prediction with independent bootstrap of calibrated residuals
    - "scp-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of calibrated residuals
    - "scp2-kde": Sequential split conformal prediction with Kernel Density Estimation of standardized calibrated residuals
    - "scp2-bootstrap": Sequential split conformal prediction with independent bootstrap of standardized calibrated residuals
    - "scp2-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of standardized calibrated residuals

block_size: int.
    size of block for 'type_pi' in ("block-bootstrap", "scp-block-bootstrap", "scp2-block-bootstrap").
    Default is round(3.15*(n_residuals^1/3))

replications: int.
    number of replications (if needed, for predictive simulation). Default is 'None'.

kernel: str.
    the kernel to use for residuals density estimation (used for predictive simulation). Currently, either 'gaussian' or 'tophat'.

agg: str.
    either "mean" or "median" for simulation of bootstrap aggregating

seed: int.
    reproducibility seed for nodes_sim=='uniform' or predictive simulation.

backend: str.
    "cpu" or "gpu" or "tpu".

verbose: int.
    0: not printing; 1: printing

show_progress: bool.
    True: progress bar when fitting each series; False: no progress bar when fitting each series

Attributes:

fit_objs_: dict
    objects adjusted to each individual time series

y_: {array-like}
    DeepMTS responses (most recent observations first)

X_: {array-like}
    DeepMTS lags

xreg_: {array-like}
    external regressors

y_means_: dict
    a dictionary of each series mean values

preds_: {array-like}
    successive model predictions

preds_std_: {array-like}
    standard deviation around the predictions

return_std_: boolean
    return uncertainty or not (set in predict)

df_: data frame
    the input data frame, in case a data.frame is provided to `fit`

Examples:

Example 1:

import nnetsauce as ns
    import numpy as np
    from sklearn import linear_model
    np.random.seed(123)
 
M = np.random.rand(10, 3) M[:,0] = 10M[:,0] M[:,2] = 25M[:,2] print(M)
# Adjust Bayesian Ridge regr4 = linear_model.BayesianRidge() obj_DeepMTS = ns.DeepMTS(regr4, lags = 1, n_hidden_features=5) obj_DeepMTS.fit(M) print(obj_DeepMTS.predict())
# with credible intervals print(obj_DeepMTS.predict(return_std=True, level=80))
print(obj_DeepMTS.predict(return_std=True, level=95))

Example 2:

import nnetsauce as ns
    import numpy as np
    from sklearn import linear_model
 
dataset = { 'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'], 'series1' : [34, 30, 35.6, 33.3, 38.1], 'series2' : [4, 5.5, 5.6, 6.3, 5.1], 'series3' : [100, 100.5, 100.6, 100.2, 100.1]} df = pd.DataFrame(dataset).set_index('date') print(df)
# Adjust Bayesian Ridge regr5 = linear_model.BayesianRidge() obj_DeepMTS = ns.DeepMTS(regr5, lags = 1, n_hidden_features=5) obj_DeepMTS.fit(df) print(obj_DeepMTS.predict())
# with credible intervals print(obj_DeepMTS.predict(return_std=True, level=80))
print(obj_DeepMTS.predict(return_std=True, level=95))

class Downloader:
 6class Downloader:
 7    """Download datasets from data sources (R-universe for now)"""
 8
 9    def __init__(self):
10        self.pkgname = None
11        self.dataset = None
12        self.source = None
13        self.url = None
14        self.request = None
15
16    def download(
17        self,
18        pkgname="MASS",
19        dataset="Boston",
20        source="https://cran.r-universe.dev/",
21        **kwargs
22    ):
23        """Download datasets from data sources (R-universe for now)
24
25        Examples:
26
27        ```python
28        import nnetsauce as ns
29
30        downloader = ns.Downloader()
31        df = downloader.download(pkgname="MASS", dataset="Boston")
32        ```
33
34        """
35        self.pkgname = pkgname
36        self.dataset = dataset
37        self.source = source
38        self.url = source + pkgname + "/data/" + dataset + "/json"
39        self.request = requests.get(self.url)
40        return pd.DataFrame(self.request.json(), **kwargs)

Download datasets from data sources (R-universe for now)

def download( self, pkgname='MASS', dataset='Boston', source='https://cran.r-universe.dev/', **kwargs):
16    def download(
17        self,
18        pkgname="MASS",
19        dataset="Boston",
20        source="https://cran.r-universe.dev/",
21        **kwargs
22    ):
23        """Download datasets from data sources (R-universe for now)
24
25        Examples:
26
27        ```python
28        import nnetsauce as ns
29
30        downloader = ns.Downloader()
31        df = downloader.download(pkgname="MASS", dataset="Boston")
32        ```
33
34        """
35        self.pkgname = pkgname
36        self.dataset = dataset
37        self.source = source
38        self.url = source + pkgname + "/data/" + dataset + "/json"
39        self.request = requests.get(self.url)
40        return pd.DataFrame(self.request.json(), **kwargs)

Download datasets from data sources (R-universe for now)

Examples:

import nnetsauce as ns

downloader = ns.Downloader()
df = downloader.download(pkgname="MASS", dataset="Boston")
class GLMClassifier(nnetsauce.glm.glm.GLM, sklearn.base.ClassifierMixin):
 16class GLMClassifier(GLM, ClassifierMixin):
 17    """Generalized 'linear' models using quasi-randomized networks (classification)
 18
 19    Parameters:
 20
 21        n_hidden_features: int
 22            number of nodes in the hidden layer
 23
 24        lambda1: float
 25            regularization parameter for GLM coefficients on original features
 26
 27        alpha1: float
 28            controls compromize between l1 and l2 norm of GLM coefficients on original features
 29
 30        lambda2: float
 31            regularization parameter for GLM coefficients on nonlinear features
 32
 33        alpha2: float
 34            controls compromize between l1 and l2 norm of GLM coefficients on nonlinear features
 35
 36        activation_name: str
 37            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 38
 39        a: float
 40            hyperparameter for 'prelu' or 'elu' activation function
 41
 42        nodes_sim: str
 43            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 44            'uniform'
 45
 46        bias: boolean
 47            indicates if the hidden layer contains a bias term (True) or not
 48            (False)
 49
 50        dropout: float
 51            regularization parameter; (random) percentage of nodes dropped out
 52            of the training
 53
 54        direct_link: boolean
 55            indicates if the original predictors are included (True) in model's
 56            fitting or not (False)
 57
 58        n_clusters: int
 59            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 60                no clustering)
 61
 62        cluster_encode: bool
 63            defines how the variable containing clusters is treated (default is one-hot)
 64            if `False`, then labels are used, without one-hot encoding
 65
 66        type_clust: str
 67            type of clustering method: currently k-means ('kmeans') or Gaussian
 68            Mixture Model ('gmm')
 69
 70        type_scaling: a tuple of 3 strings
 71            scaling methods for inputs, hidden layer, and clustering respectively
 72            (and when relevant).
 73            Currently available: standardization ('std') or MinMax scaling ('minmax')
 74
 75        optimizer: object
 76            optimizer, from class nnetsauce.Optimizer
 77
 78        seed: int
 79            reproducibility seed for nodes_sim=='uniform'
 80
 81    Attributes:
 82
 83        beta_: vector
 84            regression coefficients
 85
 86    Examples:
 87
 88    See [https://github.com/Techtonique/nnetsauce/blob/master/examples/glm_classification.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/glm_classification.py)
 89
 90    """
 91
 92    # construct the object -----
 93
 94    def __init__(
 95        self,
 96        n_hidden_features=5,
 97        lambda1=0.01,
 98        alpha1=0.5,
 99        lambda2=0.01,
100        alpha2=0.5,
101        family="expit",
102        activation_name="relu",
103        a=0.01,
104        nodes_sim="sobol",
105        bias=True,
106        dropout=0,
107        direct_link=True,
108        n_clusters=2,
109        cluster_encode=True,
110        type_clust="kmeans",
111        type_scaling=("std", "std", "std"),
112        optimizer=Optimizer(),
113        seed=123,
114    ):
115        super().__init__(
116            n_hidden_features=n_hidden_features,
117            lambda1=lambda1,
118            alpha1=alpha1,
119            lambda2=lambda2,
120            alpha2=alpha2,
121            activation_name=activation_name,
122            a=a,
123            nodes_sim=nodes_sim,
124            bias=bias,
125            dropout=dropout,
126            direct_link=direct_link,
127            n_clusters=n_clusters,
128            cluster_encode=cluster_encode,
129            type_clust=type_clust,
130            type_scaling=type_scaling,
131            optimizer=optimizer,
132            seed=seed,
133        )
134
135        self.family = family
136
137    def logit_loss(self, Y, row_index, XB):
138        self.n_classes = Y.shape[1]  # len(np.unique(y))
139        # Y = mo.one_hot_encode2(y, self.n_classes)
140        # Y = self.optimizer.one_hot_encode(y, self.n_classes)
141
142        # max_double = 709.0 # only if softmax
143        # XB[XB > max_double] = max_double
144        XB[XB > 709.0] = 709.0
145
146        if row_index is None:
147            return -np.mean(np.sum(Y * XB, axis=1) - logsumexp(XB))
148
149        return -np.mean(np.sum(Y[row_index, :] * XB, axis=1) - logsumexp(XB))
150
151    def expit_erf_loss(self, Y, row_index, XB):
152        # self.n_classes = len(np.unique(y))
153        # Y = mo.one_hot_encode2(y, self.n_classes)
154        # Y = self.optimizer.one_hot_encode(y, self.n_classes)
155        self.n_classes = Y.shape[1]
156
157        if row_index is None:
158            return -np.mean(np.sum(Y * XB, axis=1) - logsumexp(XB))
159
160        return -np.mean(np.sum(Y[row_index, :] * XB, axis=1) - logsumexp(XB))
161
162    def loss_func(
163        self,
164        beta,
165        group_index,
166        X,
167        Y,
168        y,
169        row_index=None,
170        type_loss="logit",
171        **kwargs
172    ):
173        res = {
174            "logit": self.logit_loss,
175            "expit": self.expit_erf_loss,
176            "erf": self.expit_erf_loss,
177        }
178
179        if row_index is None:
180            row_index = range(len(y))
181            XB = self.compute_XB(
182                X,
183                beta=np.reshape(beta, (X.shape[1], self.n_classes), order="F"),
184            )
185
186            return res[type_loss](Y, row_index, XB) + self.compute_penalty(
187                group_index=group_index, beta=beta
188            )
189
190        XB = self.compute_XB(
191            X,
192            beta=np.reshape(beta, (X.shape[1], self.n_classes), order="F"),
193            row_index=row_index,
194        )
195
196        return res[type_loss](Y, row_index, XB) + self.compute_penalty(
197            group_index=group_index, beta=beta
198        )
199
200    def fit(self, X, y, **kwargs):
201        """Fit GLM model to training data (X, y).
202
203        Args:
204
205            X: {array-like}, shape = [n_samples, n_features]
206                Training vectors, where n_samples is the number
207                of samples and n_features is the number of features.
208
209            y: array-like, shape = [n_samples]
210                Target values.
211
212            **kwargs: additional parameters to be passed to
213                    self.cook_training_set or self.obj.fit
214
215        Returns:
216
217            self: object
218
219        """
220
221        assert mx.is_factor(
222            y
223        ), "y must contain only integers"  # change is_factor and subsampling everywhere
224
225        self.classes_ = np.unique(y)  # for compatibility with sklearn
226        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
227
228        self.beta_ = None
229
230        n, p = X.shape
231
232        self.group_index = n * X.shape[1]
233
234        self.n_classes = len(np.unique(y))
235
236        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
237
238        # Y = mo.one_hot_encode2(output_y, self.n_classes)
239        Y = self.optimizer.one_hot_encode(output_y, self.n_classes)
240
241        # initialization
242        beta_ = np.linalg.lstsq(scaled_Z, Y, rcond=None)[0]
243
244        # optimization
245        # fit(self, loss_func, response, x0, **kwargs):
246        # loss_func(self, beta, group_index, X, y,
247        #          row_index=None, type_loss="gaussian",
248        #          **kwargs)
249        self.optimizer.fit(
250            self.loss_func,
251            response=y,
252            x0=beta_.flatten(order="F"),
253            group_index=self.group_index,
254            X=scaled_Z,
255            Y=Y,
256            y=y,
257            type_loss=self.family,
258        )
259
260        self.beta_ = self.optimizer.results[0]
261        self.classes_ = np.unique(y)
262
263        return self
264
265    def predict(self, X, **kwargs):
266        """Predict test data X.
267
268        Args:
269
270            X: {array-like}, shape = [n_samples, n_features]
271                Training vectors, where n_samples is the number
272                of samples and n_features is the number of features.
273
274            **kwargs: additional parameters to be passed to
275                    self.cook_test_set
276
277        Returns:
278
279            model predictions: {array-like}
280
281        """
282
283        return np.argmax(self.predict_proba(X, **kwargs), axis=1)
284
285    def predict_proba(self, X, **kwargs):
286        """Predict probabilities for test data X.
287
288        Args:
289
290            X: {array-like}, shape = [n_samples, n_features]
291                Training vectors, where n_samples is the number
292                of samples and n_features is the number of features.
293
294            **kwargs: additional parameters to be passed to
295                    self.cook_test_set
296
297        Returns:
298
299            probability estimates for test data: {array-like}
300
301        """
302        if len(X.shape) == 1:
303            n_features = X.shape[0]
304            new_X = mo.rbind(
305                X.reshape(1, n_features),
306                np.ones(n_features).reshape(1, n_features),
307            )
308
309            Z = self.cook_test_set(new_X, **kwargs)
310
311        else:
312            Z = self.cook_test_set(X, **kwargs)
313
314        ZB = mo.safe_sparse_dot(
315            Z,
316            self.beta_.reshape(
317                self.n_classes,
318                X.shape[1] + self.n_hidden_features + self.n_clusters,
319            ).T,
320        )
321
322        if self.family == "logit":
323            exp_ZB = np.exp(ZB)
324
325            return exp_ZB / exp_ZB.sum(axis=1)[:, None]
326
327        if self.family == "expit":
328            exp_ZB = expit(ZB)
329
330            return exp_ZB / exp_ZB.sum(axis=1)[:, None]
331
332        if self.family == "erf":
333            exp_ZB = 0.5 * (1 + erf(ZB))
334
335            return exp_ZB / exp_ZB.sum(axis=1)[:, None]

Generalized 'linear' models using quasi-randomized networks (classification)

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

lambda1: float
    regularization parameter for GLM coefficients on original features

alpha1: float
    controls compromize between l1 and l2 norm of GLM coefficients on original features

lambda2: float
    regularization parameter for GLM coefficients on nonlinear features

alpha2: float
    controls compromize between l1 and l2 norm of GLM coefficients on nonlinear features

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

optimizer: object
    optimizer, from class nnetsauce.Optimizer

seed: int
    reproducibility seed for nodes_sim=='uniform'

Attributes:

beta_: vector
    regression coefficients

Examples:

See https://github.com/Techtonique/nnetsauce/blob/master/examples/glm_classification.py

def fit(self, X, y, **kwargs):
200    def fit(self, X, y, **kwargs):
201        """Fit GLM model to training data (X, y).
202
203        Args:
204
205            X: {array-like}, shape = [n_samples, n_features]
206                Training vectors, where n_samples is the number
207                of samples and n_features is the number of features.
208
209            y: array-like, shape = [n_samples]
210                Target values.
211
212            **kwargs: additional parameters to be passed to
213                    self.cook_training_set or self.obj.fit
214
215        Returns:
216
217            self: object
218
219        """
220
221        assert mx.is_factor(
222            y
223        ), "y must contain only integers"  # change is_factor and subsampling everywhere
224
225        self.classes_ = np.unique(y)  # for compatibility with sklearn
226        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
227
228        self.beta_ = None
229
230        n, p = X.shape
231
232        self.group_index = n * X.shape[1]
233
234        self.n_classes = len(np.unique(y))
235
236        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
237
238        # Y = mo.one_hot_encode2(output_y, self.n_classes)
239        Y = self.optimizer.one_hot_encode(output_y, self.n_classes)
240
241        # initialization
242        beta_ = np.linalg.lstsq(scaled_Z, Y, rcond=None)[0]
243
244        # optimization
245        # fit(self, loss_func, response, x0, **kwargs):
246        # loss_func(self, beta, group_index, X, y,
247        #          row_index=None, type_loss="gaussian",
248        #          **kwargs)
249        self.optimizer.fit(
250            self.loss_func,
251            response=y,
252            x0=beta_.flatten(order="F"),
253            group_index=self.group_index,
254            X=scaled_Z,
255            Y=Y,
256            y=y,
257            type_loss=self.family,
258        )
259
260        self.beta_ = self.optimizer.results[0]
261        self.classes_ = np.unique(y)
262
263        return self

Fit GLM model to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
265    def predict(self, X, **kwargs):
266        """Predict test data X.
267
268        Args:
269
270            X: {array-like}, shape = [n_samples, n_features]
271                Training vectors, where n_samples is the number
272                of samples and n_features is the number of features.
273
274            **kwargs: additional parameters to be passed to
275                    self.cook_test_set
276
277        Returns:
278
279            model predictions: {array-like}
280
281        """
282
283        return np.argmax(self.predict_proba(X, **kwargs), axis=1)

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
285    def predict_proba(self, X, **kwargs):
286        """Predict probabilities for test data X.
287
288        Args:
289
290            X: {array-like}, shape = [n_samples, n_features]
291                Training vectors, where n_samples is the number
292                of samples and n_features is the number of features.
293
294            **kwargs: additional parameters to be passed to
295                    self.cook_test_set
296
297        Returns:
298
299            probability estimates for test data: {array-like}
300
301        """
302        if len(X.shape) == 1:
303            n_features = X.shape[0]
304            new_X = mo.rbind(
305                X.reshape(1, n_features),
306                np.ones(n_features).reshape(1, n_features),
307            )
308
309            Z = self.cook_test_set(new_X, **kwargs)
310
311        else:
312            Z = self.cook_test_set(X, **kwargs)
313
314        ZB = mo.safe_sparse_dot(
315            Z,
316            self.beta_.reshape(
317                self.n_classes,
318                X.shape[1] + self.n_hidden_features + self.n_clusters,
319            ).T,
320        )
321
322        if self.family == "logit":
323            exp_ZB = np.exp(ZB)
324
325            return exp_ZB / exp_ZB.sum(axis=1)[:, None]
326
327        if self.family == "expit":
328            exp_ZB = expit(ZB)
329
330            return exp_ZB / exp_ZB.sum(axis=1)[:, None]
331
332        if self.family == "erf":
333            exp_ZB = 0.5 * (1 + erf(ZB))
334
335            return exp_ZB / exp_ZB.sum(axis=1)[:, None]

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class GLMRegressor(nnetsauce.glm.glm.GLM, sklearn.base.RegressorMixin):
 14class GLMRegressor(GLM, RegressorMixin):
 15    """Generalized 'linear' models using quasi-randomized networks (regression)
 16
 17    Attributes:
 18
 19        n_hidden_features: int
 20            number of nodes in the hidden layer
 21
 22        lambda1: float
 23            regularization parameter for GLM coefficients on original features
 24
 25        alpha1: float
 26            controls compromize between l1 and l2 norm of GLM coefficients on original features
 27
 28        lambda2: float
 29            regularization parameter for GLM coefficients on nonlinear features
 30
 31        alpha2: float
 32            controls compromize between l1 and l2 norm of GLM coefficients on nonlinear features
 33
 34        family: str
 35            "gaussian", "laplace" or "poisson" (for now)
 36
 37        activation_name: str
 38            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 39
 40        a: float
 41            hyperparameter for 'prelu' or 'elu' activation function
 42
 43        nodes_sim: str
 44            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 45            'uniform'
 46
 47        bias: boolean
 48            indicates if the hidden layer contains a bias term (True) or not
 49            (False)
 50
 51        dropout: float
 52            regularization parameter; (random) percentage of nodes dropped out
 53            of the training
 54
 55        direct_link: boolean
 56            indicates if the original predictors are included (True) in model's
 57            fitting or not (False)
 58
 59        n_clusters: int
 60            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 61                no clustering)
 62
 63        cluster_encode: bool
 64            defines how the variable containing clusters is treated (default is one-hot)
 65            if `False`, then labels are used, without one-hot encoding
 66
 67        type_clust: str
 68            type of clustering method: currently k-means ('kmeans') or Gaussian
 69            Mixture Model ('gmm')
 70
 71        type_scaling: a tuple of 3 strings
 72            scaling methods for inputs, hidden layer, and clustering respectively
 73            (and when relevant).
 74            Currently available: standardization ('std') or MinMax scaling ('minmax')
 75
 76        optimizer: object
 77            optimizer, from class nnetsauce.utils.Optimizer
 78
 79        seed: int
 80            reproducibility seed for nodes_sim=='uniform'
 81
 82    Attributes:
 83
 84        beta_: vector
 85            regression coefficients
 86
 87    Examples:
 88
 89    See [https://github.com/Techtonique/nnetsauce/blob/master/examples/glm_regression.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/glm_regression.py)
 90
 91    """
 92
 93    # construct the object -----
 94
 95    def __init__(
 96        self,
 97        n_hidden_features=5,
 98        lambda1=0.01,
 99        alpha1=0.5,
100        lambda2=0.01,
101        alpha2=0.5,
102        family="gaussian",
103        activation_name="relu",
104        a=0.01,
105        nodes_sim="sobol",
106        bias=True,
107        dropout=0,
108        direct_link=True,
109        n_clusters=2,
110        cluster_encode=True,
111        type_clust="kmeans",
112        type_scaling=("std", "std", "std"),
113        optimizer=Optimizer(),
114        seed=123,
115    ):
116        super().__init__(
117            n_hidden_features=n_hidden_features,
118            lambda1=lambda1,
119            alpha1=alpha1,
120            lambda2=lambda2,
121            alpha2=alpha2,
122            activation_name=activation_name,
123            a=a,
124            nodes_sim=nodes_sim,
125            bias=bias,
126            dropout=dropout,
127            direct_link=direct_link,
128            n_clusters=n_clusters,
129            cluster_encode=cluster_encode,
130            type_clust=type_clust,
131            type_scaling=type_scaling,
132            optimizer=optimizer,
133            seed=seed,
134        )
135
136        self.family = family
137
138    def gaussian_loss(self, y, row_index, XB):
139        return 0.5 * np.mean(np.square(y[row_index] - XB))
140
141    def laplace_loss(self, y, row_index, XB):
142        return 0.5 * np.mean(np.abs(y[row_index] - XB))
143
144    def poisson_loss(self, y, row_index, XB):
145        return -np.mean(y[row_index] * XB - np.exp(XB))
146
147    def loss_func(
148        self,
149        beta,
150        group_index,
151        X,
152        y,
153        row_index=None,
154        type_loss="gaussian",
155        **kwargs
156    ):
157        res = {
158            "gaussian": self.gaussian_loss,
159            "laplace": self.laplace_loss,
160            "poisson": self.poisson_loss,
161        }
162
163        if row_index is None:
164            row_index = range(len(y))
165            XB = self.compute_XB(X, beta=beta)
166
167            return res[type_loss](y, row_index, XB) + self.compute_penalty(
168                group_index=group_index, beta=beta
169            )
170
171        XB = self.compute_XB(X, beta=beta, row_index=row_index)
172
173        return res[type_loss](y, row_index, XB) + self.compute_penalty(
174            group_index=group_index, beta=beta
175        )
176
177    def fit(self, X, y, **kwargs):
178        """Fit GLM model to training data (X, y).
179
180        Args:
181
182            X: {array-like}, shape = [n_samples, n_features]
183                Training vectors, where n_samples is the number
184                of samples and n_features is the number of features.
185
186            y: array-like, shape = [n_samples]
187                Target values.
188
189            **kwargs: additional parameters to be passed to
190                    self.cook_training_set or self.obj.fit
191
192        Returns:
193
194            self: object
195
196        """
197
198        self.beta_ = None
199
200        self.n_iter = 0
201
202        n, self.group_index = X.shape
203
204        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
205
206        n_Z = scaled_Z.shape[0]
207
208        # initialization
209        beta_ = np.linalg.lstsq(scaled_Z, centered_y, rcond=None)[0]
210
211        # optimization
212        # fit(self, loss_func, response, x0, **kwargs):
213        # loss_func(self, beta, group_index, X, y,
214        #          row_index=None, type_loss="gaussian",
215        #          **kwargs)
216        self.optimizer.fit(
217            self.loss_func,
218            response=centered_y,
219            x0=beta_,
220            group_index=self.group_index,
221            X=scaled_Z,
222            y=centered_y,
223            type_loss=self.family,
224            **kwargs
225        )
226
227        self.beta_ = self.optimizer.results[0]
228
229        return self
230
231    def predict(self, X, **kwargs):
232        """Predict test data X.
233
234        Args:
235
236            X: {array-like}, shape = [n_samples, n_features]
237                Training vectors, where n_samples is the number
238                of samples and n_features is the number of features.
239
240            **kwargs: additional parameters to be passed to
241                    self.cook_test_set
242
243        Returns:
244
245            model predictions: {array-like}
246
247        """
248
249        if len(X.shape) == 1:
250            n_features = X.shape[0]
251            new_X = mo.rbind(
252                X.reshape(1, n_features),
253                np.ones(n_features).reshape(1, n_features),
254            )
255
256            return (
257                self.y_mean_
258                + np.dot(self.cook_test_set(new_X, **kwargs), self.beta_)
259            )[0]
260
261        return self.y_mean_ + np.dot(
262            self.cook_test_set(X, **kwargs), self.beta_
263        )

Generalized 'linear' models using quasi-randomized networks (regression)

Attributes:

n_hidden_features: int
    number of nodes in the hidden layer

lambda1: float
    regularization parameter for GLM coefficients on original features

alpha1: float
    controls compromize between l1 and l2 norm of GLM coefficients on original features

lambda2: float
    regularization parameter for GLM coefficients on nonlinear features

alpha2: float
    controls compromize between l1 and l2 norm of GLM coefficients on nonlinear features

family: str
    "gaussian", "laplace" or "poisson" (for now)

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

optimizer: object
    optimizer, from class nnetsauce.utils.Optimizer

seed: int
    reproducibility seed for nodes_sim=='uniform'

Attributes:

beta_: vector
    regression coefficients

Examples:

See https://github.com/Techtonique/nnetsauce/blob/master/examples/glm_regression.py

def fit(self, X, y, **kwargs):
177    def fit(self, X, y, **kwargs):
178        """Fit GLM model to training data (X, y).
179
180        Args:
181
182            X: {array-like}, shape = [n_samples, n_features]
183                Training vectors, where n_samples is the number
184                of samples and n_features is the number of features.
185
186            y: array-like, shape = [n_samples]
187                Target values.
188
189            **kwargs: additional parameters to be passed to
190                    self.cook_training_set or self.obj.fit
191
192        Returns:
193
194            self: object
195
196        """
197
198        self.beta_ = None
199
200        self.n_iter = 0
201
202        n, self.group_index = X.shape
203
204        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
205
206        n_Z = scaled_Z.shape[0]
207
208        # initialization
209        beta_ = np.linalg.lstsq(scaled_Z, centered_y, rcond=None)[0]
210
211        # optimization
212        # fit(self, loss_func, response, x0, **kwargs):
213        # loss_func(self, beta, group_index, X, y,
214        #          row_index=None, type_loss="gaussian",
215        #          **kwargs)
216        self.optimizer.fit(
217            self.loss_func,
218            response=centered_y,
219            x0=beta_,
220            group_index=self.group_index,
221            X=scaled_Z,
222            y=centered_y,
223            type_loss=self.family,
224            **kwargs
225        )
226
227        self.beta_ = self.optimizer.results[0]
228
229        return self

Fit GLM model to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
231    def predict(self, X, **kwargs):
232        """Predict test data X.
233
234        Args:
235
236            X: {array-like}, shape = [n_samples, n_features]
237                Training vectors, where n_samples is the number
238                of samples and n_features is the number of features.
239
240            **kwargs: additional parameters to be passed to
241                    self.cook_test_set
242
243        Returns:
244
245            model predictions: {array-like}
246
247        """
248
249        if len(X.shape) == 1:
250            n_features = X.shape[0]
251            new_X = mo.rbind(
252                X.reshape(1, n_features),
253                np.ones(n_features).reshape(1, n_features),
254            )
255
256            return (
257                self.y_mean_
258                + np.dot(self.cook_test_set(new_X, **kwargs), self.beta_)
259            )[0]
260
261        return self.y_mean_ + np.dot(
262            self.cook_test_set(X, **kwargs), self.beta_
263        )

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
class LazyClassifier(nnetsauce.custom.custom.Custom, sklearn.base.ClassifierMixin):
 84class LazyClassifier(Custom, ClassifierMixin):
 85    """
 86
 87        Fitting -- almost -- all the classification algorithms with nnetsauce's
 88        CustomClassifier and returning their scores.
 89
 90    Parameters:
 91
 92        verbose: int, optional (default=0)
 93            Any positive number for verbosity.
 94
 95        ignore_warnings: bool, optional (default=True)
 96            When set to True, warnings related to algorithms that were not
 97            run are ignored.
 98
 99        custom_metric: function, optional (default=None)
100            When function is provided, models are evaluated based on the
101            custom evaluation metric provided.
102
103        predictions: bool, optional (default=False)
104            When set to True, the predictions of all the models models are
105            returned as data frame.
106
107        sort_by: string, optional (default='Accuracy')
108            Sort models by a metric. Available options are 'Accuracy',
109            'Balanced Accuracy', 'ROC AUC', 'F1 Score' or a custom metric
110            identified by its name and provided by custom_metric.
111
112        random_state: int, optional (default=42)
113            Reproducibiility seed.
114
115        estimators: list, optional (default='all')
116            list of Estimators names or just 'all' for > 90
117            classifiers (default='all')
118
119        preprocess: bool, preprocessing is done when set to True
120
121        n_jobs: int, when possible, run in parallel
122            For now, only used by individual models that support it.
123
124        All the other parameters are the same as CustomClassifier's.
125
126    Examples:
127
128        ```python
129        import nnetsauce as ns
130        from sklearn.datasets import load_breast_cancer
131        from sklearn.model_selection import train_test_split
132        data = load_breast_cancer()
133        X = data.data
134        y= data.target
135        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2,
136        random_state=123)
137        clf = ns.LazyClassifier(verbose=0, ignore_warnings=True)
138        models, predictions = clf.fit(X_train, X_test, y_train, y_test)
139        model_dictionary = clf.provide_models(X_train,X_test,y_train,y_test)
140        print(models)
141        ```
142
143    """
144
145    def __init__(
146        self,
147        verbose=0,
148        ignore_warnings=True,
149        custom_metric=None,
150        predictions=False,
151        sort_by="Accuracy",
152        random_state=42,
153        estimators="all",
154        preprocess=False,
155        n_jobs=None,
156        # CustomClassifier attributes
157        obj=None,
158        n_hidden_features=5,
159        activation_name="relu",
160        a=0.01,
161        nodes_sim="sobol",
162        bias=True,
163        dropout=0,
164        direct_link=True,
165        n_clusters=2,
166        cluster_encode=True,
167        type_clust="kmeans",
168        type_scaling=("std", "std", "std"),
169        col_sample=1,
170        row_sample=1,
171        seed=123,
172        backend="cpu",
173    ):
174        self.verbose = verbose
175        self.ignore_warnings = ignore_warnings
176        self.custom_metric = custom_metric
177        self.predictions = predictions
178        self.sort_by = sort_by
179        self.models = {}
180        self.random_state = random_state
181        self.estimators = estimators
182        self.preprocess = preprocess
183        self.n_jobs = n_jobs
184        super().__init__(
185            obj=obj,
186            n_hidden_features=n_hidden_features,
187            activation_name=activation_name,
188            a=a,
189            nodes_sim=nodes_sim,
190            bias=bias,
191            dropout=dropout,
192            direct_link=direct_link,
193            n_clusters=n_clusters,
194            cluster_encode=cluster_encode,
195            type_clust=type_clust,
196            type_scaling=type_scaling,
197            col_sample=col_sample,
198            row_sample=row_sample,
199            seed=seed,
200            backend=backend,
201        )
202
203    def fit(self, X_train, X_test, y_train, y_test):
204        """Fit classifiers to X_train and y_train, predict and score on X_test,
205        y_test.
206
207        Parameters:
208
209            X_train: array-like,
210                Training vectors, where rows is the number of samples
211                and columns is the number of features.
212
213            X_test: array-like,
214                Testing vectors, where rows is the number of samples
215                and columns is the number of features.
216
217            y_train: array-like,
218                Training vectors, where rows is the number of samples
219                and columns is the number of features.
220
221            y_test: array-like,
222                Testing vectors, where rows is the number of samples
223                and columns is the number of features.
224
225        Returns:
226
227            scores: Pandas DataFrame
228                Returns metrics of all the models in a Pandas DataFrame.
229
230            predictions: Pandas DataFrame
231                Returns predictions of all the models in a Pandas DataFrame.
232        """
233        Accuracy = []
234        B_Accuracy = []
235        ROC_AUC = []
236        F1 = []
237        names = []
238        TIME = []
239        predictions = {}
240
241        if self.custom_metric is not None:
242            CUSTOM_METRIC = []
243
244        if isinstance(X_train, np.ndarray):
245            X_train = pd.DataFrame(X_train)
246            X_test = pd.DataFrame(X_test)
247
248        numeric_features = X_train.select_dtypes(include=[np.number]).columns
249        categorical_features = X_train.select_dtypes(include=["object"]).columns
250
251        categorical_low, categorical_high = get_card_split(
252            X_train, categorical_features
253        )
254
255        if self.preprocess is True:
256
257            preprocessor = ColumnTransformer(
258                transformers=[
259                    ("numeric", numeric_transformer, numeric_features),
260                    (
261                        "categorical_low",
262                        categorical_transformer_low,
263                        categorical_low,
264                    ),
265                    (
266                        "categorical_high",
267                        categorical_transformer_high,
268                        categorical_high,
269                    ),
270                ]
271            )
272
273        if self.estimators == "all":
274
275            self.classifiers = (
276                CLASSIFIERS + MULTITASKCLASSIFIERS + SIMPLEMULTITASKCLASSIFIERS
277            )
278
279        else:  # list custom estimators, by their names
280
281            self.classifiers = (
282                [
283                    ("CustomClassifier(" + est[0] + ")", est[1])
284                    for est in all_estimators()
285                    if (
286                        issubclass(est[1], ClassifierMixin)
287                        and (est[0] in self.estimators)
288                    )
289                ]
290                + [
291                    (
292                        "MultitaskClassifier(" + est[0] + ")",
293                        partial(MultitaskClassifier, obj=est[1]()),
294                    )
295                    for est in all_estimators()
296                    if (
297                        issubclass(est[1], RegressorMixin)
298                        and (est[0] in self.estimators)
299                    )
300                ]
301                + [
302                    (
303                        "SimpleMultitaskClassifier(" + est[0] + ")",
304                        partial(SimpleMultitaskClassifier, obj=est[1]()),
305                    )
306                    for est in all_estimators()
307                    if (
308                        issubclass(est[1], RegressorMixin)
309                        and (est[0] in self.estimators)
310                    )
311                ]
312            )
313
314        if self.preprocess is True:
315
316            for name, model in tqdm(self.classifiers):  # do parallel exec
317
318                other_args = (
319                    {}
320                )  # use this trick for `random_state` too --> refactor
321                try:
322                    if (
323                        "n_jobs" in model().get_params().keys()
324                        and name.find("LogisticRegression") == -1
325                    ):
326                        other_args["n_jobs"] = self.n_jobs
327                except Exception:
328                    pass
329
330                start = time.time()
331
332                try:
333                    if "random_state" in model().get_params().keys():
334                        pipe = Pipeline(
335                            [
336                                ("preprocessor", preprocessor),
337                                (
338                                    "classifier",
339                                    CustomClassifier(
340                                        obj=model(
341                                            random_state=self.random_state,
342                                            **other_args
343                                        ),
344                                        n_hidden_features=self.n_hidden_features,
345                                        activation_name=self.activation_name,
346                                        a=self.a,
347                                        nodes_sim=self.nodes_sim,
348                                        bias=self.bias,
349                                        dropout=self.dropout,
350                                        direct_link=self.direct_link,
351                                        n_clusters=self.n_clusters,
352                                        cluster_encode=self.cluster_encode,
353                                        type_clust=self.type_clust,
354                                        type_scaling=self.type_scaling,
355                                        col_sample=self.col_sample,
356                                        row_sample=self.row_sample,
357                                        seed=self.seed,
358                                        backend=self.backend,
359                                    ),
360                                ),
361                            ]
362                        )
363                    else:
364                        pipe = Pipeline(
365                            [
366                                ("preprocessor", preprocessor),
367                                (
368                                    "classifier",
369                                    CustomClassifier(
370                                        obj=model(**other_args),
371                                        n_hidden_features=self.n_hidden_features,
372                                        activation_name=self.activation_name,
373                                        a=self.a,
374                                        nodes_sim=self.nodes_sim,
375                                        bias=self.bias,
376                                        dropout=self.dropout,
377                                        direct_link=self.direct_link,
378                                        n_clusters=self.n_clusters,
379                                        cluster_encode=self.cluster_encode,
380                                        type_clust=self.type_clust,
381                                        type_scaling=self.type_scaling,
382                                        col_sample=self.col_sample,
383                                        row_sample=self.row_sample,
384                                        seed=self.seed,
385                                        backend=self.backend,
386                                    ),
387                                ),
388                            ]
389                        )
390
391                    pipe.fit(X_train, y_train)
392                    self.models[name] = pipe
393                    y_pred = pipe.predict(X_test)
394                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
395                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
396                    f1 = f1_score(y_test, y_pred, average="weighted")
397                    try:
398                        roc_auc = roc_auc_score(y_test, y_pred)
399                    except Exception as exception:
400                        roc_auc = None
401                        if self.ignore_warnings is False:
402                            print("ROC AUC couldn't be calculated for " + name)
403                            print(exception)
404                    names.append(name)
405                    Accuracy.append(accuracy)
406                    B_Accuracy.append(b_accuracy)
407                    ROC_AUC.append(roc_auc)
408                    F1.append(f1)
409                    TIME.append(time.time() - start)
410                    if self.custom_metric is not None:
411                        custom_metric = self.custom_metric(y_test, y_pred)
412                        CUSTOM_METRIC.append(custom_metric)
413                    if self.verbose > 0:
414                        if self.custom_metric is not None:
415                            print(
416                                {
417                                    "Model": name,
418                                    "Accuracy": accuracy,
419                                    "Balanced Accuracy": b_accuracy,
420                                    "ROC AUC": roc_auc,
421                                    "F1 Score": f1,
422                                    self.custom_metric.__name__: custom_metric,
423                                    "Time taken": time.time() - start,
424                                }
425                            )
426                        else:
427                            print(
428                                {
429                                    "Model": name,
430                                    "Accuracy": accuracy,
431                                    "Balanced Accuracy": b_accuracy,
432                                    "ROC AUC": roc_auc,
433                                    "F1 Score": f1,
434                                    "Time taken": time.time() - start,
435                                }
436                            )
437                    if self.predictions:
438                        predictions[name] = y_pred
439                except Exception as exception:
440                    try:
441                        if self.ignore_warnings is False:
442                            print(name + " model failed to execute")
443                            print(exception)
444                    except Exception as exception:
445                        pass
446
447        else:  # if self.preprocess is False:
448
449            for name, model in tqdm(self.classifiers):  # do parallel exec
450                other_args = (
451                    {}
452                )  # use this trick for `random_state` too --> refactor
453                try:
454                    if (
455                        "n_jobs" in model().get_params().keys()
456                        and name.find("LogisticRegression") == -1
457                    ):
458                        other_args["n_jobs"] = self.n_jobs
459                except Exception:
460                    pass
461
462                start = time.time()
463                try:
464                    if "random_state" in model().get_params().keys():
465                        pipe = CustomClassifier(
466                            obj=model(
467                                random_state=self.random_state, **other_args
468                            ),
469                            n_hidden_features=self.n_hidden_features,
470                            activation_name=self.activation_name,
471                            a=self.a,
472                            nodes_sim=self.nodes_sim,
473                            bias=self.bias,
474                            dropout=self.dropout,
475                            direct_link=self.direct_link,
476                            n_clusters=self.n_clusters,
477                            cluster_encode=self.cluster_encode,
478                            type_clust=self.type_clust,
479                            type_scaling=self.type_scaling,
480                            col_sample=self.col_sample,
481                            row_sample=self.row_sample,
482                            seed=self.seed,
483                            backend=self.backend,
484                        )
485                    else:
486                        pipe = CustomClassifier(
487                            obj=model(**other_args),
488                            n_hidden_features=self.n_hidden_features,
489                            activation_name=self.activation_name,
490                            a=self.a,
491                            nodes_sim=self.nodes_sim,
492                            bias=self.bias,
493                            dropout=self.dropout,
494                            direct_link=self.direct_link,
495                            n_clusters=self.n_clusters,
496                            cluster_encode=self.cluster_encode,
497                            type_clust=self.type_clust,
498                            type_scaling=self.type_scaling,
499                            col_sample=self.col_sample,
500                            row_sample=self.row_sample,
501                            seed=self.seed,
502                            backend=self.backend,
503                        )
504
505                    pipe.fit(X_train, y_train)
506                    self.models[name] = pipe
507                    y_pred = pipe.predict(X_test)
508                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
509                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
510                    f1 = f1_score(y_test, y_pred, average="weighted")
511                    try:
512                        roc_auc = roc_auc_score(y_test, y_pred)
513                    except Exception as exception:
514                        roc_auc = None
515                        if self.ignore_warnings is False:
516                            print("ROC AUC couldn't be calculated for " + name)
517                            print(exception)
518                    names.append(name)
519                    Accuracy.append(accuracy)
520                    B_Accuracy.append(b_accuracy)
521                    ROC_AUC.append(roc_auc)
522                    F1.append(f1)
523                    TIME.append(time.time() - start)
524                    if self.custom_metric is not None:
525                        custom_metric = self.custom_metric(y_test, y_pred)
526                        CUSTOM_METRIC.append(custom_metric)
527                    if self.verbose > 0:
528                        if self.custom_metric is not None:
529                            print(
530                                {
531                                    "Model": name,
532                                    "Accuracy": accuracy,
533                                    "Balanced Accuracy": b_accuracy,
534                                    "ROC AUC": roc_auc,
535                                    "F1 Score": f1,
536                                    self.custom_metric.__name__: custom_metric,
537                                    "Time taken": time.time() - start,
538                                }
539                            )
540                        else:
541                            print(
542                                {
543                                    "Model": name,
544                                    "Accuracy": accuracy,
545                                    "Balanced Accuracy": b_accuracy,
546                                    "ROC AUC": roc_auc,
547                                    "F1 Score": f1,
548                                    "Time taken": time.time() - start,
549                                }
550                            )
551                    if self.predictions:
552                        predictions[name] = y_pred
553                except Exception as exception:
554                    try:
555                        if self.ignore_warnings is False:
556                            print(name + " model failed to execute")
557                            print(exception)
558                    except Exception as exception:
559                        pass
560
561        if self.custom_metric is None:
562            scores = pd.DataFrame(
563                {
564                    "Model": names,
565                    "Accuracy": Accuracy,
566                    "Balanced Accuracy": B_Accuracy,
567                    "ROC AUC": ROC_AUC,
568                    "F1 Score": F1,
569                    "Time Taken": TIME,
570                }
571            )
572        else:
573            scores = pd.DataFrame(
574                {
575                    "Model": names,
576                    "Accuracy": Accuracy,
577                    "Balanced Accuracy": B_Accuracy,
578                    "ROC AUC": ROC_AUC,
579                    "F1 Score": F1,
580                    self.custom_metric.__name__: CUSTOM_METRIC,
581                    "Time Taken": TIME,
582                }
583            )
584        scores = scores.sort_values(by=self.sort_by, ascending=False).set_index(
585            "Model"
586        )
587
588        if self.predictions:
589            predictions_df = pd.DataFrame.from_dict(predictions)
590        return scores, predictions_df if self.predictions is True else scores
591
592    def provide_models(self, X_train, X_test, y_train, y_test):
593        """Returns all the model objects trained. If fit hasn't been called yet,
594        then it's called to return the models.
595
596        Parameters:
597
598        X_train: array-like,
599            Training vectors, where rows is the number of samples
600            and columns is the number of features.
601
602        X_test: array-like,
603            Testing vectors, where rows is the number of samples
604            and columns is the number of features.
605
606        y_train: array-like,
607            Training vectors, where rows is the number of samples
608            and columns is the number of features.
609
610        y_test: array-like,
611            Testing vectors, where rows is the number of samples
612            and columns is the number of features.
613
614        Returns:
615
616            models: dict-object,
617                Returns a dictionary with each model's pipeline as value
618                and key = name of the model.
619        """
620        if len(self.models.keys()) == 0:
621            self.fit(X_train, X_test, y_train, y_test)
622
623        return self.models

Fitting -- almost -- all the classification algorithms with nnetsauce's CustomClassifier and returning their scores.

Parameters:

verbose: int, optional (default=0)
    Any positive number for verbosity.

ignore_warnings: bool, optional (default=True)
    When set to True, warnings related to algorithms that were not
    run are ignored.

custom_metric: function, optional (default=None)
    When function is provided, models are evaluated based on the
    custom evaluation metric provided.

predictions: bool, optional (default=False)
    When set to True, the predictions of all the models models are
    returned as data frame.

sort_by: string, optional (default='Accuracy')
    Sort models by a metric. Available options are 'Accuracy',
    'Balanced Accuracy', 'ROC AUC', 'F1 Score' or a custom metric
    identified by its name and provided by custom_metric.

random_state: int, optional (default=42)
    Reproducibiility seed.

estimators: list, optional (default='all')
    list of Estimators names or just 'all' for > 90
    classifiers (default='all')

preprocess: bool, preprocessing is done when set to True

n_jobs: int, when possible, run in parallel
    For now, only used by individual models that support it.

All the other parameters are the same as CustomClassifier's.

Examples:

import nnetsauce as ns
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    data = load_breast_cancer()
    X = data.data
    y= data.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2,
    random_state=123)
    clf = ns.LazyClassifier(verbose=0, ignore_warnings=True)
    models, predictions = clf.fit(X_train, X_test, y_train, y_test)
    model_dictionary = clf.provide_models(X_train,X_test,y_train,y_test)
    print(models)
    

def fit(self, X_train, X_test, y_train, y_test):
203    def fit(self, X_train, X_test, y_train, y_test):
204        """Fit classifiers to X_train and y_train, predict and score on X_test,
205        y_test.
206
207        Parameters:
208
209            X_train: array-like,
210                Training vectors, where rows is the number of samples
211                and columns is the number of features.
212
213            X_test: array-like,
214                Testing vectors, where rows is the number of samples
215                and columns is the number of features.
216
217            y_train: array-like,
218                Training vectors, where rows is the number of samples
219                and columns is the number of features.
220
221            y_test: array-like,
222                Testing vectors, where rows is the number of samples
223                and columns is the number of features.
224
225        Returns:
226
227            scores: Pandas DataFrame
228                Returns metrics of all the models in a Pandas DataFrame.
229
230            predictions: Pandas DataFrame
231                Returns predictions of all the models in a Pandas DataFrame.
232        """
233        Accuracy = []
234        B_Accuracy = []
235        ROC_AUC = []
236        F1 = []
237        names = []
238        TIME = []
239        predictions = {}
240
241        if self.custom_metric is not None:
242            CUSTOM_METRIC = []
243
244        if isinstance(X_train, np.ndarray):
245            X_train = pd.DataFrame(X_train)
246            X_test = pd.DataFrame(X_test)
247
248        numeric_features = X_train.select_dtypes(include=[np.number]).columns
249        categorical_features = X_train.select_dtypes(include=["object"]).columns
250
251        categorical_low, categorical_high = get_card_split(
252            X_train, categorical_features
253        )
254
255        if self.preprocess is True:
256
257            preprocessor = ColumnTransformer(
258                transformers=[
259                    ("numeric", numeric_transformer, numeric_features),
260                    (
261                        "categorical_low",
262                        categorical_transformer_low,
263                        categorical_low,
264                    ),
265                    (
266                        "categorical_high",
267                        categorical_transformer_high,
268                        categorical_high,
269                    ),
270                ]
271            )
272
273        if self.estimators == "all":
274
275            self.classifiers = (
276                CLASSIFIERS + MULTITASKCLASSIFIERS + SIMPLEMULTITASKCLASSIFIERS
277            )
278
279        else:  # list custom estimators, by their names
280
281            self.classifiers = (
282                [
283                    ("CustomClassifier(" + est[0] + ")", est[1])
284                    for est in all_estimators()
285                    if (
286                        issubclass(est[1], ClassifierMixin)
287                        and (est[0] in self.estimators)
288                    )
289                ]
290                + [
291                    (
292                        "MultitaskClassifier(" + est[0] + ")",
293                        partial(MultitaskClassifier, obj=est[1]()),
294                    )
295                    for est in all_estimators()
296                    if (
297                        issubclass(est[1], RegressorMixin)
298                        and (est[0] in self.estimators)
299                    )
300                ]
301                + [
302                    (
303                        "SimpleMultitaskClassifier(" + est[0] + ")",
304                        partial(SimpleMultitaskClassifier, obj=est[1]()),
305                    )
306                    for est in all_estimators()
307                    if (
308                        issubclass(est[1], RegressorMixin)
309                        and (est[0] in self.estimators)
310                    )
311                ]
312            )
313
314        if self.preprocess is True:
315
316            for name, model in tqdm(self.classifiers):  # do parallel exec
317
318                other_args = (
319                    {}
320                )  # use this trick for `random_state` too --> refactor
321                try:
322                    if (
323                        "n_jobs" in model().get_params().keys()
324                        and name.find("LogisticRegression") == -1
325                    ):
326                        other_args["n_jobs"] = self.n_jobs
327                except Exception:
328                    pass
329
330                start = time.time()
331
332                try:
333                    if "random_state" in model().get_params().keys():
334                        pipe = Pipeline(
335                            [
336                                ("preprocessor", preprocessor),
337                                (
338                                    "classifier",
339                                    CustomClassifier(
340                                        obj=model(
341                                            random_state=self.random_state,
342                                            **other_args
343                                        ),
344                                        n_hidden_features=self.n_hidden_features,
345                                        activation_name=self.activation_name,
346                                        a=self.a,
347                                        nodes_sim=self.nodes_sim,
348                                        bias=self.bias,
349                                        dropout=self.dropout,
350                                        direct_link=self.direct_link,
351                                        n_clusters=self.n_clusters,
352                                        cluster_encode=self.cluster_encode,
353                                        type_clust=self.type_clust,
354                                        type_scaling=self.type_scaling,
355                                        col_sample=self.col_sample,
356                                        row_sample=self.row_sample,
357                                        seed=self.seed,
358                                        backend=self.backend,
359                                    ),
360                                ),
361                            ]
362                        )
363                    else:
364                        pipe = Pipeline(
365                            [
366                                ("preprocessor", preprocessor),
367                                (
368                                    "classifier",
369                                    CustomClassifier(
370                                        obj=model(**other_args),
371                                        n_hidden_features=self.n_hidden_features,
372                                        activation_name=self.activation_name,
373                                        a=self.a,
374                                        nodes_sim=self.nodes_sim,
375                                        bias=self.bias,
376                                        dropout=self.dropout,
377                                        direct_link=self.direct_link,
378                                        n_clusters=self.n_clusters,
379                                        cluster_encode=self.cluster_encode,
380                                        type_clust=self.type_clust,
381                                        type_scaling=self.type_scaling,
382                                        col_sample=self.col_sample,
383                                        row_sample=self.row_sample,
384                                        seed=self.seed,
385                                        backend=self.backend,
386                                    ),
387                                ),
388                            ]
389                        )
390
391                    pipe.fit(X_train, y_train)
392                    self.models[name] = pipe
393                    y_pred = pipe.predict(X_test)
394                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
395                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
396                    f1 = f1_score(y_test, y_pred, average="weighted")
397                    try:
398                        roc_auc = roc_auc_score(y_test, y_pred)
399                    except Exception as exception:
400                        roc_auc = None
401                        if self.ignore_warnings is False:
402                            print("ROC AUC couldn't be calculated for " + name)
403                            print(exception)
404                    names.append(name)
405                    Accuracy.append(accuracy)
406                    B_Accuracy.append(b_accuracy)
407                    ROC_AUC.append(roc_auc)
408                    F1.append(f1)
409                    TIME.append(time.time() - start)
410                    if self.custom_metric is not None:
411                        custom_metric = self.custom_metric(y_test, y_pred)
412                        CUSTOM_METRIC.append(custom_metric)
413                    if self.verbose > 0:
414                        if self.custom_metric is not None:
415                            print(
416                                {
417                                    "Model": name,
418                                    "Accuracy": accuracy,
419                                    "Balanced Accuracy": b_accuracy,
420                                    "ROC AUC": roc_auc,
421                                    "F1 Score": f1,
422                                    self.custom_metric.__name__: custom_metric,
423                                    "Time taken": time.time() - start,
424                                }
425                            )
426                        else:
427                            print(
428                                {
429                                    "Model": name,
430                                    "Accuracy": accuracy,
431                                    "Balanced Accuracy": b_accuracy,
432                                    "ROC AUC": roc_auc,
433                                    "F1 Score": f1,
434                                    "Time taken": time.time() - start,
435                                }
436                            )
437                    if self.predictions:
438                        predictions[name] = y_pred
439                except Exception as exception:
440                    try:
441                        if self.ignore_warnings is False:
442                            print(name + " model failed to execute")
443                            print(exception)
444                    except Exception as exception:
445                        pass
446
447        else:  # if self.preprocess is False:
448
449            for name, model in tqdm(self.classifiers):  # do parallel exec
450                other_args = (
451                    {}
452                )  # use this trick for `random_state` too --> refactor
453                try:
454                    if (
455                        "n_jobs" in model().get_params().keys()
456                        and name.find("LogisticRegression") == -1
457                    ):
458                        other_args["n_jobs"] = self.n_jobs
459                except Exception:
460                    pass
461
462                start = time.time()
463                try:
464                    if "random_state" in model().get_params().keys():
465                        pipe = CustomClassifier(
466                            obj=model(
467                                random_state=self.random_state, **other_args
468                            ),
469                            n_hidden_features=self.n_hidden_features,
470                            activation_name=self.activation_name,
471                            a=self.a,
472                            nodes_sim=self.nodes_sim,
473                            bias=self.bias,
474                            dropout=self.dropout,
475                            direct_link=self.direct_link,
476                            n_clusters=self.n_clusters,
477                            cluster_encode=self.cluster_encode,
478                            type_clust=self.type_clust,
479                            type_scaling=self.type_scaling,
480                            col_sample=self.col_sample,
481                            row_sample=self.row_sample,
482                            seed=self.seed,
483                            backend=self.backend,
484                        )
485                    else:
486                        pipe = CustomClassifier(
487                            obj=model(**other_args),
488                            n_hidden_features=self.n_hidden_features,
489                            activation_name=self.activation_name,
490                            a=self.a,
491                            nodes_sim=self.nodes_sim,
492                            bias=self.bias,
493                            dropout=self.dropout,
494                            direct_link=self.direct_link,
495                            n_clusters=self.n_clusters,
496                            cluster_encode=self.cluster_encode,
497                            type_clust=self.type_clust,
498                            type_scaling=self.type_scaling,
499                            col_sample=self.col_sample,
500                            row_sample=self.row_sample,
501                            seed=self.seed,
502                            backend=self.backend,
503                        )
504
505                    pipe.fit(X_train, y_train)
506                    self.models[name] = pipe
507                    y_pred = pipe.predict(X_test)
508                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
509                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
510                    f1 = f1_score(y_test, y_pred, average="weighted")
511                    try:
512                        roc_auc = roc_auc_score(y_test, y_pred)
513                    except Exception as exception:
514                        roc_auc = None
515                        if self.ignore_warnings is False:
516                            print("ROC AUC couldn't be calculated for " + name)
517                            print(exception)
518                    names.append(name)
519                    Accuracy.append(accuracy)
520                    B_Accuracy.append(b_accuracy)
521                    ROC_AUC.append(roc_auc)
522                    F1.append(f1)
523                    TIME.append(time.time() - start)
524                    if self.custom_metric is not None:
525                        custom_metric = self.custom_metric(y_test, y_pred)
526                        CUSTOM_METRIC.append(custom_metric)
527                    if self.verbose > 0:
528                        if self.custom_metric is not None:
529                            print(
530                                {
531                                    "Model": name,
532                                    "Accuracy": accuracy,
533                                    "Balanced Accuracy": b_accuracy,
534                                    "ROC AUC": roc_auc,
535                                    "F1 Score": f1,
536                                    self.custom_metric.__name__: custom_metric,
537                                    "Time taken": time.time() - start,
538                                }
539                            )
540                        else:
541                            print(
542                                {
543                                    "Model": name,
544                                    "Accuracy": accuracy,
545                                    "Balanced Accuracy": b_accuracy,
546                                    "ROC AUC": roc_auc,
547                                    "F1 Score": f1,
548                                    "Time taken": time.time() - start,
549                                }
550                            )
551                    if self.predictions:
552                        predictions[name] = y_pred
553                except Exception as exception:
554                    try:
555                        if self.ignore_warnings is False:
556                            print(name + " model failed to execute")
557                            print(exception)
558                    except Exception as exception:
559                        pass
560
561        if self.custom_metric is None:
562            scores = pd.DataFrame(
563                {
564                    "Model": names,
565                    "Accuracy": Accuracy,
566                    "Balanced Accuracy": B_Accuracy,
567                    "ROC AUC": ROC_AUC,
568                    "F1 Score": F1,
569                    "Time Taken": TIME,
570                }
571            )
572        else:
573            scores = pd.DataFrame(
574                {
575                    "Model": names,
576                    "Accuracy": Accuracy,
577                    "Balanced Accuracy": B_Accuracy,
578                    "ROC AUC": ROC_AUC,
579                    "F1 Score": F1,
580                    self.custom_metric.__name__: CUSTOM_METRIC,
581                    "Time Taken": TIME,
582                }
583            )
584        scores = scores.sort_values(by=self.sort_by, ascending=False).set_index(
585            "Model"
586        )
587
588        if self.predictions:
589            predictions_df = pd.DataFrame.from_dict(predictions)
590        return scores, predictions_df if self.predictions is True else scores

Fit classifiers to X_train and y_train, predict and score on X_test, y_test.

Parameters:

X_train: array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test: array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

y_train: array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

y_test: array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

Returns:

scores: Pandas DataFrame
    Returns metrics of all the models in a Pandas DataFrame.

predictions: Pandas DataFrame
    Returns predictions of all the models in a Pandas DataFrame.
def provide_models(self, X_train, X_test, y_train, y_test):
592    def provide_models(self, X_train, X_test, y_train, y_test):
593        """Returns all the model objects trained. If fit hasn't been called yet,
594        then it's called to return the models.
595
596        Parameters:
597
598        X_train: array-like,
599            Training vectors, where rows is the number of samples
600            and columns is the number of features.
601
602        X_test: array-like,
603            Testing vectors, where rows is the number of samples
604            and columns is the number of features.
605
606        y_train: array-like,
607            Training vectors, where rows is the number of samples
608            and columns is the number of features.
609
610        y_test: array-like,
611            Testing vectors, where rows is the number of samples
612            and columns is the number of features.
613
614        Returns:
615
616            models: dict-object,
617                Returns a dictionary with each model's pipeline as value
618                and key = name of the model.
619        """
620        if len(self.models.keys()) == 0:
621            self.fit(X_train, X_test, y_train, y_test)
622
623        return self.models

Returns all the model objects trained. If fit hasn't been called yet, then it's called to return the models.

Parameters:

X_train: array-like, Training vectors, where rows is the number of samples and columns is the number of features.

X_test: array-like, Testing vectors, where rows is the number of samples and columns is the number of features.

y_train: array-like, Training vectors, where rows is the number of samples and columns is the number of features.

y_test: array-like, Testing vectors, where rows is the number of samples and columns is the number of features.

Returns:

models: dict-object,
    Returns a dictionary with each model's pipeline as value
    and key = name of the model.
class LazyRegressor(nnetsauce.custom.custom.Custom, sklearn.base.RegressorMixin):
 85class LazyRegressor(Custom, RegressorMixin):
 86    """
 87
 88    Fitting a collection of regression models using nnetsauce's CustomRegressor
 89
 90    Parameters:
 91
 92        verbose: int, optional (default=0)
 93            Any positive number for verbosity.
 94
 95        ignore_warnings: bool, optional (default=True)
 96            When set to True, the warning related to algorigms that are not able to run are ignored.
 97
 98        custom_metric: function, optional (default=None)
 99            When function is provided, models are evaluated based on the custom evaluation metric provided.
100
101        predictions: bool, optional (default=False)
102            When set to True, the predictions of all the models models are returned as dataframe.
103
104        sort_by: string, optional (default='Accuracy')
105            Sort models by a metric. Available options are 'Accuracy', 'Balanced Accuracy', 'ROC AUC', 'F1 Score'
106            or a custom metric identified by its name and provided by custom_metric.
107
108        random_state: int, optional (default=42)
109            Reproducibiility seed.
110
111        estimators: list, optional (default='all')
112            a list of Estimators names or just 'all' (default='all')
113
114        preprocess: bool
115            preprocessing is done when set to True
116
117        n_jobs : int, when possible, run in parallel
118            For now, only used by individual models that support it.
119
120        n_layers: int, optional (default=3)
121            Number of layers of CustomRegressors to be used.
122
123        All the other parameters are the same as CustomRegressor's.
124
125    Examples:
126        ```python
127        import nnetsauce as ns
128        from sklearn.datasets import load_diabetes
129        from sklearn.model_selection import train_test_split
130        data = load_diabetes()
131        X = data.data
132        y= data.target
133        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=123)
134        regr = ns.LazyRegressor(verbose=0, ignore_warnings=True)
135        models, predictions = clf.fit(X_train, X_test, y_train, y_test)
136        model_dictionary = clf.provide_models(X_train,X_test,y_train,y_test)
137        print(models)
138        ```
139
140    """
141
142    def __init__(
143        self,
144        verbose=0,
145        ignore_warnings=True,
146        custom_metric=None,
147        predictions=False,
148        random_state=42,
149        estimators="all",
150        preprocess=False,
151        n_jobs=None,
152        # CustomRegressor attributes
153        obj=None,
154        n_hidden_features=5,
155        activation_name="relu",
156        a=0.01,
157        nodes_sim="sobol",
158        bias=True,
159        dropout=0,
160        direct_link=True,
161        n_clusters=2,
162        cluster_encode=True,
163        type_clust="kmeans",
164        type_scaling=("std", "std", "std"),
165        col_sample=1,
166        row_sample=1,
167        seed=123,
168        backend="cpu",
169    ):
170        self.verbose = verbose
171        self.ignore_warnings = ignore_warnings
172        self.custom_metric = custom_metric
173        self.predictions = predictions
174        self.models = {}
175        self.random_state = random_state
176        self.estimators = estimators
177        self.preprocess = preprocess
178        self.n_jobs = n_jobs
179        super().__init__(
180            obj=obj,
181            n_hidden_features=n_hidden_features,
182            activation_name=activation_name,
183            a=a,
184            nodes_sim=nodes_sim,
185            bias=bias,
186            dropout=dropout,
187            direct_link=direct_link,
188            n_clusters=n_clusters,
189            cluster_encode=cluster_encode,
190            type_clust=type_clust,
191            type_scaling=type_scaling,
192            col_sample=col_sample,
193            row_sample=row_sample,
194            seed=seed,
195            backend=backend,
196        )
197
198    def fit(self, X_train, X_test, y_train, y_test):
199        """Fit Regression algorithms to X_train and y_train, predict and score on X_test, y_test.
200
201        Parameters:
202
203            X_train : array-like,
204                Training vectors, where rows is the number of samples
205                and columns is the number of features.
206
207            X_test : array-like,
208                Testing vectors, where rows is the number of samples
209                and columns is the number of features.
210
211            y_train : array-like,
212                Training vectors, where rows is the number of samples
213                and columns is the number of features.
214
215            y_test : array-like,
216                Testing vectors, where rows is the number of samples
217                and columns is the number of features.
218
219        Returns:
220
221        scores : Pandas DataFrame
222            Returns metrics of all the models in a Pandas DataFrame.
223
224        predictions : Pandas DataFrame
225            Returns predictions of all the models in a Pandas DataFrame.
226
227        """
228        R2 = []
229        ADJR2 = []
230        RMSE = []
231        # WIN = []
232        names = []
233        TIME = []
234        predictions = {}
235
236        if self.custom_metric:
237            CUSTOM_METRIC = []
238
239        if isinstance(X_train, np.ndarray):
240            X_train = pd.DataFrame(X_train)
241            X_test = pd.DataFrame(X_test)
242
243        numeric_features = X_train.select_dtypes(include=[np.number]).columns
244        categorical_features = X_train.select_dtypes(include=["object"]).columns
245
246        categorical_low, categorical_high = get_card_split(
247            X_train, categorical_features
248        )
249
250        if self.preprocess is True:
251            preprocessor = ColumnTransformer(
252                transformers=[
253                    ("numeric", numeric_transformer, numeric_features),
254                    (
255                        "categorical_low",
256                        categorical_transformer_low,
257                        categorical_low,
258                    ),
259                    (
260                        "categorical_high",
261                        categorical_transformer_high,
262                        categorical_high,
263                    ),
264                ]
265            )
266
267        if self.estimators == "all":
268            self.regressors = REGRESSORS
269        else:
270            self.regressors = [
271                ("CustomRegressor(" + est[0] + ")", est[1])
272                for est in all_estimators()
273                if (
274                    issubclass(est[1], RegressorMixin)
275                    and (est[0] in self.estimators)
276                )
277            ]
278
279        if self.preprocess is True:
280            for name, model in tqdm(self.regressors):  # do parallel exec
281                start = time.time()
282                try:
283                    if "random_state" in model().get_params().keys():
284                        pipe = Pipeline(
285                            steps=[
286                                ("preprocessor", preprocessor),
287                                (
288                                    "regressor",
289                                    CustomRegressor(
290                                        obj=model(
291                                            random_state=self.random_state
292                                        ),
293                                        n_hidden_features=self.n_hidden_features,
294                                        activation_name=self.activation_name,
295                                        a=self.a,
296                                        nodes_sim=self.nodes_sim,
297                                        bias=self.bias,
298                                        dropout=self.dropout,
299                                        direct_link=self.direct_link,
300                                        n_clusters=self.n_clusters,
301                                        cluster_encode=self.cluster_encode,
302                                        type_clust=self.type_clust,
303                                        type_scaling=self.type_scaling,
304                                        col_sample=self.col_sample,
305                                        row_sample=self.row_sample,
306                                        seed=self.seed,
307                                        backend=self.backend,
308                                    ),
309                                ),
310                            ]
311                        )
312                    else:
313                        pipe = Pipeline(
314                            steps=[
315                                ("preprocessor", preprocessor),
316                                (
317                                    "regressor",
318                                    CustomRegressor(
319                                        obj=model(),
320                                        n_hidden_features=self.n_hidden_features,
321                                        activation_name=self.activation_name,
322                                        a=self.a,
323                                        nodes_sim=self.nodes_sim,
324                                        bias=self.bias,
325                                        dropout=self.dropout,
326                                        direct_link=self.direct_link,
327                                        n_clusters=self.n_clusters,
328                                        cluster_encode=self.cluster_encode,
329                                        type_clust=self.type_clust,
330                                        type_scaling=self.type_scaling,
331                                        col_sample=self.col_sample,
332                                        row_sample=self.row_sample,
333                                        seed=self.seed,
334                                        backend=self.backend,
335                                    ),
336                                ),
337                            ]
338                        )
339
340                    pipe.fit(X_train, y_train)
341                    self.models[name] = pipe
342                    y_pred = pipe.predict(X_test)
343
344                    r_squared = r2_score(y_test, y_pred)
345                    adj_rsquared = adjusted_rsquared(
346                        r_squared, X_test.shape[0], X_test.shape[1]
347                    )
348                    rmse = mean_squared_error(y_test, y_pred, squared=False)
349
350                    names.append(name)
351                    R2.append(r_squared)
352                    ADJR2.append(adj_rsquared)
353                    RMSE.append(rmse)
354                    TIME.append(time.time() - start)
355
356                    if self.custom_metric:
357                        custom_metric = self.custom_metric(y_test, y_pred)
358                        CUSTOM_METRIC.append(custom_metric)
359
360                    if self.verbose > 0:
361                        scores_verbose = {
362                            "Model": name,
363                            "R-Squared": r_squared,
364                            "Adjusted R-Squared": adj_rsquared,
365                            "RMSE": rmse,
366                            "Time taken": time.time() - start,
367                        }
368
369                        if self.custom_metric:
370                            scores_verbose[self.custom_metric.__name__] = (
371                                custom_metric
372                            )
373
374                        print(scores_verbose)
375                    if self.predictions:
376                        predictions[name] = y_pred
377                except Exception as exception:
378                    if self.ignore_warnings is False:
379                        print(name + " model failed to execute")
380                        print(exception)
381
382        else:
383            for name, model in tqdm(self.regressors):  # do parallel exec
384                start = time.time()
385                try:
386                    if "random_state" in model().get_params().keys():
387                        pipe = CustomRegressor(
388                            obj=model(random_state=self.random_state),
389                            n_hidden_features=self.n_hidden_features,
390                            activation_name=self.activation_name,
391                            a=self.a,
392                            nodes_sim=self.nodes_sim,
393                            bias=self.bias,
394                            dropout=self.dropout,
395                            direct_link=self.direct_link,
396                            n_clusters=self.n_clusters,
397                            cluster_encode=self.cluster_encode,
398                            type_clust=self.type_clust,
399                            type_scaling=self.type_scaling,
400                            col_sample=self.col_sample,
401                            row_sample=self.row_sample,
402                            seed=self.seed,
403                            backend=self.backend,
404                        )
405                    else:
406                        pipe = CustomRegressor(
407                            obj=model(),
408                            n_hidden_features=self.n_hidden_features,
409                            activation_name=self.activation_name,
410                            a=self.a,
411                            nodes_sim=self.nodes_sim,
412                            bias=self.bias,
413                            dropout=self.dropout,
414                            direct_link=self.direct_link,
415                            n_clusters=self.n_clusters,
416                            cluster_encode=self.cluster_encode,
417                            type_clust=self.type_clust,
418                            type_scaling=self.type_scaling,
419                            col_sample=self.col_sample,
420                            row_sample=self.row_sample,
421                            seed=self.seed,
422                            backend=self.backend,
423                        )
424
425                    pipe.fit(X_train, y_train)
426                    self.models[name] = pipe
427                    y_pred = pipe.predict(X_test)
428
429                    r_squared = r2_score(y_test, y_pred)
430                    adj_rsquared = adjusted_rsquared(
431                        r_squared, X_test.shape[0], X_test.shape[1]
432                    )
433                    rmse = mean_squared_error(y_test, y_pred, squared=False)
434
435                    names.append(name)
436                    R2.append(r_squared)
437                    ADJR2.append(adj_rsquared)
438                    RMSE.append(rmse)
439                    TIME.append(time.time() - start)
440
441                    if self.custom_metric:
442                        custom_metric = self.custom_metric(y_test, y_pred)
443                        CUSTOM_METRIC.append(custom_metric)
444
445                    if self.verbose > 0:
446                        scores_verbose = {
447                            "Model": name,
448                            "R-Squared": r_squared,
449                            "Adjusted R-Squared": adj_rsquared,
450                            "RMSE": rmse,
451                            "Time taken": time.time() - start,
452                        }
453
454                        if self.custom_metric:
455                            scores_verbose[self.custom_metric.__name__] = (
456                                custom_metric
457                            )
458
459                        print(scores_verbose)
460                    if self.predictions:
461                        predictions[name] = y_pred
462                except Exception as exception:
463                    if self.ignore_warnings is False:
464                        print(name + " model failed to execute")
465                        print(exception)
466
467        scores = {
468            "Model": names,
469            "Adjusted R-Squared": ADJR2,
470            "R-Squared": R2,
471            "RMSE": RMSE,
472            "Time Taken": TIME,
473        }
474
475        if self.custom_metric:
476            scores[self.custom_metric.__name__] = CUSTOM_METRIC
477
478        scores = pd.DataFrame(scores)
479        scores = scores.sort_values(by="RMSE", ascending=True).set_index(
480            "Model"
481        )
482
483        if self.predictions:
484            predictions_df = pd.DataFrame.from_dict(predictions)
485        return scores, predictions_df if self.predictions is True else scores
486
487    def provide_models(self, X_train, X_test, y_train, y_test):
488        """
489        This function returns all the model objects trained in fit function.
490        If fit is not called already, then we call fit and then return the models.
491        Parameters
492        ----------
493        X_train : array-like,
494            Training vectors, where rows is the number of samples
495            and columns is the number of features.
496        X_test : array-like,
497            Testing vectors, where rows is the number of samples
498            and columns is the number of features.
499        y_train : array-like,
500            Training vectors, where rows is the number of samples
501            and columns is the number of features.
502        y_test : array-like,
503            Testing vectors, where rows is the number of samples
504            and columns is the number of features.
505        Returns
506        -------
507        models: dict-object,
508            Returns a dictionary with each model pipeline as value
509            with key as name of models.
510        """
511        if len(self.models.keys()) == 0:
512            self.fit(X_train, X_test, y_train, y_test)
513
514        return self.models

Fitting a collection of regression models using nnetsauce's CustomRegressor

Parameters:

verbose: int, optional (default=0)
    Any positive number for verbosity.

ignore_warnings: bool, optional (default=True)
    When set to True, the warning related to algorigms that are not able to run are ignored.

custom_metric: function, optional (default=None)
    When function is provided, models are evaluated based on the custom evaluation metric provided.

predictions: bool, optional (default=False)
    When set to True, the predictions of all the models models are returned as dataframe.

sort_by: string, optional (default='Accuracy')
    Sort models by a metric. Available options are 'Accuracy', 'Balanced Accuracy', 'ROC AUC', 'F1 Score'
    or a custom metric identified by its name and provided by custom_metric.

random_state: int, optional (default=42)
    Reproducibiility seed.

estimators: list, optional (default='all')
    a list of Estimators names or just 'all' (default='all')

preprocess: bool
    preprocessing is done when set to True

n_jobs : int, when possible, run in parallel
    For now, only used by individual models that support it.

n_layers: int, optional (default=3)
    Number of layers of CustomRegressors to be used.

All the other parameters are the same as CustomRegressor's.

Examples:

import nnetsauce as ns
    from sklearn.datasets import load_diabetes
    from sklearn.model_selection import train_test_split
    data = load_diabetes()
    X = data.data
    y= data.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=123)
    regr = ns.LazyRegressor(verbose=0, ignore_warnings=True)
    models, predictions = clf.fit(X_train, X_test, y_train, y_test)
    model_dictionary = clf.provide_models(X_train,X_test,y_train,y_test)
    print(models)
    

def fit(self, X_train, X_test, y_train, y_test):
198    def fit(self, X_train, X_test, y_train, y_test):
199        """Fit Regression algorithms to X_train and y_train, predict and score on X_test, y_test.
200
201        Parameters:
202
203            X_train : array-like,
204                Training vectors, where rows is the number of samples
205                and columns is the number of features.
206
207            X_test : array-like,
208                Testing vectors, where rows is the number of samples
209                and columns is the number of features.
210
211            y_train : array-like,
212                Training vectors, where rows is the number of samples
213                and columns is the number of features.
214
215            y_test : array-like,
216                Testing vectors, where rows is the number of samples
217                and columns is the number of features.
218
219        Returns:
220
221        scores : Pandas DataFrame
222            Returns metrics of all the models in a Pandas DataFrame.
223
224        predictions : Pandas DataFrame
225            Returns predictions of all the models in a Pandas DataFrame.
226
227        """
228        R2 = []
229        ADJR2 = []
230        RMSE = []
231        # WIN = []
232        names = []
233        TIME = []
234        predictions = {}
235
236        if self.custom_metric:
237            CUSTOM_METRIC = []
238
239        if isinstance(X_train, np.ndarray):
240            X_train = pd.DataFrame(X_train)
241            X_test = pd.DataFrame(X_test)
242
243        numeric_features = X_train.select_dtypes(include=[np.number]).columns
244        categorical_features = X_train.select_dtypes(include=["object"]).columns
245
246        categorical_low, categorical_high = get_card_split(
247            X_train, categorical_features
248        )
249
250        if self.preprocess is True:
251            preprocessor = ColumnTransformer(
252                transformers=[
253                    ("numeric", numeric_transformer, numeric_features),
254                    (
255                        "categorical_low",
256                        categorical_transformer_low,
257                        categorical_low,
258                    ),
259                    (
260                        "categorical_high",
261                        categorical_transformer_high,
262                        categorical_high,
263                    ),
264                ]
265            )
266
267        if self.estimators == "all":
268            self.regressors = REGRESSORS
269        else:
270            self.regressors = [
271                ("CustomRegressor(" + est[0] + ")", est[1])
272                for est in all_estimators()
273                if (
274                    issubclass(est[1], RegressorMixin)
275                    and (est[0] in self.estimators)
276                )
277            ]
278
279        if self.preprocess is True:
280            for name, model in tqdm(self.regressors):  # do parallel exec
281                start = time.time()
282                try:
283                    if "random_state" in model().get_params().keys():
284                        pipe = Pipeline(
285                            steps=[
286                                ("preprocessor", preprocessor),
287                                (
288                                    "regressor",
289                                    CustomRegressor(
290                                        obj=model(
291                                            random_state=self.random_state
292                                        ),
293                                        n_hidden_features=self.n_hidden_features,
294                                        activation_name=self.activation_name,
295                                        a=self.a,
296                                        nodes_sim=self.nodes_sim,
297                                        bias=self.bias,
298                                        dropout=self.dropout,
299                                        direct_link=self.direct_link,
300                                        n_clusters=self.n_clusters,
301                                        cluster_encode=self.cluster_encode,
302                                        type_clust=self.type_clust,
303                                        type_scaling=self.type_scaling,
304                                        col_sample=self.col_sample,
305                                        row_sample=self.row_sample,
306                                        seed=self.seed,
307                                        backend=self.backend,
308                                    ),
309                                ),
310                            ]
311                        )
312                    else:
313                        pipe = Pipeline(
314                            steps=[
315                                ("preprocessor", preprocessor),
316                                (
317                                    "regressor",
318                                    CustomRegressor(
319                                        obj=model(),
320                                        n_hidden_features=self.n_hidden_features,
321                                        activation_name=self.activation_name,
322                                        a=self.a,
323                                        nodes_sim=self.nodes_sim,
324                                        bias=self.bias,
325                                        dropout=self.dropout,
326                                        direct_link=self.direct_link,
327                                        n_clusters=self.n_clusters,
328                                        cluster_encode=self.cluster_encode,
329                                        type_clust=self.type_clust,
330                                        type_scaling=self.type_scaling,
331                                        col_sample=self.col_sample,
332                                        row_sample=self.row_sample,
333                                        seed=self.seed,
334                                        backend=self.backend,
335                                    ),
336                                ),
337                            ]
338                        )
339
340                    pipe.fit(X_train, y_train)
341                    self.models[name] = pipe
342                    y_pred = pipe.predict(X_test)
343
344                    r_squared = r2_score(y_test, y_pred)
345                    adj_rsquared = adjusted_rsquared(
346                        r_squared, X_test.shape[0], X_test.shape[1]
347                    )
348                    rmse = mean_squared_error(y_test, y_pred, squared=False)
349
350                    names.append(name)
351                    R2.append(r_squared)
352                    ADJR2.append(adj_rsquared)
353                    RMSE.append(rmse)
354                    TIME.append(time.time() - start)
355
356                    if self.custom_metric:
357                        custom_metric = self.custom_metric(y_test, y_pred)
358                        CUSTOM_METRIC.append(custom_metric)
359
360                    if self.verbose > 0:
361                        scores_verbose = {
362                            "Model": name,
363                            "R-Squared": r_squared,
364                            "Adjusted R-Squared": adj_rsquared,
365                            "RMSE": rmse,
366                            "Time taken": time.time() - start,
367                        }
368
369                        if self.custom_metric:
370                            scores_verbose[self.custom_metric.__name__] = (
371                                custom_metric
372                            )
373
374                        print(scores_verbose)
375                    if self.predictions:
376                        predictions[name] = y_pred
377                except Exception as exception:
378                    if self.ignore_warnings is False:
379                        print(name + " model failed to execute")
380                        print(exception)
381
382        else:
383            for name, model in tqdm(self.regressors):  # do parallel exec
384                start = time.time()
385                try:
386                    if "random_state" in model().get_params().keys():
387                        pipe = CustomRegressor(
388                            obj=model(random_state=self.random_state),
389                            n_hidden_features=self.n_hidden_features,
390                            activation_name=self.activation_name,
391                            a=self.a,
392                            nodes_sim=self.nodes_sim,
393                            bias=self.bias,
394                            dropout=self.dropout,
395                            direct_link=self.direct_link,
396                            n_clusters=self.n_clusters,
397                            cluster_encode=self.cluster_encode,
398                            type_clust=self.type_clust,
399                            type_scaling=self.type_scaling,
400                            col_sample=self.col_sample,
401                            row_sample=self.row_sample,
402                            seed=self.seed,
403                            backend=self.backend,
404                        )
405                    else:
406                        pipe = CustomRegressor(
407                            obj=model(),
408                            n_hidden_features=self.n_hidden_features,
409                            activation_name=self.activation_name,
410                            a=self.a,
411                            nodes_sim=self.nodes_sim,
412                            bias=self.bias,
413                            dropout=self.dropout,
414                            direct_link=self.direct_link,
415                            n_clusters=self.n_clusters,
416                            cluster_encode=self.cluster_encode,
417                            type_clust=self.type_clust,
418                            type_scaling=self.type_scaling,
419                            col_sample=self.col_sample,
420                            row_sample=self.row_sample,
421                            seed=self.seed,
422                            backend=self.backend,
423                        )
424
425                    pipe.fit(X_train, y_train)
426                    self.models[name] = pipe
427                    y_pred = pipe.predict(X_test)
428
429                    r_squared = r2_score(y_test, y_pred)
430                    adj_rsquared = adjusted_rsquared(
431                        r_squared, X_test.shape[0], X_test.shape[1]
432                    )
433                    rmse = mean_squared_error(y_test, y_pred, squared=False)
434
435                    names.append(name)
436                    R2.append(r_squared)
437                    ADJR2.append(adj_rsquared)
438                    RMSE.append(rmse)
439                    TIME.append(time.time() - start)
440
441                    if self.custom_metric:
442                        custom_metric = self.custom_metric(y_test, y_pred)
443                        CUSTOM_METRIC.append(custom_metric)
444
445                    if self.verbose > 0:
446                        scores_verbose = {
447                            "Model": name,
448                            "R-Squared": r_squared,
449                            "Adjusted R-Squared": adj_rsquared,
450                            "RMSE": rmse,
451                            "Time taken": time.time() - start,
452                        }
453
454                        if self.custom_metric:
455                            scores_verbose[self.custom_metric.__name__] = (
456                                custom_metric
457                            )
458
459                        print(scores_verbose)
460                    if self.predictions:
461                        predictions[name] = y_pred
462                except Exception as exception:
463                    if self.ignore_warnings is False:
464                        print(name + " model failed to execute")
465                        print(exception)
466
467        scores = {
468            "Model": names,
469            "Adjusted R-Squared": ADJR2,
470            "R-Squared": R2,
471            "RMSE": RMSE,
472            "Time Taken": TIME,
473        }
474
475        if self.custom_metric:
476            scores[self.custom_metric.__name__] = CUSTOM_METRIC
477
478        scores = pd.DataFrame(scores)
479        scores = scores.sort_values(by="RMSE", ascending=True).set_index(
480            "Model"
481        )
482
483        if self.predictions:
484            predictions_df = pd.DataFrame.from_dict(predictions)
485        return scores, predictions_df if self.predictions is True else scores

Fit Regression algorithms to X_train and y_train, predict and score on X_test, y_test.

Parameters:

X_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

y_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

y_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

Returns:

scores : Pandas DataFrame Returns metrics of all the models in a Pandas DataFrame.

predictions : Pandas DataFrame Returns predictions of all the models in a Pandas DataFrame.

def provide_models(self, X_train, X_test, y_train, y_test):
487    def provide_models(self, X_train, X_test, y_train, y_test):
488        """
489        This function returns all the model objects trained in fit function.
490        If fit is not called already, then we call fit and then return the models.
491        Parameters
492        ----------
493        X_train : array-like,
494            Training vectors, where rows is the number of samples
495            and columns is the number of features.
496        X_test : array-like,
497            Testing vectors, where rows is the number of samples
498            and columns is the number of features.
499        y_train : array-like,
500            Training vectors, where rows is the number of samples
501            and columns is the number of features.
502        y_test : array-like,
503            Testing vectors, where rows is the number of samples
504            and columns is the number of features.
505        Returns
506        -------
507        models: dict-object,
508            Returns a dictionary with each model pipeline as value
509            with key as name of models.
510        """
511        if len(self.models.keys()) == 0:
512            self.fit(X_train, X_test, y_train, y_test)
513
514        return self.models

This function returns all the model objects trained in fit function. If fit is not called already, then we call fit and then return the models.

Parameters

X_train : array-like, Training vectors, where rows is the number of samples and columns is the number of features. X_test : array-like, Testing vectors, where rows is the number of samples and columns is the number of features. y_train : array-like, Training vectors, where rows is the number of samples and columns is the number of features. y_test : array-like, Testing vectors, where rows is the number of samples and columns is the number of features.

Returns

models: dict-object, Returns a dictionary with each model pipeline as value with key as name of models.

class LazyDeepClassifier(nnetsauce.custom.custom.Custom, sklearn.base.ClassifierMixin):
 84class LazyDeepClassifier(Custom, ClassifierMixin):
 85    """
 86
 87    Fitting -- almost -- all the classification algorithms with layers of
 88    nnetsauce's CustomClassifier and returning their scores.
 89
 90    Parameters:
 91
 92        verbose: int, optional (default=0)
 93            Any positive number for verbosity.
 94
 95        ignore_warnings: bool, optional (default=True)
 96            When set to True, the warning related to algorigms that are not
 97            able to run are ignored.
 98
 99        custom_metric: function, optional (default=None)
100            When function is provided, models are evaluated based on the custom
101              evaluation metric provided.
102
103        predictions: bool, optional (default=False)
104            When set to True, the predictions of all the models models are
105            returned as data frame.
106
107        sort_by: string, optional (default='Accuracy')
108            Sort models by a metric. Available options are 'Accuracy',
109            'Balanced Accuracy', 'ROC AUC', 'F1 Score' or a custom metric
110            identified by its name and provided by custom_metric.
111
112        random_state: int, optional (default=42)
113            Reproducibiility seed.
114
115        estimators: list, optional (default='all')
116            list of Estimators names or just 'all' for > 90 classifiers
117            (default='all')
118
119        preprocess: bool, preprocessing is done when set to True
120
121        n_jobs: int, when possible, run in parallel
122            For now, only used by individual models that support it.
123
124        n_layers: int, optional (default=3)
125            Number of layers of CustomClassifiers to be used.
126
127        All the other parameters are the same as CustomClassifier's.
128
129
130    Examples
131
132        ```python
133        import nnetsauce as ns
134        from sklearn.datasets import load_breast_cancer
135        from sklearn.model_selection import train_test_split
136        data = load_breast_cancer()
137        X = data.data
138        y= data.target
139        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2,
140            random_state=123)
141        clf = ns.LazyDeepClassifier(verbose=0, ignore_warnings=True, custom_metric=None)
142        models, predictions = clf.fit(X_train, X_test, y_train, y_test)
143        model_dictionary = clf.provide_models(X_train,X_test,y_train,y_test)
144        print(models)
145        ```
146
147    """
148
149    def __init__(
150        self,
151        verbose=0,
152        ignore_warnings=True,
153        custom_metric=None,
154        predictions=False,
155        sort_by="Accuracy",
156        random_state=42,
157        estimators="all",
158        preprocess=False,
159        n_jobs=None,
160        # Defining depth
161        n_layers=3,
162        # CustomClassifier attributes
163        obj=None,
164        n_hidden_features=5,
165        activation_name="relu",
166        a=0.01,
167        nodes_sim="sobol",
168        bias=True,
169        dropout=0,
170        direct_link=True,
171        n_clusters=2,
172        cluster_encode=True,
173        type_clust="kmeans",
174        type_scaling=("std", "std", "std"),
175        col_sample=1,
176        row_sample=1,
177        seed=123,
178        backend="cpu",
179    ):
180        self.verbose = verbose
181        self.ignore_warnings = ignore_warnings
182        self.custom_metric = custom_metric
183        self.predictions = predictions
184        self.sort_by = sort_by
185        self.models = {}
186        self.random_state = random_state
187        self.estimators = estimators
188        self.preprocess = preprocess
189        self.n_layers = n_layers - 1
190        self.n_jobs = n_jobs
191        super().__init__(
192            obj=obj,
193            n_hidden_features=n_hidden_features,
194            activation_name=activation_name,
195            a=a,
196            nodes_sim=nodes_sim,
197            bias=bias,
198            dropout=dropout,
199            direct_link=direct_link,
200            n_clusters=n_clusters,
201            cluster_encode=cluster_encode,
202            type_clust=type_clust,
203            type_scaling=type_scaling,
204            col_sample=col_sample,
205            row_sample=row_sample,
206            seed=seed,
207            backend=backend,
208        )
209
210    def fit(self, X_train, X_test, y_train, y_test):
211        """Fit classifiers to X_train and y_train, predict and score on X_test,
212        y_test.
213
214        Parameters:
215
216            X_train: array-like,
217                Training vectors, where rows is the number of samples
218                and columns is the number of features.
219
220            X_test: array-like,
221                Testing vectors, where rows is the number of samples
222                and columns is the number of features.
223
224            y_train: array-like,
225                Training vectors, where rows is the number of samples
226                and columns is the number of features.
227
228            y_test: array-like,
229                Testing vectors, where rows is the number of samples
230                and columns is the number of features.
231
232        Returns:
233
234            scores: Pandas DataFrame
235                Returns metrics of all the models in a Pandas DataFrame.
236
237            predictions: Pandas DataFrame
238                Returns predictions of all the models in a Pandas DataFrame.
239        """
240        Accuracy = []
241        B_Accuracy = []
242        ROC_AUC = []
243        F1 = []
244        names = []
245        TIME = []
246        predictions = {}
247
248        if self.custom_metric is not None:
249            CUSTOM_METRIC = []
250
251        if isinstance(X_train, np.ndarray):
252            X_train = pd.DataFrame(X_train)
253            X_test = pd.DataFrame(X_test)
254
255        numeric_features = X_train.select_dtypes(include=[np.number]).columns
256        categorical_features = X_train.select_dtypes(include=["object"]).columns
257
258        categorical_low, categorical_high = get_card_split(
259            X_train, categorical_features
260        )
261
262        if self.preprocess is True:
263            preprocessor = ColumnTransformer(
264                transformers=[
265                    ("numeric", numeric_transformer, numeric_features),
266                    (
267                        "categorical_low",
268                        categorical_transformer_low,
269                        categorical_low,
270                    ),
271                    (
272                        "categorical_high",
273                        categorical_transformer_high,
274                        categorical_high,
275                    ),
276                ]
277            )
278
279        if self.estimators == "all":
280            self.classifiers = [
281                item
282                for sublist in [
283                    DEEPCLASSIFIERS,
284                    DEEPMULTITASKCLASSIFIERS,
285                    DEEPSIMPLEMULTITASKCLASSIFIERS,
286                ]
287                for item in sublist
288            ]
289        else:
290            self.classifiers = (
291                [
292                    ("DeepCustomClassifier(" + est[0] + ")", est[1])
293                    for est in all_estimators()
294                    if (
295                        issubclass(est[1], ClassifierMixin)
296                        and (est[0] in self.estimators)
297                    )
298                ]
299                + [
300                    (
301                        "DeepMultitaskClassifier(" + est[0] + ")",
302                        partial(MultitaskClassifier, obj=est[1]()),
303                    )
304                    for est in all_estimators()
305                    if (
306                        issubclass(est[1], RegressorMixin)
307                        and (est[0] in self.estimators)
308                    )
309                ]
310                + [
311                    (
312                        "DeepSimpleMultitaskClassifier(" + est[0] + ")",
313                        partial(SimpleMultitaskClassifier, obj=est[1]()),
314                    )
315                    for est in all_estimators()
316                    if (
317                        issubclass(est[1], RegressorMixin)
318                        and (est[0] in self.estimators)
319                    )
320                ]
321            )
322
323        if self.preprocess is True:
324
325            for name, model in tqdm(self.classifiers):  # do parallel exec
326
327                other_args = (
328                    {}
329                )  # use this trick for `random_state` too --> refactor
330                try:
331                    if (
332                        "n_jobs" in model().get_params().keys()
333                        and name.find("LogisticRegression") == -1
334                    ):
335                        other_args["n_jobs"] = self.n_jobs
336                except Exception:
337                    pass
338
339                start = time.time()
340
341                try:
342                    if "random_state" in model().get_params().keys():
343                        layer_clf = CustomClassifier(
344                            obj=model(random_state=self.random_state),
345                            n_hidden_features=self.n_hidden_features,
346                            activation_name=self.activation_name,
347                            a=self.a,
348                            nodes_sim=self.nodes_sim,
349                            bias=self.bias,
350                            dropout=self.dropout,
351                            direct_link=self.direct_link,
352                            n_clusters=self.n_clusters,
353                            cluster_encode=self.cluster_encode,
354                            type_clust=self.type_clust,
355                            type_scaling=self.type_scaling,
356                            col_sample=self.col_sample,
357                            row_sample=self.row_sample,
358                            seed=self.seed,
359                            backend=self.backend,
360                        )
361
362                    else:
363                        layer_clf = CustomClassifier(
364                            obj=model(),
365                            n_hidden_features=self.n_hidden_features,
366                            activation_name=self.activation_name,
367                            a=self.a,
368                            nodes_sim=self.nodes_sim,
369                            bias=self.bias,
370                            dropout=self.dropout,
371                            direct_link=self.direct_link,
372                            n_clusters=self.n_clusters,
373                            cluster_encode=self.cluster_encode,
374                            type_clust=self.type_clust,
375                            type_scaling=self.type_scaling,
376                            col_sample=self.col_sample,
377                            row_sample=self.row_sample,
378                            seed=self.seed,
379                            backend=self.backend,
380                        )
381
382                    layer_clf.fit(X_train, y_train)
383
384                    for _ in range(self.n_layers):
385                        layer_clf = deepcopy(
386                            CustomClassifier(
387                                obj=layer_clf,
388                                n_hidden_features=self.n_hidden_features,
389                                activation_name=self.activation_name,
390                                a=self.a,
391                                nodes_sim=self.nodes_sim,
392                                bias=self.bias,
393                                dropout=self.dropout,
394                                direct_link=self.direct_link,
395                                n_clusters=self.n_clusters,
396                                cluster_encode=self.cluster_encode,
397                                type_clust=self.type_clust,
398                                type_scaling=self.type_scaling,
399                                col_sample=self.col_sample,
400                                row_sample=self.row_sample,
401                                seed=self.seed,
402                                backend=self.backend,
403                            )
404                        )
405
406                    pipe = Pipeline(
407                        [
408                            ("preprocessor", preprocessor),
409                            ("classifier", layer_clf),
410                        ]
411                    )
412
413                    pipe.fit(X_train, y_train)
414                    self.models[name] = pipe
415                    y_pred = pipe.predict(X_test)
416                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
417                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
418                    f1 = f1_score(y_test, y_pred, average="weighted")
419                    try:
420                        roc_auc = roc_auc_score(y_test, y_pred)
421                    except Exception as exception:
422                        roc_auc = None
423                        if self.ignore_warnings is False:
424                            print("ROC AUC couldn't be calculated for " + name)
425                            print(exception)
426                    names.append(name)
427                    Accuracy.append(accuracy)
428                    B_Accuracy.append(b_accuracy)
429                    ROC_AUC.append(roc_auc)
430                    F1.append(f1)
431                    TIME.append(time.time() - start)
432                    if self.custom_metric is not None:
433                        custom_metric = self.custom_metric(y_test, y_pred)
434                        CUSTOM_METRIC.append(custom_metric)
435                    if self.verbose > 0:
436                        if self.custom_metric is not None:
437                            print(
438                                {
439                                    "Model": name,
440                                    "Accuracy": accuracy,
441                                    "Balanced Accuracy": b_accuracy,
442                                    "ROC AUC": roc_auc,
443                                    "F1 Score": f1,
444                                    self.custom_metric.__name__: custom_metric,
445                                    "Time taken": time.time() - start,
446                                }
447                            )
448                        else:
449                            print(
450                                {
451                                    "Model": name,
452                                    "Accuracy": accuracy,
453                                    "Balanced Accuracy": b_accuracy,
454                                    "ROC AUC": roc_auc,
455                                    "F1 Score": f1,
456                                    "Time taken": time.time() - start,
457                                }
458                            )
459                    if self.predictions:
460                        predictions[name] = y_pred
461                except Exception as exception:
462                    if self.ignore_warnings is False:
463                        print(name + " model failed to execute")
464                        print(exception)
465
466        else:  # no preprocessing
467
468            for name, model in tqdm(self.classifiers):  # do parallel exec
469                start = time.time()
470                try:
471                    if "random_state" in model().get_params().keys():
472                        layer_clf = CustomClassifier(
473                            obj=model(random_state=self.random_state),
474                            n_hidden_features=self.n_hidden_features,
475                            activation_name=self.activation_name,
476                            a=self.a,
477                            nodes_sim=self.nodes_sim,
478                            bias=self.bias,
479                            dropout=self.dropout,
480                            direct_link=self.direct_link,
481                            n_clusters=self.n_clusters,
482                            cluster_encode=self.cluster_encode,
483                            type_clust=self.type_clust,
484                            type_scaling=self.type_scaling,
485                            col_sample=self.col_sample,
486                            row_sample=self.row_sample,
487                            seed=self.seed,
488                            backend=self.backend,
489                        )
490
491                    else:
492                        layer_clf = CustomClassifier(
493                            obj=model(),
494                            n_hidden_features=self.n_hidden_features,
495                            activation_name=self.activation_name,
496                            a=self.a,
497                            nodes_sim=self.nodes_sim,
498                            bias=self.bias,
499                            dropout=self.dropout,
500                            direct_link=self.direct_link,
501                            n_clusters=self.n_clusters,
502                            cluster_encode=self.cluster_encode,
503                            type_clust=self.type_clust,
504                            type_scaling=self.type_scaling,
505                            col_sample=self.col_sample,
506                            row_sample=self.row_sample,
507                            seed=self.seed,
508                            backend=self.backend,
509                        )
510
511                    layer_clf.fit(X_train, y_train)
512
513                    for _ in range(self.n_layers):
514                        layer_clf = deepcopy(
515                            CustomClassifier(
516                                obj=layer_clf,
517                                n_hidden_features=self.n_hidden_features,
518                                activation_name=self.activation_name,
519                                a=self.a,
520                                nodes_sim=self.nodes_sim,
521                                bias=self.bias,
522                                dropout=self.dropout,
523                                direct_link=self.direct_link,
524                                n_clusters=self.n_clusters,
525                                cluster_encode=self.cluster_encode,
526                                type_clust=self.type_clust,
527                                type_scaling=self.type_scaling,
528                                col_sample=self.col_sample,
529                                row_sample=self.row_sample,
530                                seed=self.seed,
531                                backend=self.backend,
532                            )
533                        )
534
535                        # layer_clf.fit(X_train, y_train)
536
537                    layer_clf.fit(X_train, y_train)
538
539                    self.models[name] = layer_clf
540                    y_pred = layer_clf.predict(X_test)
541                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
542                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
543                    f1 = f1_score(y_test, y_pred, average="weighted")
544                    try:
545                        roc_auc = roc_auc_score(y_test, y_pred)
546                    except Exception as exception:
547                        roc_auc = None
548                        if self.ignore_warnings is False:
549                            print("ROC AUC couldn't be calculated for " + name)
550                            print(exception)
551                    names.append(name)
552                    Accuracy.append(accuracy)
553                    B_Accuracy.append(b_accuracy)
554                    ROC_AUC.append(roc_auc)
555                    F1.append(f1)
556                    TIME.append(time.time() - start)
557                    if self.custom_metric is not None:
558                        custom_metric = self.custom_metric(y_test, y_pred)
559                        CUSTOM_METRIC.append(custom_metric)
560                    if self.verbose > 0:
561                        if self.custom_metric is not None:
562                            print(
563                                {
564                                    "Model": name,
565                                    "Accuracy": accuracy,
566                                    "Balanced Accuracy": b_accuracy,
567                                    "ROC AUC": roc_auc,
568                                    "F1 Score": f1,
569                                    self.custom_metric.__name__: custom_metric,
570                                    "Time taken": time.time() - start,
571                                }
572                            )
573                        else:
574                            print(
575                                {
576                                    "Model": name,
577                                    "Accuracy": accuracy,
578                                    "Balanced Accuracy": b_accuracy,
579                                    "ROC AUC": roc_auc,
580                                    "F1 Score": f1,
581                                    "Time taken": time.time() - start,
582                                }
583                            )
584                    if self.predictions:
585                        predictions[name] = y_pred
586                except Exception as exception:
587                    if self.ignore_warnings is False:
588                        print(name + " model failed to execute")
589                        print(exception)
590
591        if self.custom_metric is None:
592            scores = pd.DataFrame(
593                {
594                    "Model": names,
595                    "Accuracy": Accuracy,
596                    "Balanced Accuracy": B_Accuracy,
597                    "ROC AUC": ROC_AUC,
598                    "F1 Score": F1,
599                    "Time Taken": TIME,
600                }
601            )
602        else:
603            scores = pd.DataFrame(
604                {
605                    "Model": names,
606                    "Accuracy": Accuracy,
607                    "Balanced Accuracy": B_Accuracy,
608                    "ROC AUC": ROC_AUC,
609                    "F1 Score": F1,
610                    self.custom_metric.__name__: CUSTOM_METRIC,
611                    "Time Taken": TIME,
612                }
613            )
614        scores = scores.sort_values(by=self.sort_by, ascending=False).set_index(
615            "Model"
616        )
617
618        if self.predictions:
619            predictions_df = pd.DataFrame.from_dict(predictions)
620        return scores, predictions_df if self.predictions is True else scores
621
622    def provide_models(self, X_train, X_test, y_train, y_test):
623        """Returns all the model objects trained. If fit hasn't been called yet,
624        then it's called to return the models.
625
626        Parameters:
627
628        X_train: array-like,
629            Training vectors, where rows is the number of samples
630            and columns is the number of features.
631
632        X_test: array-like,
633            Testing vectors, where rows is the number of samples
634            and columns is the number of features.
635
636        y_train: array-like,
637            Training vectors, where rows is the number of samples
638            and columns is the number of features.
639
640        y_test: array-like,
641            Testing vectors, where rows is the number of samples
642            and columns is the number of features.
643
644        Returns:
645
646            models: dict-object,
647                Returns a dictionary with each model's pipeline as value
648                and key = name of the model.
649        """
650        if len(self.models.keys()) == 0:
651            self.fit(X_train, X_test, y_train, y_test)
652
653        return self.models

Fitting -- almost -- all the classification algorithms with layers of nnetsauce's CustomClassifier and returning their scores.

Parameters:

verbose: int, optional (default=0)
    Any positive number for verbosity.

ignore_warnings: bool, optional (default=True)
    When set to True, the warning related to algorigms that are not
    able to run are ignored.

custom_metric: function, optional (default=None)
    When function is provided, models are evaluated based on the custom
      evaluation metric provided.

predictions: bool, optional (default=False)
    When set to True, the predictions of all the models models are
    returned as data frame.

sort_by: string, optional (default='Accuracy')
    Sort models by a metric. Available options are 'Accuracy',
    'Balanced Accuracy', 'ROC AUC', 'F1 Score' or a custom metric
    identified by its name and provided by custom_metric.

random_state: int, optional (default=42)
    Reproducibiility seed.

estimators: list, optional (default='all')
    list of Estimators names or just 'all' for > 90 classifiers
    (default='all')

preprocess: bool, preprocessing is done when set to True

n_jobs: int, when possible, run in parallel
    For now, only used by individual models that support it.

n_layers: int, optional (default=3)
    Number of layers of CustomClassifiers to be used.

All the other parameters are the same as CustomClassifier's.

Examples

import nnetsauce as ns
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    data = load_breast_cancer()
    X = data.data
    y= data.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2,
        random_state=123)
    clf = ns.LazyDeepClassifier(verbose=0, ignore_warnings=True, custom_metric=None)
    models, predictions = clf.fit(X_train, X_test, y_train, y_test)
    model_dictionary = clf.provide_models(X_train,X_test,y_train,y_test)
    print(models)
    

def fit(self, X_train, X_test, y_train, y_test):
210    def fit(self, X_train, X_test, y_train, y_test):
211        """Fit classifiers to X_train and y_train, predict and score on X_test,
212        y_test.
213
214        Parameters:
215
216            X_train: array-like,
217                Training vectors, where rows is the number of samples
218                and columns is the number of features.
219
220            X_test: array-like,
221                Testing vectors, where rows is the number of samples
222                and columns is the number of features.
223
224            y_train: array-like,
225                Training vectors, where rows is the number of samples
226                and columns is the number of features.
227
228            y_test: array-like,
229                Testing vectors, where rows is the number of samples
230                and columns is the number of features.
231
232        Returns:
233
234            scores: Pandas DataFrame
235                Returns metrics of all the models in a Pandas DataFrame.
236
237            predictions: Pandas DataFrame
238                Returns predictions of all the models in a Pandas DataFrame.
239        """
240        Accuracy = []
241        B_Accuracy = []
242        ROC_AUC = []
243        F1 = []
244        names = []
245        TIME = []
246        predictions = {}
247
248        if self.custom_metric is not None:
249            CUSTOM_METRIC = []
250
251        if isinstance(X_train, np.ndarray):
252            X_train = pd.DataFrame(X_train)
253            X_test = pd.DataFrame(X_test)
254
255        numeric_features = X_train.select_dtypes(include=[np.number]).columns
256        categorical_features = X_train.select_dtypes(include=["object"]).columns
257
258        categorical_low, categorical_high = get_card_split(
259            X_train, categorical_features
260        )
261
262        if self.preprocess is True:
263            preprocessor = ColumnTransformer(
264                transformers=[
265                    ("numeric", numeric_transformer, numeric_features),
266                    (
267                        "categorical_low",
268                        categorical_transformer_low,
269                        categorical_low,
270                    ),
271                    (
272                        "categorical_high",
273                        categorical_transformer_high,
274                        categorical_high,
275                    ),
276                ]
277            )
278
279        if self.estimators == "all":
280            self.classifiers = [
281                item
282                for sublist in [
283                    DEEPCLASSIFIERS,
284                    DEEPMULTITASKCLASSIFIERS,
285                    DEEPSIMPLEMULTITASKCLASSIFIERS,
286                ]
287                for item in sublist
288            ]
289        else:
290            self.classifiers = (
291                [
292                    ("DeepCustomClassifier(" + est[0] + ")", est[1])
293                    for est in all_estimators()
294                    if (
295                        issubclass(est[1], ClassifierMixin)
296                        and (est[0] in self.estimators)
297                    )
298                ]
299                + [
300                    (
301                        "DeepMultitaskClassifier(" + est[0] + ")",
302                        partial(MultitaskClassifier, obj=est[1]()),
303                    )
304                    for est in all_estimators()
305                    if (
306                        issubclass(est[1], RegressorMixin)
307                        and (est[0] in self.estimators)
308                    )
309                ]
310                + [
311                    (
312                        "DeepSimpleMultitaskClassifier(" + est[0] + ")",
313                        partial(SimpleMultitaskClassifier, obj=est[1]()),
314                    )
315                    for est in all_estimators()
316                    if (
317                        issubclass(est[1], RegressorMixin)
318                        and (est[0] in self.estimators)
319                    )
320                ]
321            )
322
323        if self.preprocess is True:
324
325            for name, model in tqdm(self.classifiers):  # do parallel exec
326
327                other_args = (
328                    {}
329                )  # use this trick for `random_state` too --> refactor
330                try:
331                    if (
332                        "n_jobs" in model().get_params().keys()
333                        and name.find("LogisticRegression") == -1
334                    ):
335                        other_args["n_jobs"] = self.n_jobs
336                except Exception:
337                    pass
338
339                start = time.time()
340
341                try:
342                    if "random_state" in model().get_params().keys():
343                        layer_clf = CustomClassifier(
344                            obj=model(random_state=self.random_state),
345                            n_hidden_features=self.n_hidden_features,
346                            activation_name=self.activation_name,
347                            a=self.a,
348                            nodes_sim=self.nodes_sim,
349                            bias=self.bias,
350                            dropout=self.dropout,
351                            direct_link=self.direct_link,
352                            n_clusters=self.n_clusters,
353                            cluster_encode=self.cluster_encode,
354                            type_clust=self.type_clust,
355                            type_scaling=self.type_scaling,
356                            col_sample=self.col_sample,
357                            row_sample=self.row_sample,
358                            seed=self.seed,
359                            backend=self.backend,
360                        )
361
362                    else:
363                        layer_clf = CustomClassifier(
364                            obj=model(),
365                            n_hidden_features=self.n_hidden_features,
366                            activation_name=self.activation_name,
367                            a=self.a,
368                            nodes_sim=self.nodes_sim,
369                            bias=self.bias,
370                            dropout=self.dropout,
371                            direct_link=self.direct_link,
372                            n_clusters=self.n_clusters,
373                            cluster_encode=self.cluster_encode,
374                            type_clust=self.type_clust,
375                            type_scaling=self.type_scaling,
376                            col_sample=self.col_sample,
377                            row_sample=self.row_sample,
378                            seed=self.seed,
379                            backend=self.backend,
380                        )
381
382                    layer_clf.fit(X_train, y_train)
383
384                    for _ in range(self.n_layers):
385                        layer_clf = deepcopy(
386                            CustomClassifier(
387                                obj=layer_clf,
388                                n_hidden_features=self.n_hidden_features,
389                                activation_name=self.activation_name,
390                                a=self.a,
391                                nodes_sim=self.nodes_sim,
392                                bias=self.bias,
393                                dropout=self.dropout,
394                                direct_link=self.direct_link,
395                                n_clusters=self.n_clusters,
396                                cluster_encode=self.cluster_encode,
397                                type_clust=self.type_clust,
398                                type_scaling=self.type_scaling,
399                                col_sample=self.col_sample,
400                                row_sample=self.row_sample,
401                                seed=self.seed,
402                                backend=self.backend,
403                            )
404                        )
405
406                    pipe = Pipeline(
407                        [
408                            ("preprocessor", preprocessor),
409                            ("classifier", layer_clf),
410                        ]
411                    )
412
413                    pipe.fit(X_train, y_train)
414                    self.models[name] = pipe
415                    y_pred = pipe.predict(X_test)
416                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
417                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
418                    f1 = f1_score(y_test, y_pred, average="weighted")
419                    try:
420                        roc_auc = roc_auc_score(y_test, y_pred)
421                    except Exception as exception:
422                        roc_auc = None
423                        if self.ignore_warnings is False:
424                            print("ROC AUC couldn't be calculated for " + name)
425                            print(exception)
426                    names.append(name)
427                    Accuracy.append(accuracy)
428                    B_Accuracy.append(b_accuracy)
429                    ROC_AUC.append(roc_auc)
430                    F1.append(f1)
431                    TIME.append(time.time() - start)
432                    if self.custom_metric is not None:
433                        custom_metric = self.custom_metric(y_test, y_pred)
434                        CUSTOM_METRIC.append(custom_metric)
435                    if self.verbose > 0:
436                        if self.custom_metric is not None:
437                            print(
438                                {
439                                    "Model": name,
440                                    "Accuracy": accuracy,
441                                    "Balanced Accuracy": b_accuracy,
442                                    "ROC AUC": roc_auc,
443                                    "F1 Score": f1,
444                                    self.custom_metric.__name__: custom_metric,
445                                    "Time taken": time.time() - start,
446                                }
447                            )
448                        else:
449                            print(
450                                {
451                                    "Model": name,
452                                    "Accuracy": accuracy,
453                                    "Balanced Accuracy": b_accuracy,
454                                    "ROC AUC": roc_auc,
455                                    "F1 Score": f1,
456                                    "Time taken": time.time() - start,
457                                }
458                            )
459                    if self.predictions:
460                        predictions[name] = y_pred
461                except Exception as exception:
462                    if self.ignore_warnings is False:
463                        print(name + " model failed to execute")
464                        print(exception)
465
466        else:  # no preprocessing
467
468            for name, model in tqdm(self.classifiers):  # do parallel exec
469                start = time.time()
470                try:
471                    if "random_state" in model().get_params().keys():
472                        layer_clf = CustomClassifier(
473                            obj=model(random_state=self.random_state),
474                            n_hidden_features=self.n_hidden_features,
475                            activation_name=self.activation_name,
476                            a=self.a,
477                            nodes_sim=self.nodes_sim,
478                            bias=self.bias,
479                            dropout=self.dropout,
480                            direct_link=self.direct_link,
481                            n_clusters=self.n_clusters,
482                            cluster_encode=self.cluster_encode,
483                            type_clust=self.type_clust,
484                            type_scaling=self.type_scaling,
485                            col_sample=self.col_sample,
486                            row_sample=self.row_sample,
487                            seed=self.seed,
488                            backend=self.backend,
489                        )
490
491                    else:
492                        layer_clf = CustomClassifier(
493                            obj=model(),
494                            n_hidden_features=self.n_hidden_features,
495                            activation_name=self.activation_name,
496                            a=self.a,
497                            nodes_sim=self.nodes_sim,
498                            bias=self.bias,
499                            dropout=self.dropout,
500                            direct_link=self.direct_link,
501                            n_clusters=self.n_clusters,
502                            cluster_encode=self.cluster_encode,
503                            type_clust=self.type_clust,
504                            type_scaling=self.type_scaling,
505                            col_sample=self.col_sample,
506                            row_sample=self.row_sample,
507                            seed=self.seed,
508                            backend=self.backend,
509                        )
510
511                    layer_clf.fit(X_train, y_train)
512
513                    for _ in range(self.n_layers):
514                        layer_clf = deepcopy(
515                            CustomClassifier(
516                                obj=layer_clf,
517                                n_hidden_features=self.n_hidden_features,
518                                activation_name=self.activation_name,
519                                a=self.a,
520                                nodes_sim=self.nodes_sim,
521                                bias=self.bias,
522                                dropout=self.dropout,
523                                direct_link=self.direct_link,
524                                n_clusters=self.n_clusters,
525                                cluster_encode=self.cluster_encode,
526                                type_clust=self.type_clust,
527                                type_scaling=self.type_scaling,
528                                col_sample=self.col_sample,
529                                row_sample=self.row_sample,
530                                seed=self.seed,
531                                backend=self.backend,
532                            )
533                        )
534
535                        # layer_clf.fit(X_train, y_train)
536
537                    layer_clf.fit(X_train, y_train)
538
539                    self.models[name] = layer_clf
540                    y_pred = layer_clf.predict(X_test)
541                    accuracy = accuracy_score(y_test, y_pred, normalize=True)
542                    b_accuracy = balanced_accuracy_score(y_test, y_pred)
543                    f1 = f1_score(y_test, y_pred, average="weighted")
544                    try:
545                        roc_auc = roc_auc_score(y_test, y_pred)
546                    except Exception as exception:
547                        roc_auc = None
548                        if self.ignore_warnings is False:
549                            print("ROC AUC couldn't be calculated for " + name)
550                            print(exception)
551                    names.append(name)
552                    Accuracy.append(accuracy)
553                    B_Accuracy.append(b_accuracy)
554                    ROC_AUC.append(roc_auc)
555                    F1.append(f1)
556                    TIME.append(time.time() - start)
557                    if self.custom_metric is not None:
558                        custom_metric = self.custom_metric(y_test, y_pred)
559                        CUSTOM_METRIC.append(custom_metric)
560                    if self.verbose > 0:
561                        if self.custom_metric is not None:
562                            print(
563                                {
564                                    "Model": name,
565                                    "Accuracy": accuracy,
566                                    "Balanced Accuracy": b_accuracy,
567                                    "ROC AUC": roc_auc,
568                                    "F1 Score": f1,
569                                    self.custom_metric.__name__: custom_metric,
570                                    "Time taken": time.time() - start,
571                                }
572                            )
573                        else:
574                            print(
575                                {
576                                    "Model": name,
577                                    "Accuracy": accuracy,
578                                    "Balanced Accuracy": b_accuracy,
579                                    "ROC AUC": roc_auc,
580                                    "F1 Score": f1,
581                                    "Time taken": time.time() - start,
582                                }
583                            )
584                    if self.predictions:
585                        predictions[name] = y_pred
586                except Exception as exception:
587                    if self.ignore_warnings is False:
588                        print(name + " model failed to execute")
589                        print(exception)
590
591        if self.custom_metric is None:
592            scores = pd.DataFrame(
593                {
594                    "Model": names,
595                    "Accuracy": Accuracy,
596                    "Balanced Accuracy": B_Accuracy,
597                    "ROC AUC": ROC_AUC,
598                    "F1 Score": F1,
599                    "Time Taken": TIME,
600                }
601            )
602        else:
603            scores = pd.DataFrame(
604                {
605                    "Model": names,
606                    "Accuracy": Accuracy,
607                    "Balanced Accuracy": B_Accuracy,
608                    "ROC AUC": ROC_AUC,
609                    "F1 Score": F1,
610                    self.custom_metric.__name__: CUSTOM_METRIC,
611                    "Time Taken": TIME,
612                }
613            )
614        scores = scores.sort_values(by=self.sort_by, ascending=False).set_index(
615            "Model"
616        )
617
618        if self.predictions:
619            predictions_df = pd.DataFrame.from_dict(predictions)
620        return scores, predictions_df if self.predictions is True else scores

Fit classifiers to X_train and y_train, predict and score on X_test, y_test.

Parameters:

X_train: array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test: array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

y_train: array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

y_test: array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

Returns:

scores: Pandas DataFrame
    Returns metrics of all the models in a Pandas DataFrame.

predictions: Pandas DataFrame
    Returns predictions of all the models in a Pandas DataFrame.
def provide_models(self, X_train, X_test, y_train, y_test):
622    def provide_models(self, X_train, X_test, y_train, y_test):
623        """Returns all the model objects trained. If fit hasn't been called yet,
624        then it's called to return the models.
625
626        Parameters:
627
628        X_train: array-like,
629            Training vectors, where rows is the number of samples
630            and columns is the number of features.
631
632        X_test: array-like,
633            Testing vectors, where rows is the number of samples
634            and columns is the number of features.
635
636        y_train: array-like,
637            Training vectors, where rows is the number of samples
638            and columns is the number of features.
639
640        y_test: array-like,
641            Testing vectors, where rows is the number of samples
642            and columns is the number of features.
643
644        Returns:
645
646            models: dict-object,
647                Returns a dictionary with each model's pipeline as value
648                and key = name of the model.
649        """
650        if len(self.models.keys()) == 0:
651            self.fit(X_train, X_test, y_train, y_test)
652
653        return self.models

Returns all the model objects trained. If fit hasn't been called yet, then it's called to return the models.

Parameters:

X_train: array-like, Training vectors, where rows is the number of samples and columns is the number of features.

X_test: array-like, Testing vectors, where rows is the number of samples and columns is the number of features.

y_train: array-like, Training vectors, where rows is the number of samples and columns is the number of features.

y_test: array-like, Testing vectors, where rows is the number of samples and columns is the number of features.

Returns:

models: dict-object,
    Returns a dictionary with each model's pipeline as value
    and key = name of the model.
class LazyDeepRegressor(nnetsauce.custom.custom.Custom, sklearn.base.RegressorMixin):
 83class LazyDeepRegressor(Custom, RegressorMixin):
 84    """
 85        Fitting -- almost -- all the regression algorithms with layers of
 86        nnetsauce's CustomRegressor and returning their scores.
 87
 88    Parameters:
 89
 90        verbose: int, optional (default=0)
 91            Any positive number for verbosity.
 92
 93        ignore_warnings: bool, optional (default=True)
 94            When set to True, the warning related to algorigms that are not able to run are ignored.
 95
 96        custom_metric: function, optional (default=None)
 97            When function is provided, models are evaluated based on the custom evaluation metric provided.
 98
 99        predictions: bool, optional (default=False)
100            When set to True, the predictions of all the models models are returned as dataframe.
101
102        sort_by: string, optional (default='Accuracy')
103            Sort models by a metric. Available options are 'Accuracy', 'Balanced Accuracy', 'ROC AUC', 'F1 Score'
104            or a custom metric identified by its name and provided by custom_metric.
105
106        random_state: int, optional (default=42)
107            Reproducibiility seed.
108
109        estimators: list, optional (default='all')
110            list of Estimators names or just 'all' (default='all')
111
112        preprocess: bool
113            preprocessing is done when set to True
114
115        n_jobs : int, when possible, run in parallel
116            For now, only used by individual models that support it.
117
118        n_layers: int, optional (default=3)
119            Number of layers of CustomRegressors to be used.
120
121        All the other parameters are the same as CustomRegressor's.
122
123    Examples:
124
125        import nnetsauce as ns
126        import numpy as np
127        from sklearn import datasets
128        from sklearn.utils import shuffle
129
130        diabetes = datasets.load_diabetes()
131        X, y = shuffle(diabetes.data, diabetes.target, random_state=13)
132        X = X.astype(np.float32)
133
134        offset = int(X.shape[0] * 0.9)
135        X_train, y_train = X[:offset], y[:offset]
136        X_test, y_test = X[offset:], y[offset:]
137
138        reg = ns.LazyDeepRegressor(verbose=0, ignore_warnings=False, custom_metric=None)
139        models, predictions = reg.fit(X_train, X_test, y_train, y_test)
140        print(models)
141
142    """
143
144    def __init__(
145        self,
146        verbose=0,
147        ignore_warnings=True,
148        custom_metric=None,
149        predictions=False,
150        random_state=42,
151        estimators="all",
152        preprocess=False,
153        n_jobs=None,
154        # Defining depth
155        n_layers=3,
156        # CustomRegressor attributes
157        obj=None,
158        n_hidden_features=5,
159        activation_name="relu",
160        a=0.01,
161        nodes_sim="sobol",
162        bias=True,
163        dropout=0,
164        direct_link=True,
165        n_clusters=2,
166        cluster_encode=True,
167        type_clust="kmeans",
168        type_scaling=("std", "std", "std"),
169        col_sample=1,
170        row_sample=1,
171        seed=123,
172        backend="cpu",
173    ):
174        self.verbose = verbose
175        self.ignore_warnings = ignore_warnings
176        self.custom_metric = custom_metric
177        self.predictions = predictions
178        self.models = {}
179        self.random_state = random_state
180        self.estimators = estimators
181        self.preprocess = preprocess
182        self.n_layers = n_layers - 1
183        self.n_jobs = n_jobs
184        super().__init__(
185            obj=obj,
186            n_hidden_features=n_hidden_features,
187            activation_name=activation_name,
188            a=a,
189            nodes_sim=nodes_sim,
190            bias=bias,
191            dropout=dropout,
192            direct_link=direct_link,
193            n_clusters=n_clusters,
194            cluster_encode=cluster_encode,
195            type_clust=type_clust,
196            type_scaling=type_scaling,
197            col_sample=col_sample,
198            row_sample=row_sample,
199            seed=seed,
200            backend=backend,
201        )
202
203    def fit(self, X_train, X_test, y_train, y_test):
204        """Fit Regression algorithms to X_train and y_train, predict and score on X_test, y_test.
205
206        Parameters:
207
208            X_train : array-like,
209                Training vectors, where rows is the number of samples
210                and columns is the number of features.
211
212            X_test : array-like,
213                Testing vectors, where rows is the number of samples
214                and columns is the number of features.
215
216            y_train : array-like,
217                Training vectors, where rows is the number of samples
218                and columns is the number of features.
219
220            y_test : array-like,
221                Testing vectors, where rows is the number of samples
222                and columns is the number of features.
223
224        Returns:
225        -------
226        scores:  Pandas DataFrame
227            Returns metrics of all the models in a Pandas DataFrame.
228
229        predictions : Pandas DataFrame
230            Returns predictions of all the models in a Pandas DataFrame.
231
232        """
233        R2 = []
234        ADJR2 = []
235        RMSE = []
236        # WIN = []
237        names = []
238        TIME = []
239        predictions = {}
240
241        if self.custom_metric:
242            CUSTOM_METRIC = []
243
244        if isinstance(X_train, np.ndarray):
245            X_train = pd.DataFrame(X_train)
246            X_test = pd.DataFrame(X_test)
247
248        numeric_features = X_train.select_dtypes(include=[np.number]).columns
249        categorical_features = X_train.select_dtypes(include=["object"]).columns
250
251        categorical_low, categorical_high = get_card_split(
252            X_train, categorical_features
253        )
254
255        if self.preprocess is True:
256            preprocessor = ColumnTransformer(
257                transformers=[
258                    ("numeric", numeric_transformer, numeric_features),
259                    (
260                        "categorical_low",
261                        categorical_transformer_low,
262                        categorical_low,
263                    ),
264                    (
265                        "categorical_high",
266                        categorical_transformer_high,
267                        categorical_high,
268                    ),
269                ]
270            )
271
272        if self.estimators == "all":
273            self.regressors = DEEPREGRESSORS
274        else:
275            self.regressors = [
276                ("DeepCustomRegressor(" + est[0] + ")", est[1])
277                for est in all_estimators()
278                if (
279                    issubclass(est[1], RegressorMixin)
280                    and (est[0] in self.estimators)
281                )
282            ]
283
284        if self.preprocess is True:
285
286            for name, model in tqdm(self.regressors):  # do parallel exec
287                start = time.time()
288                try:
289                    if "random_state" in model().get_params().keys():
290                        layer_regr = CustomRegressor(
291                            obj=model(random_state=self.random_state),
292                            n_hidden_features=self.n_hidden_features,
293                            activation_name=self.activation_name,
294                            a=self.a,
295                            nodes_sim=self.nodes_sim,
296                            bias=self.bias,
297                            dropout=self.dropout,
298                            direct_link=self.direct_link,
299                            n_clusters=self.n_clusters,
300                            cluster_encode=self.cluster_encode,
301                            type_clust=self.type_clust,
302                            type_scaling=self.type_scaling,
303                            col_sample=self.col_sample,
304                            row_sample=self.row_sample,
305                            seed=self.seed,
306                            backend=self.backend,
307                        )
308                    else:
309                        layer_regr = CustomRegressor(
310                            obj=model(),
311                            n_hidden_features=self.n_hidden_features,
312                            activation_name=self.activation_name,
313                            a=self.a,
314                            nodes_sim=self.nodes_sim,
315                            bias=self.bias,
316                            dropout=self.dropout,
317                            direct_link=self.direct_link,
318                            n_clusters=self.n_clusters,
319                            cluster_encode=self.cluster_encode,
320                            type_clust=self.type_clust,
321                            type_scaling=self.type_scaling,
322                            col_sample=self.col_sample,
323                            row_sample=self.row_sample,
324                            seed=self.seed,
325                            backend=self.backend,
326                        )
327
328                    for _ in range(self.n_layers):
329                        layer_regr = deepcopy(
330                            CustomRegressor(
331                                obj=layer_regr,
332                                n_hidden_features=self.n_hidden_features,
333                                activation_name=self.activation_name,
334                                a=self.a,
335                                nodes_sim=self.nodes_sim,
336                                bias=self.bias,
337                                dropout=self.dropout,
338                                direct_link=self.direct_link,
339                                n_clusters=self.n_clusters,
340                                cluster_encode=self.cluster_encode,
341                                type_clust=self.type_clust,
342                                type_scaling=self.type_scaling,
343                                col_sample=self.col_sample,
344                                row_sample=self.row_sample,
345                                seed=self.seed,
346                                backend=self.backend,
347                            )
348                        )
349
350                    layer_regr.fit(X_train, y_train)
351
352                    pipe = Pipeline(
353                        steps=[
354                            ("preprocessor", preprocessor),
355                            ("regressor", layer_regr),
356                        ]
357                    )
358
359                    pipe.fit(X_train, y_train)
360
361                    self.models[name] = pipe
362                    y_pred = pipe.predict(X_test)
363                    r_squared = r2_score(y_test, y_pred)
364                    adj_rsquared = adjusted_rsquared(
365                        r_squared, X_test.shape[0], X_test.shape[1]
366                    )
367                    rmse = mean_squared_error(y_test, y_pred, squared=False)
368
369                    names.append(name)
370                    R2.append(r_squared)
371                    ADJR2.append(adj_rsquared)
372                    RMSE.append(rmse)
373                    TIME.append(time.time() - start)
374
375                    if self.custom_metric:
376                        custom_metric = self.custom_metric(y_test, y_pred)
377                        CUSTOM_METRIC.append(custom_metric)
378
379                    if self.verbose > 0:
380                        scores_verbose = {
381                            "Model": name,
382                            "R-Squared": r_squared,
383                            "Adjusted R-Squared": adj_rsquared,
384                            "RMSE": rmse,
385                            "Time taken": time.time() - start,
386                        }
387
388                        if self.custom_metric:
389                            scores_verbose[self.custom_metric.__name__] = (
390                                custom_metric
391                            )
392
393                        print(scores_verbose)
394                    if self.predictions:
395                        predictions[name] = y_pred
396                except Exception as exception:
397                    if self.ignore_warnings is False:
398                        print(name + " model failed to execute")
399                        print(exception)
400
401        else:  # no preprocessing
402
403            for name, model in tqdm(self.regressors):  # do parallel exec
404                start = time.time()
405                try:
406                    if "random_state" in model().get_params().keys():
407                        layer_regr = CustomRegressor(
408                            obj=model(random_state=self.random_state),
409                            n_hidden_features=self.n_hidden_features,
410                            activation_name=self.activation_name,
411                            a=self.a,
412                            nodes_sim=self.nodes_sim,
413                            bias=self.bias,
414                            dropout=self.dropout,
415                            direct_link=self.direct_link,
416                            n_clusters=self.n_clusters,
417                            cluster_encode=self.cluster_encode,
418                            type_clust=self.type_clust,
419                            type_scaling=self.type_scaling,
420                            col_sample=self.col_sample,
421                            row_sample=self.row_sample,
422                            seed=self.seed,
423                            backend=self.backend,
424                        )
425                    else:
426                        layer_regr = CustomRegressor(
427                            obj=model(),
428                            n_hidden_features=self.n_hidden_features,
429                            activation_name=self.activation_name,
430                            a=self.a,
431                            nodes_sim=self.nodes_sim,
432                            bias=self.bias,
433                            dropout=self.dropout,
434                            direct_link=self.direct_link,
435                            n_clusters=self.n_clusters,
436                            cluster_encode=self.cluster_encode,
437                            type_clust=self.type_clust,
438                            type_scaling=self.type_scaling,
439                            col_sample=self.col_sample,
440                            row_sample=self.row_sample,
441                            seed=self.seed,
442                            backend=self.backend,
443                        )
444
445                    layer_regr.fit(X_train, y_train)
446
447                    for _ in range(self.n_layers):
448                        layer_regr = deepcopy(
449                            CustomRegressor(
450                                obj=layer_regr,
451                                n_hidden_features=self.n_hidden_features,
452                                activation_name=self.activation_name,
453                                a=self.a,
454                                nodes_sim=self.nodes_sim,
455                                bias=self.bias,
456                                dropout=self.dropout,
457                                direct_link=self.direct_link,
458                                n_clusters=self.n_clusters,
459                                cluster_encode=self.cluster_encode,
460                                type_clust=self.type_clust,
461                                type_scaling=self.type_scaling,
462                                col_sample=self.col_sample,
463                                row_sample=self.row_sample,
464                                seed=self.seed,
465                                backend=self.backend,
466                            )
467                        )
468
469                        # layer_regr.fit(X_train, y_train)
470
471                    layer_regr.fit(X_train, y_train)
472
473                    self.models[name] = layer_regr
474                    y_pred = layer_regr.predict(X_test)
475
476                    r_squared = r2_score(y_test, y_pred)
477                    adj_rsquared = adjusted_rsquared(
478                        r_squared, X_test.shape[0], X_test.shape[1]
479                    )
480                    rmse = mean_squared_error(y_test, y_pred, squared=False)
481
482                    names.append(name)
483                    R2.append(r_squared)
484                    ADJR2.append(adj_rsquared)
485                    RMSE.append(rmse)
486                    TIME.append(time.time() - start)
487
488                    if self.custom_metric:
489                        custom_metric = self.custom_metric(y_test, y_pred)
490                        CUSTOM_METRIC.append(custom_metric)
491
492                    if self.verbose > 0:
493                        scores_verbose = {
494                            "Model": name,
495                            "R-Squared": r_squared,
496                            "Adjusted R-Squared": adj_rsquared,
497                            "RMSE": rmse,
498                            "Time taken": time.time() - start,
499                        }
500
501                        if self.custom_metric:
502                            scores_verbose[self.custom_metric.__name__] = (
503                                custom_metric
504                            )
505
506                        print(scores_verbose)
507                    if self.predictions:
508                        predictions[name] = y_pred
509                except Exception as exception:
510                    if self.ignore_warnings is False:
511                        print(name + " model failed to execute")
512                        print(exception)
513
514        scores = {
515            "Model": names,
516            "Adjusted R-Squared": ADJR2,
517            "R-Squared": R2,
518            "RMSE": RMSE,
519            "Time Taken": TIME,
520        }
521
522        if self.custom_metric:
523            scores[self.custom_metric.__name__] = CUSTOM_METRIC
524
525        scores = pd.DataFrame(scores)
526        scores = scores.sort_values(by="RMSE", ascending=True).set_index(
527            "Model"
528        )
529
530        if self.predictions:
531            predictions_df = pd.DataFrame.from_dict(predictions)
532        return scores, predictions_df if self.predictions is True else scores
533
534    def provide_models(self, X_train, X_test, y_train, y_test):
535        """
536        This function returns all the model objects trained in fit function.
537        If fit is not called already, then we call fit and then return the models.
538
539        Parameters:
540
541            X_train : array-like,
542                Training vectors, where rows is the number of samples
543                and columns is the number of features.
544
545            X_test : array-like,
546                Testing vectors, where rows is the number of samples
547                and columns is the number of features.
548
549            y_train : array-like,
550                Training vectors, where rows is the number of samples
551                and columns is the number of features.
552
553            y_test : array-like,
554                Testing vectors, where rows is the number of samples
555                and columns is the number of features.
556
557        Returns:
558
559            models: dict-object,
560                Returns a dictionary with each model pipeline as value
561                with key as name of models.
562
563        """
564        if len(self.models.keys()) == 0:
565            self.fit(X_train, X_test, y_train, y_test)
566
567        return self.models

Fitting -- almost -- all the regression algorithms with layers of nnetsauce's CustomRegressor and returning their scores.

Parameters:

verbose: int, optional (default=0)
    Any positive number for verbosity.

ignore_warnings: bool, optional (default=True)
    When set to True, the warning related to algorigms that are not able to run are ignored.

custom_metric: function, optional (default=None)
    When function is provided, models are evaluated based on the custom evaluation metric provided.

predictions: bool, optional (default=False)
    When set to True, the predictions of all the models models are returned as dataframe.

sort_by: string, optional (default='Accuracy')
    Sort models by a metric. Available options are 'Accuracy', 'Balanced Accuracy', 'ROC AUC', 'F1 Score'
    or a custom metric identified by its name and provided by custom_metric.

random_state: int, optional (default=42)
    Reproducibiility seed.

estimators: list, optional (default='all')
    list of Estimators names or just 'all' (default='all')

preprocess: bool
    preprocessing is done when set to True

n_jobs : int, when possible, run in parallel
    For now, only used by individual models that support it.

n_layers: int, optional (default=3)
    Number of layers of CustomRegressors to be used.

All the other parameters are the same as CustomRegressor's.

Examples:

import nnetsauce as ns
import numpy as np
from sklearn import datasets
from sklearn.utils import shuffle

diabetes = datasets.load_diabetes()
X, y = shuffle(diabetes.data, diabetes.target, random_state=13)
X = X.astype(np.float32)

offset = int(X.shape[0] * 0.9)
X_train, y_train = X[:offset], y[:offset]
X_test, y_test = X[offset:], y[offset:]

reg = ns.LazyDeepRegressor(verbose=0, ignore_warnings=False, custom_metric=None)
models, predictions = reg.fit(X_train, X_test, y_train, y_test)
print(models)
def fit(self, X_train, X_test, y_train, y_test):
203    def fit(self, X_train, X_test, y_train, y_test):
204        """Fit Regression algorithms to X_train and y_train, predict and score on X_test, y_test.
205
206        Parameters:
207
208            X_train : array-like,
209                Training vectors, where rows is the number of samples
210                and columns is the number of features.
211
212            X_test : array-like,
213                Testing vectors, where rows is the number of samples
214                and columns is the number of features.
215
216            y_train : array-like,
217                Training vectors, where rows is the number of samples
218                and columns is the number of features.
219
220            y_test : array-like,
221                Testing vectors, where rows is the number of samples
222                and columns is the number of features.
223
224        Returns:
225        -------
226        scores:  Pandas DataFrame
227            Returns metrics of all the models in a Pandas DataFrame.
228
229        predictions : Pandas DataFrame
230            Returns predictions of all the models in a Pandas DataFrame.
231
232        """
233        R2 = []
234        ADJR2 = []
235        RMSE = []
236        # WIN = []
237        names = []
238        TIME = []
239        predictions = {}
240
241        if self.custom_metric:
242            CUSTOM_METRIC = []
243
244        if isinstance(X_train, np.ndarray):
245            X_train = pd.DataFrame(X_train)
246            X_test = pd.DataFrame(X_test)
247
248        numeric_features = X_train.select_dtypes(include=[np.number]).columns
249        categorical_features = X_train.select_dtypes(include=["object"]).columns
250
251        categorical_low, categorical_high = get_card_split(
252            X_train, categorical_features
253        )
254
255        if self.preprocess is True:
256            preprocessor = ColumnTransformer(
257                transformers=[
258                    ("numeric", numeric_transformer, numeric_features),
259                    (
260                        "categorical_low",
261                        categorical_transformer_low,
262                        categorical_low,
263                    ),
264                    (
265                        "categorical_high",
266                        categorical_transformer_high,
267                        categorical_high,
268                    ),
269                ]
270            )
271
272        if self.estimators == "all":
273            self.regressors = DEEPREGRESSORS
274        else:
275            self.regressors = [
276                ("DeepCustomRegressor(" + est[0] + ")", est[1])
277                for est in all_estimators()
278                if (
279                    issubclass(est[1], RegressorMixin)
280                    and (est[0] in self.estimators)
281                )
282            ]
283
284        if self.preprocess is True:
285
286            for name, model in tqdm(self.regressors):  # do parallel exec
287                start = time.time()
288                try:
289                    if "random_state" in model().get_params().keys():
290                        layer_regr = CustomRegressor(
291                            obj=model(random_state=self.random_state),
292                            n_hidden_features=self.n_hidden_features,
293                            activation_name=self.activation_name,
294                            a=self.a,
295                            nodes_sim=self.nodes_sim,
296                            bias=self.bias,
297                            dropout=self.dropout,
298                            direct_link=self.direct_link,
299                            n_clusters=self.n_clusters,
300                            cluster_encode=self.cluster_encode,
301                            type_clust=self.type_clust,
302                            type_scaling=self.type_scaling,
303                            col_sample=self.col_sample,
304                            row_sample=self.row_sample,
305                            seed=self.seed,
306                            backend=self.backend,
307                        )
308                    else:
309                        layer_regr = CustomRegressor(
310                            obj=model(),
311                            n_hidden_features=self.n_hidden_features,
312                            activation_name=self.activation_name,
313                            a=self.a,
314                            nodes_sim=self.nodes_sim,
315                            bias=self.bias,
316                            dropout=self.dropout,
317                            direct_link=self.direct_link,
318                            n_clusters=self.n_clusters,
319                            cluster_encode=self.cluster_encode,
320                            type_clust=self.type_clust,
321                            type_scaling=self.type_scaling,
322                            col_sample=self.col_sample,
323                            row_sample=self.row_sample,
324                            seed=self.seed,
325                            backend=self.backend,
326                        )
327
328                    for _ in range(self.n_layers):
329                        layer_regr = deepcopy(
330                            CustomRegressor(
331                                obj=layer_regr,
332                                n_hidden_features=self.n_hidden_features,
333                                activation_name=self.activation_name,
334                                a=self.a,
335                                nodes_sim=self.nodes_sim,
336                                bias=self.bias,
337                                dropout=self.dropout,
338                                direct_link=self.direct_link,
339                                n_clusters=self.n_clusters,
340                                cluster_encode=self.cluster_encode,
341                                type_clust=self.type_clust,
342                                type_scaling=self.type_scaling,
343                                col_sample=self.col_sample,
344                                row_sample=self.row_sample,
345                                seed=self.seed,
346                                backend=self.backend,
347                            )
348                        )
349
350                    layer_regr.fit(X_train, y_train)
351
352                    pipe = Pipeline(
353                        steps=[
354                            ("preprocessor", preprocessor),
355                            ("regressor", layer_regr),
356                        ]
357                    )
358
359                    pipe.fit(X_train, y_train)
360
361                    self.models[name] = pipe
362                    y_pred = pipe.predict(X_test)
363                    r_squared = r2_score(y_test, y_pred)
364                    adj_rsquared = adjusted_rsquared(
365                        r_squared, X_test.shape[0], X_test.shape[1]
366                    )
367                    rmse = mean_squared_error(y_test, y_pred, squared=False)
368
369                    names.append(name)
370                    R2.append(r_squared)
371                    ADJR2.append(adj_rsquared)
372                    RMSE.append(rmse)
373                    TIME.append(time.time() - start)
374
375                    if self.custom_metric:
376                        custom_metric = self.custom_metric(y_test, y_pred)
377                        CUSTOM_METRIC.append(custom_metric)
378
379                    if self.verbose > 0:
380                        scores_verbose = {
381                            "Model": name,
382                            "R-Squared": r_squared,
383                            "Adjusted R-Squared": adj_rsquared,
384                            "RMSE": rmse,
385                            "Time taken": time.time() - start,
386                        }
387
388                        if self.custom_metric:
389                            scores_verbose[self.custom_metric.__name__] = (
390                                custom_metric
391                            )
392
393                        print(scores_verbose)
394                    if self.predictions:
395                        predictions[name] = y_pred
396                except Exception as exception:
397                    if self.ignore_warnings is False:
398                        print(name + " model failed to execute")
399                        print(exception)
400
401        else:  # no preprocessing
402
403            for name, model in tqdm(self.regressors):  # do parallel exec
404                start = time.time()
405                try:
406                    if "random_state" in model().get_params().keys():
407                        layer_regr = CustomRegressor(
408                            obj=model(random_state=self.random_state),
409                            n_hidden_features=self.n_hidden_features,
410                            activation_name=self.activation_name,
411                            a=self.a,
412                            nodes_sim=self.nodes_sim,
413                            bias=self.bias,
414                            dropout=self.dropout,
415                            direct_link=self.direct_link,
416                            n_clusters=self.n_clusters,
417                            cluster_encode=self.cluster_encode,
418                            type_clust=self.type_clust,
419                            type_scaling=self.type_scaling,
420                            col_sample=self.col_sample,
421                            row_sample=self.row_sample,
422                            seed=self.seed,
423                            backend=self.backend,
424                        )
425                    else:
426                        layer_regr = CustomRegressor(
427                            obj=model(),
428                            n_hidden_features=self.n_hidden_features,
429                            activation_name=self.activation_name,
430                            a=self.a,
431                            nodes_sim=self.nodes_sim,
432                            bias=self.bias,
433                            dropout=self.dropout,
434                            direct_link=self.direct_link,
435                            n_clusters=self.n_clusters,
436                            cluster_encode=self.cluster_encode,
437                            type_clust=self.type_clust,
438                            type_scaling=self.type_scaling,
439                            col_sample=self.col_sample,
440                            row_sample=self.row_sample,
441                            seed=self.seed,
442                            backend=self.backend,
443                        )
444
445                    layer_regr.fit(X_train, y_train)
446
447                    for _ in range(self.n_layers):
448                        layer_regr = deepcopy(
449                            CustomRegressor(
450                                obj=layer_regr,
451                                n_hidden_features=self.n_hidden_features,
452                                activation_name=self.activation_name,
453                                a=self.a,
454                                nodes_sim=self.nodes_sim,
455                                bias=self.bias,
456                                dropout=self.dropout,
457                                direct_link=self.direct_link,
458                                n_clusters=self.n_clusters,
459                                cluster_encode=self.cluster_encode,
460                                type_clust=self.type_clust,
461                                type_scaling=self.type_scaling,
462                                col_sample=self.col_sample,
463                                row_sample=self.row_sample,
464                                seed=self.seed,
465                                backend=self.backend,
466                            )
467                        )
468
469                        # layer_regr.fit(X_train, y_train)
470
471                    layer_regr.fit(X_train, y_train)
472
473                    self.models[name] = layer_regr
474                    y_pred = layer_regr.predict(X_test)
475
476                    r_squared = r2_score(y_test, y_pred)
477                    adj_rsquared = adjusted_rsquared(
478                        r_squared, X_test.shape[0], X_test.shape[1]
479                    )
480                    rmse = mean_squared_error(y_test, y_pred, squared=False)
481
482                    names.append(name)
483                    R2.append(r_squared)
484                    ADJR2.append(adj_rsquared)
485                    RMSE.append(rmse)
486                    TIME.append(time.time() - start)
487
488                    if self.custom_metric:
489                        custom_metric = self.custom_metric(y_test, y_pred)
490                        CUSTOM_METRIC.append(custom_metric)
491
492                    if self.verbose > 0:
493                        scores_verbose = {
494                            "Model": name,
495                            "R-Squared": r_squared,
496                            "Adjusted R-Squared": adj_rsquared,
497                            "RMSE": rmse,
498                            "Time taken": time.time() - start,
499                        }
500
501                        if self.custom_metric:
502                            scores_verbose[self.custom_metric.__name__] = (
503                                custom_metric
504                            )
505
506                        print(scores_verbose)
507                    if self.predictions:
508                        predictions[name] = y_pred
509                except Exception as exception:
510                    if self.ignore_warnings is False:
511                        print(name + " model failed to execute")
512                        print(exception)
513
514        scores = {
515            "Model": names,
516            "Adjusted R-Squared": ADJR2,
517            "R-Squared": R2,
518            "RMSE": RMSE,
519            "Time Taken": TIME,
520        }
521
522        if self.custom_metric:
523            scores[self.custom_metric.__name__] = CUSTOM_METRIC
524
525        scores = pd.DataFrame(scores)
526        scores = scores.sort_values(by="RMSE", ascending=True).set_index(
527            "Model"
528        )
529
530        if self.predictions:
531            predictions_df = pd.DataFrame.from_dict(predictions)
532        return scores, predictions_df if self.predictions is True else scores

Fit Regression algorithms to X_train and y_train, predict and score on X_test, y_test.

Parameters:

X_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

y_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

y_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

Returns:

scores: Pandas DataFrame Returns metrics of all the models in a Pandas DataFrame.

predictions : Pandas DataFrame Returns predictions of all the models in a Pandas DataFrame.

def provide_models(self, X_train, X_test, y_train, y_test):
534    def provide_models(self, X_train, X_test, y_train, y_test):
535        """
536        This function returns all the model objects trained in fit function.
537        If fit is not called already, then we call fit and then return the models.
538
539        Parameters:
540
541            X_train : array-like,
542                Training vectors, where rows is the number of samples
543                and columns is the number of features.
544
545            X_test : array-like,
546                Testing vectors, where rows is the number of samples
547                and columns is the number of features.
548
549            y_train : array-like,
550                Training vectors, where rows is the number of samples
551                and columns is the number of features.
552
553            y_test : array-like,
554                Testing vectors, where rows is the number of samples
555                and columns is the number of features.
556
557        Returns:
558
559            models: dict-object,
560                Returns a dictionary with each model pipeline as value
561                with key as name of models.
562
563        """
564        if len(self.models.keys()) == 0:
565            self.fit(X_train, X_test, y_train, y_test)
566
567        return self.models

This function returns all the model objects trained in fit function. If fit is not called already, then we call fit and then return the models.

Parameters:

X_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

y_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

y_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

Returns:

models: dict-object,
    Returns a dictionary with each model pipeline as value
    with key as name of models.
class LazyDeepMTS(nnetsauce.MTS):
 101class LazyDeepMTS(MTS):
 102    """
 103
 104    Fitting -- almost -- all the regression algorithms with layers of
 105    nnetsauce's CustomRegressor to multivariate time series
 106    and returning their scores.
 107
 108    Parameters:
 109
 110        verbose: int, optional (default=0)
 111            Any positive number for verbosity.
 112
 113        ignore_warnings: bool, optional (default=True)
 114            When set to True, the warning related to algorigms that are not
 115            able to run are ignored.
 116
 117        custom_metric: function, optional (default=None)
 118            When function is provided, models are evaluated based on the custom
 119              evaluation metric provided.
 120
 121        predictions: bool, optional (default=False)
 122            When set to True, the predictions of all the models models are returned as dataframe.
 123
 124        sort_by: string, optional (default='RMSE')
 125            Sort models by a metric. Available options are 'RMSE', 'MAE', 'MPL', 'MPE', 'MAPE',
 126            'R-Squared', 'Adjusted R-Squared' or a custom metric identified by its name and
 127            provided by custom_metric.
 128
 129        random_state: int, optional (default=42)
 130            Reproducibiility seed.
 131
 132        estimators: list, optional (default='all')
 133            list of Estimators (regression algorithms) names or just 'all' (default='all')
 134
 135        preprocess: bool, preprocessing is done when set to True
 136
 137        n_layers: int, optional (default=1)
 138            Number of layers in the network. When set to 1, the model is equivalent to a MTS.
 139
 140        h: int, optional (default=None)
 141            Number of steps ahead to predict (when used, must be > 0 and < X_test.shape[0]).
 142
 143        All the other parameters are the same as MTS's.
 144
 145    Examples:
 146
 147        See https://thierrymoudiki.github.io/blog/2023/10/29/python/quasirandomizednn/MTS-LazyPredict
 148
 149    """
 150
 151    def __init__(
 152        self,
 153        verbose=0,
 154        ignore_warnings=True,
 155        custom_metric=None,
 156        predictions=False,
 157        sort_by=None,
 158        random_state=42,
 159        estimators="all",
 160        preprocess=False,
 161        n_layers=1,
 162        h=None,
 163        # MTS attributes
 164        obj=None,
 165        n_hidden_features=5,
 166        activation_name="relu",
 167        a=0.01,
 168        nodes_sim="sobol",
 169        bias=True,
 170        dropout=0,
 171        direct_link=True,
 172        n_clusters=2,
 173        cluster_encode=True,
 174        type_clust="kmeans",
 175        type_scaling=("std", "std", "std"),
 176        lags=15,
 177        type_pi="scp2-kde",
 178        block_size=None,
 179        replications=None,
 180        kernel=None,
 181        agg="mean",
 182        seed=123,
 183        backend="cpu",
 184        show_progress=False,
 185    ):
 186        self.verbose = verbose
 187        self.ignore_warnings = ignore_warnings
 188        self.custom_metric = custom_metric
 189        self.predictions = predictions
 190        self.sort_by = sort_by
 191        self.models = {}
 192        self.random_state = random_state
 193        self.estimators = estimators
 194        self.preprocess = preprocess
 195        self.n_layers = n_layers
 196        self.h = h
 197        super().__init__(
 198            obj=obj,
 199            n_hidden_features=n_hidden_features,
 200            activation_name=activation_name,
 201            a=a,
 202            nodes_sim=nodes_sim,
 203            bias=bias,
 204            dropout=dropout,
 205            direct_link=direct_link,
 206            n_clusters=n_clusters,
 207            cluster_encode=cluster_encode,
 208            type_clust=type_clust,
 209            type_scaling=type_scaling,
 210            seed=seed,
 211            backend=backend,
 212            lags=lags,
 213            type_pi=type_pi,
 214            block_size=block_size,
 215            replications=replications,
 216            kernel=kernel,
 217            agg=agg,
 218            verbose=verbose,
 219            show_progress=show_progress,
 220        )
 221        if self.replications is not None:
 222            if self.sort_by is None:
 223                self.sort_by = "WINKLERSCORE"
 224        else:
 225            if self.sort_by is None:
 226                self.sort_by = "RMSE"
 227
 228    def fit(self, X_train, X_test, xreg=None, per_series=False, **kwargs):
 229        """Fit Regression algorithms to X_train, predict and score on X_test.
 230
 231        Parameters:
 232
 233            X_train: array-like or data frame,
 234                Training vectors, where rows is the number of samples
 235                and columns is the number of features.
 236
 237            X_test: array-like or data frame,
 238                Testing vectors, where rows is the number of samples
 239                and columns is the number of features.
 240
 241            xreg: array-like, optional (default=None)
 242                Additional (external) regressors to be passed to self.obj
 243                xreg must be in 'increasing' order (most recent observations last)
 244
 245            per_series: bool, optional (default=False)
 246                When set to True, the metrics are computed series by series.
 247
 248            **kwargs: dict, optional (default=None)
 249                Additional parameters to be passed to `fit` method of `obj`.
 250
 251        Returns:
 252
 253            scores: Pandas DataFrame
 254                Returns metrics of all the models in a Pandas DataFrame.
 255
 256            predictions: Pandas DataFrame
 257                Returns predictions of all the models in a Pandas DataFrame.
 258
 259        """
 260        R2 = []
 261        ADJR2 = []
 262        ME = []
 263        MPL = []
 264        RMSE = []
 265        MAE = []
 266        MPE = []
 267        MAPE = []
 268        WINKLERSCORE = []
 269        COVERAGE = []
 270
 271        # WIN = []
 272        names = []
 273        TIME = []
 274        predictions = {}
 275
 276        if self.custom_metric:
 277            CUSTOM_METRIC = []
 278
 279        if self.h is None:
 280            assert X_test is not None, "If h is None, X_test must be provided."
 281
 282        if isinstance(X_train, np.ndarray):
 283            X_train = pd.DataFrame(X_train)
 284            X_test = pd.DataFrame(X_test)
 285
 286        self.series_names = X_train.columns.tolist()
 287
 288        X_train = convert_df_to_numeric(X_train)
 289        X_test = convert_df_to_numeric(X_test)
 290
 291        numeric_features = X_train.select_dtypes(include=[np.number]).columns
 292        categorical_features = X_train.select_dtypes(include=["object"]).columns
 293
 294        categorical_low, categorical_high = get_card_split(
 295            X_train, categorical_features
 296        )
 297
 298        if self.preprocess:
 299            preprocessor = ColumnTransformer(
 300                transformers=[
 301                    ("numeric", numeric_transformer, numeric_features),
 302                    (
 303                        "categorical_low",
 304                        categorical_transformer_low,
 305                        categorical_low,
 306                    ),
 307                    (
 308                        "categorical_high",
 309                        categorical_transformer_high,
 310                        categorical_high,
 311                    ),
 312                ]
 313            )
 314
 315        # baselines (Classical MTS) ----
 316        for i, name in enumerate(["VAR", "VECM"]):
 317            start = time.time()
 318            regr = ClassicalMTS(model=name)
 319            regr.fit(X_train, **kwargs)
 320            self.models[name] = regr
 321            if self.h is None:
 322                X_pred = regr.predict(h=X_test.shape[0], **kwargs)
 323            else:
 324                assert self.h > 0, "h must be > 0"
 325                X_pred = regr.predict(h=self.h, **kwargs)
 326                try:
 327                    X_test = X_test[0: self.h, :]
 328                except Exception as e:
 329                    X_test = X_test.iloc[0: self.h, :]
 330
 331            if per_series == False:
 332                rmse = mean_squared_error(X_test, X_pred.mean, squared=False)
 333                mae = mean_absolute_error(X_test, X_pred.mean)
 334                mpl = mean_pinball_loss(X_test, X_pred.mean)
 335            else:
 336                rmse = mean_errors(
 337                    actual=X_test,
 338                    pred=X_pred.mean,
 339                    scoring="root_mean_squared_error",
 340                    per_series=True,
 341                )
 342                mae = mean_errors(
 343                    actual=X_test,
 344                    pred=X_pred.mean,
 345                    scoring="mean_absolute_error",
 346                    per_series=True,
 347                )
 348                mpl = mean_errors(
 349                    actual=X_test,
 350                    pred=X_pred.mean,
 351                    scoring="mean_pinball_loss",
 352                    per_series=True,
 353                )
 354
 355            names.append(name)
 356            RMSE.append(rmse)
 357            MAE.append(mae)
 358            MPL.append(mpl)
 359            if (self.replications is not None) or (self.type_pi == "gaussian"):
 360                winklerscore = winkler_score(
 361                    obj=X_pred, actual=X_test, level=95
 362                )
 363                coveragecalc = coverage(X_pred, X_test, level=95)
 364                WINKLERSCORE.append(winklerscore)
 365                COVERAGE.append(coveragecalc)
 366            TIME.append(time.time() - start)
 367
 368        if self.estimators == "all":
 369            if self.n_layers <= 1:
 370                self.regressors = REGRESSORSMTS
 371            else:
 372                self.regressors = DEEPREGRESSORSMTS
 373        else:
 374            if self.n_layers <= 1:
 375                self.regressors = [
 376                    ("MTS(" + est[0] + ")", est[1])
 377                    for est in all_estimators()
 378                    if (
 379                        issubclass(est[1], RegressorMixin)
 380                        and (est[0] in self.estimators)
 381                    )
 382                ]
 383            else:  # self.n_layers > 1
 384                self.regressors = [
 385                    ("DeepMTS(" + est[0] + ")", est[1])
 386                    for est in all_estimators()
 387                    if (
 388                        issubclass(est[1], RegressorMixin)
 389                        and (est[0] in self.estimators)
 390                    )
 391                ]
 392
 393        if self.preprocess is True:
 394            for name, model in tqdm(self.regressors):  # do parallel exec
 395                start = time.time()
 396                try:
 397                    if "random_state" in model().get_params().keys():
 398                        pipe = Pipeline(
 399                            steps=[
 400                                ("preprocessor", preprocessor),
 401                                (
 402                                    "regressor",
 403                                    DeepMTS(
 404                                        obj=model(
 405                                            random_state=self.random_state,
 406                                            **kwargs
 407                                        ),
 408                                        n_layers=self.n_layers,
 409                                        n_hidden_features=self.n_hidden_features,
 410                                        activation_name=self.activation_name,
 411                                        a=self.a,
 412                                        nodes_sim=self.nodes_sim,
 413                                        bias=self.bias,
 414                                        dropout=self.dropout,
 415                                        direct_link=self.direct_link,
 416                                        n_clusters=self.n_clusters,
 417                                        cluster_encode=self.cluster_encode,
 418                                        type_clust=self.type_clust,
 419                                        type_scaling=self.type_scaling,
 420                                        lags=self.lags,
 421                                        type_pi=self.type_pi,
 422                                        block_size=self.block_size,
 423                                        replications=self.replications,
 424                                        kernel=self.kernel,
 425                                        agg=self.agg,
 426                                        seed=self.seed,
 427                                        backend=self.backend,
 428                                        show_progress=self.show_progress,
 429                                    ),
 430                                ),
 431                            ]
 432                        )
 433                    else:  # "random_state" in model().get_params().keys()
 434                        pipe = Pipeline(
 435                            steps=[
 436                                ("preprocessor", preprocessor),
 437                                (
 438                                    "regressor",
 439                                    DeepMTS(
 440                                        obj=model(**kwargs),
 441                                        n_layers=self.n_layers,
 442                                        n_hidden_features=self.n_hidden_features,
 443                                        activation_name=self.activation_name,
 444                                        a=self.a,
 445                                        nodes_sim=self.nodes_sim,
 446                                        bias=self.bias,
 447                                        dropout=self.dropout,
 448                                        direct_link=self.direct_link,
 449                                        n_clusters=self.n_clusters,
 450                                        cluster_encode=self.cluster_encode,
 451                                        type_clust=self.type_clust,
 452                                        type_scaling=self.type_scaling,
 453                                        lags=self.lags,
 454                                        type_pi=self.type_pi,
 455                                        block_size=self.block_size,
 456                                        replications=self.replications,
 457                                        kernel=self.kernel,
 458                                        agg=self.agg,
 459                                        seed=self.seed,
 460                                        backend=self.backend,
 461                                        show_progress=self.show_progress,
 462                                    ),
 463                                ),
 464                            ]
 465                        )
 466
 467                    pipe.fit(X_train, **kwargs)
 468                    # pipe.fit(X_train, xreg=xreg)
 469
 470                    self.models[name] = pipe
 471
 472                    if self.h is None:
 473                        X_pred = pipe["regressor"].predict(h=self.h, **kwargs)
 474                    else:
 475                        assert self.h > 0, "h must be > 0"
 476                        X_pred = pipe["regressor"].predict(h=self.h, **kwargs)
 477
 478                    if (self.replications is not None) or (
 479                        self.type_pi == "gaussian"
 480                    ):
 481                        if per_series == False:
 482                            rmse = mean_squared_error(
 483                                X_test, X_pred.mean, squared=False
 484                            )
 485                            mae = mean_absolute_error(X_test, X_pred.mean)
 486                            mpl = mean_pinball_loss(X_test, X_pred.mean)
 487                            winklerscore = winkler_score(
 488                                obj=X_pred, actual=X_test, level=95
 489                            )
 490                            coveragecalc = coverage(X_pred, X_test, level=95)
 491                        else:
 492                            rmse = mean_errors(
 493                                actual=X_test,
 494                                pred=X_pred,
 495                                scoring="root_mean_squared_error",
 496                                per_series=True,
 497                            )
 498                            mae = mean_errors(
 499                                actual=X_test,
 500                                pred=X_pred,
 501                                scoring="mean_absolute_error",
 502                                per_series=True,
 503                            )
 504                            mpl = mean_errors(
 505                                actual=X_test,
 506                                pred=X_pred,
 507                                scoring="mean_pinball_loss",
 508                                per_series=True,
 509                            )
 510                            winklerscore = winkler_score(
 511                                obj=X_pred,
 512                                actual=X_test,
 513                                level=95,
 514                                per_series=True,
 515                            )
 516                            coveragecalc = coverage(
 517                                X_pred, X_test, level=95, per_series=True
 518                            )
 519                    else:
 520                        if per_series == False:
 521                            rmse = mean_squared_error(
 522                                X_test, X_pred, squared=False
 523                            )
 524                            mae = mean_absolute_error(X_test, X_pred)
 525                            mpl = mean_pinball_loss(X_test, X_pred)
 526                        else:
 527                            rmse = mean_errors(
 528                                actual=X_test,
 529                                pred=X_pred,
 530                                scoring="root_mean_squared_error",
 531                                per_series=True,
 532                            )
 533                            mae = mean_errors(
 534                                actual=X_test,
 535                                pred=X_pred,
 536                                scoring="mean_absolute_error",
 537                                per_series=True,
 538                            )
 539                            mpl = mean_errors(
 540                                actual=X_test,
 541                                pred=X_pred,
 542                                scoring="mean_pinball_loss",
 543                                per_series=True,
 544                            )
 545
 546                    names.append(name)
 547                    RMSE.append(rmse)
 548                    MAE.append(mae)
 549                    MPL.append(mpl)
 550
 551                    if (self.replications is not None) or (
 552                        self.type_pi == "gaussian"
 553                    ):
 554                        WINKLERSCORE.append(winklerscore)
 555                        COVERAGE.append(coveragecalc)
 556                    TIME.append(time.time() - start)
 557
 558                    if self.custom_metric:
 559                        custom_metric = self.custom_metric(X_test, X_pred)
 560                        CUSTOM_METRIC.append(custom_metric)
 561
 562                    if self.verbose > 0:
 563                        if (self.replications is not None) or (
 564                            self.type_pi == "gaussian"
 565                        ):
 566                            scores_verbose = {
 567                                "Model": name,
 568                                "RMSE": rmse,
 569                                "MAE": mae,
 570                                "MPL": mpl,
 571                                "WINKLERSCORE": winklerscore,
 572                                "COVERAGE": coveragecalc,
 573                                "Time taken": time.time() - start,
 574                            }
 575                        else:
 576                            scores_verbose = {
 577                                "Model": name,
 578                                "RMSE": rmse,
 579                                "MAE": mae,
 580                                "MPL": mpl,
 581                                "Time taken": time.time() - start,
 582                            }
 583
 584                        if self.custom_metric:
 585                            scores_verbose[self.custom_metric.__name__] = (
 586                                custom_metric
 587                            )
 588
 589                        print(scores_verbose)
 590                    if self.predictions:
 591                        predictions[name] = X_pred
 592                except Exception as exception:
 593                    if self.ignore_warnings is False:
 594                        print(name + " model failed to execute")
 595                        print(exception)
 596
 597        else:  # no preprocessing
 598
 599            for name, model in tqdm(self.regressors):  # do parallel exec
 600                start = time.time()
 601                try:
 602                    if "random_state" in model().get_params().keys():
 603                        pipe = DeepMTS(
 604                            obj=model(random_state=self.random_state, **kwargs),
 605                            n_layers=self.n_layers,
 606                            n_hidden_features=self.n_hidden_features,
 607                            activation_name=self.activation_name,
 608                            a=self.a,
 609                            nodes_sim=self.nodes_sim,
 610                            bias=self.bias,
 611                            dropout=self.dropout,
 612                            direct_link=self.direct_link,
 613                            n_clusters=self.n_clusters,
 614                            cluster_encode=self.cluster_encode,
 615                            type_clust=self.type_clust,
 616                            type_scaling=self.type_scaling,
 617                            lags=self.lags,
 618                            type_pi=self.type_pi,
 619                            block_size=self.block_size,
 620                            replications=self.replications,
 621                            kernel=self.kernel,
 622                            agg=self.agg,
 623                            seed=self.seed,
 624                            backend=self.backend,
 625                            show_progress=self.show_progress,
 626                        )
 627                    else:
 628                        pipe = DeepMTS(
 629                            obj=model(**kwargs),
 630                            n_layers=self.n_layers,
 631                            n_hidden_features=self.n_hidden_features,
 632                            activation_name=self.activation_name,
 633                            a=self.a,
 634                            nodes_sim=self.nodes_sim,
 635                            bias=self.bias,
 636                            dropout=self.dropout,
 637                            direct_link=self.direct_link,
 638                            n_clusters=self.n_clusters,
 639                            cluster_encode=self.cluster_encode,
 640                            type_clust=self.type_clust,
 641                            type_scaling=self.type_scaling,
 642                            lags=self.lags,
 643                            type_pi=self.type_pi,
 644                            block_size=self.block_size,
 645                            replications=self.replications,
 646                            kernel=self.kernel,
 647                            agg=self.agg,
 648                            seed=self.seed,
 649                            backend=self.backend,
 650                            show_progress=self.show_progress,
 651                        )
 652
 653                    pipe.fit(X_train, xreg, **kwargs)
 654                    # pipe.fit(X_train, xreg=xreg) # DO xreg like in `ahead`
 655
 656                    self.models[name] = pipe
 657
 658                    if self.preprocess is True:
 659                        if self.h is None:
 660                            X_pred = pipe["regressor"].predict(
 661                                h=X_test.shape[0], **kwargs
 662                            )
 663                        else:
 664                            assert (
 665                                self.h > 0 and self.h <= X_test.shape[0]
 666                            ), "h must be > 0 and < X_test.shape[0]"
 667                            X_pred = pipe["regressor"].predict(
 668                                h=self.h, **kwargs
 669                            )
 670
 671                    else:
 672                        if self.h is None:
 673                            X_pred = pipe.predict(
 674                                h=X_test.shape[0], **kwargs
 675                            )  # X_pred = pipe.predict(h=X_test.shape[0], new_xreg=new_xreg) ## DO xreg like in `ahead`
 676                        else:
 677                            assert (
 678                                self.h > 0 and self.h <= X_test.shape[0]
 679                            ), "h must be > 0 and < X_test.shape[0]"
 680                            X_pred = pipe.predict(h=self.h, **kwargs)
 681
 682                    if self.h is None:
 683                        if (self.replications is not None) or (
 684                            self.type_pi == "gaussian"
 685                        ):
 686
 687                            if per_series == True:
 688                                rmse = mean_errors(
 689                                    actual=X_test,
 690                                    pred=X_pred.mean,
 691                                    scoring="root_mean_squared_error",
 692                                    per_series=True,
 693                                )
 694                                mae = mean_errors(
 695                                    actual=X_test,
 696                                    pred=X_pred.mean,
 697                                    scoring="mean_absolute_error",
 698                                    per_series=True,
 699                                )
 700                                mpl = mean_errors(
 701                                    actual=X_test,
 702                                    pred=X_pred.mean,
 703                                    scoring="mean_pinball_loss",
 704                                    per_series=True,
 705                                )
 706                                winklerscore = winkler_score(
 707                                    obj=X_pred,
 708                                    actual=X_test,
 709                                    level=95,
 710                                    per_series=True,
 711                                )
 712                                coveragecalc = coverage(
 713                                    X_pred, X_test, level=95, per_series=True
 714                                )
 715                            else:
 716                                rmse = mean_squared_error(
 717                                    X_test, X_pred.mean, squared=False
 718                                )
 719                                mae = mean_absolute_error(X_test, X_pred.mean)
 720                                mpl = mean_pinball_loss(X_test, X_pred.mean)
 721                                winklerscore = winkler_score(
 722                                    obj=X_pred, actual=X_test, level=95
 723                                )
 724                                coveragecalc = coverage(
 725                                    X_pred, X_test, level=95
 726                                )
 727                        else:  # no prediction interval
 728                            if per_series == True:
 729                                rmse = mean_errors(
 730                                    actual=X_test,
 731                                    pred=X_pred,
 732                                    scoring="root_mean_squared_error",
 733                                    per_series=True,
 734                                )
 735                                mae = mean_errors(
 736                                    actual=X_test,
 737                                    pred=X_pred,
 738                                    scoring="mean_absolute_error",
 739                                    per_series=True,
 740                                )
 741                                mpl = mean_errors(
 742                                    actual=X_test,
 743                                    pred=X_pred,
 744                                    scoring="mean_pinball_loss",
 745                                    per_series=True,
 746                                )
 747                            else:
 748                                rmse = mean_squared_error(
 749                                    X_test, X_pred, squared=False
 750                                )
 751                                mae = mean_absolute_error(X_test, X_pred)
 752                                mpl = mean_pinball_loss(X_test, X_pred)
 753                    else:  # self.h is not None
 754                        if (self.replications is not None) or (
 755                            self.type_pi == "gaussian"
 756                        ):
 757
 758                            if per_series == False:
 759                                if isinstance(X_test, pd.DataFrame) == False:
 760                                    X_test_h = X_test[0: self.h, :]
 761                                    rmse = mean_squared_error(
 762                                        X_test_h, X_pred.mean, squared=False
 763                                    )
 764                                    mae = mean_absolute_error(
 765                                        X_test_h, X_pred.mean
 766                                    )
 767                                    mpl = mean_pinball_loss(
 768                                        X_test_h, X_pred.mean
 769                                    )
 770                                    winklerscore = winkler_score(
 771                                        obj=X_pred, actual=X_test_h, level=95
 772                                    )
 773                                    coveragecalc = coverage(
 774                                        X_pred, X_test_h, level=95
 775                                    )
 776                                else:
 777                                    X_test_h = X_test.iloc[0: self.h, :]
 778                                    rmse = mean_squared_error(
 779                                        X_test_h, X_pred.mean, squared=False
 780                                    )
 781                                    mae = mean_absolute_error(
 782                                        X_test_h, X_pred.mean
 783                                    )
 784                                    mpl = mean_pinball_loss(
 785                                        X_test_h, X_pred.mean
 786                                    )
 787                                    winklerscore = winkler_score(
 788                                        obj=X_pred, actual=X_test_h, level=95
 789                                    )
 790                                    coveragecalc = coverage(
 791                                        X_pred, X_test_h, level=95
 792                                    )
 793                            else:
 794                                if isinstance(X_test, pd.DataFrame):
 795                                    X_test_h = X_test.iloc[0: self.h, :]
 796                                    rmse = mean_errors(
 797                                        actual=X_test_h,
 798                                        pred=X_pred,
 799                                        scoring="root_mean_squared_error",
 800                                        per_series=True,
 801                                    )
 802                                    mae = mean_errors(
 803                                        actual=X_test_h,
 804                                        pred=X_pred,
 805                                        scoring="mean_absolute_error",
 806                                        per_series=True,
 807                                    )
 808                                    mpl = mean_errors(
 809                                        actual=X_test_h,
 810                                        pred=X_pred,
 811                                        scoring="mean_pinball_loss",
 812                                        per_series=True,
 813                                    )
 814                                    winklerscore = winkler_score(
 815                                        obj=X_pred,
 816                                        actual=X_test_h,
 817                                        level=95,
 818                                        per_series=True,
 819                                    )
 820                                    coveragecalc = coverage(
 821                                        X_pred,
 822                                        X_test_h,
 823                                        level=95,
 824                                        per_series=True,
 825                                    )
 826                                else:
 827                                    X_test_h = X_test[0: self.h, :]
 828                                    rmse = mean_errors(
 829                                        actual=X_test_h,
 830                                        pred=X_pred,
 831                                        scoring="root_mean_squared_error",
 832                                        per_series=True,
 833                                    )
 834                                    mae = mean_errors(
 835                                        actual=X_test_h,
 836                                        pred=X_pred,
 837                                        scoring="mean_absolute_error",
 838                                        per_series=True,
 839                                    )
 840                                    mpl = mean_errors(
 841                                        actual=X_test_h,
 842                                        pred=X_pred,
 843                                        scoring="mean_pinball_loss",
 844                                        per_series=True,
 845                                    )
 846                                    winklerscore = winkler_score(
 847                                        obj=X_pred,
 848                                        actual=X_test_h,
 849                                        level=95,
 850                                        per_series=True,
 851                                    )
 852                                    coveragecalc = coverage(
 853                                        X_pred,
 854                                        X_test_h,
 855                                        level=95,
 856                                        per_series=True,
 857                                    )
 858                        else:  # no prediction interval
 859                            if per_series == False:
 860                                if isinstance(X_test, pd.DataFrame):
 861                                    X_test_h = X_test.iloc[0: self.h, :]
 862                                    rmse = mean_squared_error(
 863                                        X_test_h, X_pred, squared=False
 864                                    )
 865                                    mae = mean_absolute_error(X_test_h, X_pred)
 866                                    mpl = mean_pinball_loss(X_test_h, X_pred)
 867                                else:
 868                                    X_test_h = X_test[0: self.h, :]
 869                                    rmse = mean_squared_error(
 870                                        X_test_h, X_pred, squared=False
 871                                    )
 872                                    mae = mean_absolute_error(X_test_h, X_pred)
 873                                    mpl = mean_pinball_loss(X_test_h, X_pred)
 874                            else:
 875                                if isinstance(X_test, pd.DataFrame):
 876                                    X_test_h = X_test.iloc[0: self.h, :]
 877                                    rmse = mean_errors(
 878                                        actual=X_test_h,
 879                                        pred=X_pred,
 880                                        scoring="root_mean_squared_error",
 881                                        per_series=True,
 882                                    )
 883                                    mae = mean_errors(
 884                                        actual=X_test_h,
 885                                        pred=X_pred,
 886                                        scoring="mean_absolute_error",
 887                                        per_series=True,
 888                                    )
 889                                    mpl = mean_errors(
 890                                        actual=X_test_h,
 891                                        pred=X_pred,
 892                                        scoring="mean_pinball_loss",
 893                                        per_series=True,
 894                                    )
 895                                else:
 896                                    X_test_h = X_test[0: self.h, :]
 897                                    rmse = mean_errors(
 898                                        actual=X_test_h,
 899                                        pred=X_pred,
 900                                        scoring="root_mean_squared_error",
 901                                        per_series=True,
 902                                    )
 903                                    mae = mean_errors(
 904                                        actual=X_test_h,
 905                                        pred=X_pred,
 906                                        scoring="mean_absolute_error",
 907                                        per_series=True,
 908                                    )
 909
 910                    names.append(name)
 911                    RMSE.append(rmse)
 912                    MAE.append(mae)
 913                    MPL.append(mpl)
 914                    if (self.replications is not None) or (
 915                        self.type_pi == "gaussian"
 916                    ):
 917                        WINKLERSCORE.append(winklerscore)
 918                        COVERAGE.append(coveragecalc)
 919                    TIME.append(time.time() - start)
 920
 921                    if self.custom_metric:
 922                        if self.h is None:
 923                            custom_metric = self.custom_metric(X_test, X_pred)
 924                        else:
 925                            custom_metric = self.custom_metric(X_test_h, X_pred)
 926
 927                        CUSTOM_METRIC.append(custom_metric)
 928
 929                    if self.verbose > 0:
 930                        if (self.replications is not None) or (
 931                            self.type_pi == "gaussian"
 932                        ):
 933                            scores_verbose = {
 934                                "Model": name,
 935                                "RMSE": rmse,
 936                                "MAE": mae,
 937                                "MPL": mpl,
 938                                "WINKLERSCORE": winklerscore,
 939                                "COVERAGE": coveragecalc,
 940                                "Time taken": time.time() - start,
 941                            }
 942                        else:
 943                            scores_verbose = {
 944                                "Model": name,
 945                                "RMSE": rmse,
 946                                "MAE": mae,
 947                                "MPL": mpl,
 948                                "Time taken": time.time() - start,
 949                            }
 950
 951                        if self.custom_metric:
 952                            scores_verbose[self.custom_metric.__name__] = (
 953                                custom_metric
 954                            )
 955
 956                        print(scores_verbose)
 957
 958                    if self.predictions:
 959                        predictions[name] = X_pred
 960
 961                except Exception as exception:
 962                    if self.ignore_warnings is False:
 963                        print(name + " model failed to execute")
 964                        print(exception)
 965
 966        if (self.replications is not None) or (self.type_pi == "gaussian"):
 967            scores = {
 968                "Model": names,
 969                "RMSE": RMSE,
 970                "MAE": MAE,
 971                "MPL": MPL,
 972                "WINKLERSCORE": WINKLERSCORE,
 973                "COVERAGE": COVERAGE,
 974                "Time Taken": TIME,
 975            }
 976        else:
 977            scores = {
 978                "Model": names,
 979                "RMSE": RMSE,
 980                "MAE": MAE,
 981                "MPL": MPL,
 982                "Time Taken": TIME,
 983            }
 984
 985        if self.custom_metric:
 986            scores[self.custom_metric.__name__] = CUSTOM_METRIC
 987
 988        if per_series:
 989            scores = dict_to_dataframe_series(scores, self.series_names)
 990        else:
 991            scores = pd.DataFrame(scores)
 992
 993        try:
 994            scores = scores.sort_values(
 995                by=self.sort_by, ascending=True
 996            ).set_index("Model")
 997        except:
 998            pass
 999
1000        if self.predictions:
1001            predictions_df = pd.DataFrame.from_dict(predictions)
1002
1003        return scores, predictions_df if self.predictions is True else scores
1004
1005    def provide_models(self, X_train, X_test):
1006        """
1007        This function returns all the model objects trained in fit function.
1008        If fit is not called already, then we call fit and then return the models.
1009
1010        Parameters:
1011
1012            X_train : array-like,
1013                Training vectors, where rows is the number of samples
1014                and columns is the number of features.
1015
1016            X_test : array-like,
1017                Testing vectors, where rows is the number of samples
1018                and columns is the number of features.
1019
1020        Returns:
1021
1022            models: dict-object,
1023                Returns a dictionary with each model pipeline as value
1024                with key as name of models.
1025
1026        """
1027        if self.h is None:
1028            if len(self.models.keys()) == 0:
1029                self.fit(X_train, X_test)
1030        else:
1031            if len(self.models.keys()) == 0:
1032                if isinstance(X_test, pd.DataFrame):
1033                    self.fit(X_train, X_test.iloc[0: self.h, :])
1034                else:
1035                    self.fit(X_train, X_test[0: self.h, :])
1036
1037        return self.models

Fitting -- almost -- all the regression algorithms with layers of nnetsauce's CustomRegressor to multivariate time series and returning their scores.

Parameters:

verbose: int, optional (default=0)
    Any positive number for verbosity.

ignore_warnings: bool, optional (default=True)
    When set to True, the warning related to algorigms that are not
    able to run are ignored.

custom_metric: function, optional (default=None)
    When function is provided, models are evaluated based on the custom
      evaluation metric provided.

predictions: bool, optional (default=False)
    When set to True, the predictions of all the models models are returned as dataframe.

sort_by: string, optional (default='RMSE')
    Sort models by a metric. Available options are 'RMSE', 'MAE', 'MPL', 'MPE', 'MAPE',
    'R-Squared', 'Adjusted R-Squared' or a custom metric identified by its name and
    provided by custom_metric.

random_state: int, optional (default=42)
    Reproducibiility seed.

estimators: list, optional (default='all')
    list of Estimators (regression algorithms) names or just 'all' (default='all')

preprocess: bool, preprocessing is done when set to True

n_layers: int, optional (default=1)
    Number of layers in the network. When set to 1, the model is equivalent to a MTS.

h: int, optional (default=None)
    Number of steps ahead to predict (when used, must be > 0 and < X_test.shape[0]).

All the other parameters are the same as MTS's.

Examples:

See https://thierrymoudiki.github.io/blog/2023/10/29/python/quasirandomizednn/MTS-LazyPredict
def fit(self, X_train, X_test, xreg=None, per_series=False, **kwargs):
 228    def fit(self, X_train, X_test, xreg=None, per_series=False, **kwargs):
 229        """Fit Regression algorithms to X_train, predict and score on X_test.
 230
 231        Parameters:
 232
 233            X_train: array-like or data frame,
 234                Training vectors, where rows is the number of samples
 235                and columns is the number of features.
 236
 237            X_test: array-like or data frame,
 238                Testing vectors, where rows is the number of samples
 239                and columns is the number of features.
 240
 241            xreg: array-like, optional (default=None)
 242                Additional (external) regressors to be passed to self.obj
 243                xreg must be in 'increasing' order (most recent observations last)
 244
 245            per_series: bool, optional (default=False)
 246                When set to True, the metrics are computed series by series.
 247
 248            **kwargs: dict, optional (default=None)
 249                Additional parameters to be passed to `fit` method of `obj`.
 250
 251        Returns:
 252
 253            scores: Pandas DataFrame
 254                Returns metrics of all the models in a Pandas DataFrame.
 255
 256            predictions: Pandas DataFrame
 257                Returns predictions of all the models in a Pandas DataFrame.
 258
 259        """
 260        R2 = []
 261        ADJR2 = []
 262        ME = []
 263        MPL = []
 264        RMSE = []
 265        MAE = []
 266        MPE = []
 267        MAPE = []
 268        WINKLERSCORE = []
 269        COVERAGE = []
 270
 271        # WIN = []
 272        names = []
 273        TIME = []
 274        predictions = {}
 275
 276        if self.custom_metric:
 277            CUSTOM_METRIC = []
 278
 279        if self.h is None:
 280            assert X_test is not None, "If h is None, X_test must be provided."
 281
 282        if isinstance(X_train, np.ndarray):
 283            X_train = pd.DataFrame(X_train)
 284            X_test = pd.DataFrame(X_test)
 285
 286        self.series_names = X_train.columns.tolist()
 287
 288        X_train = convert_df_to_numeric(X_train)
 289        X_test = convert_df_to_numeric(X_test)
 290
 291        numeric_features = X_train.select_dtypes(include=[np.number]).columns
 292        categorical_features = X_train.select_dtypes(include=["object"]).columns
 293
 294        categorical_low, categorical_high = get_card_split(
 295            X_train, categorical_features
 296        )
 297
 298        if self.preprocess:
 299            preprocessor = ColumnTransformer(
 300                transformers=[
 301                    ("numeric", numeric_transformer, numeric_features),
 302                    (
 303                        "categorical_low",
 304                        categorical_transformer_low,
 305                        categorical_low,
 306                    ),
 307                    (
 308                        "categorical_high",
 309                        categorical_transformer_high,
 310                        categorical_high,
 311                    ),
 312                ]
 313            )
 314
 315        # baselines (Classical MTS) ----
 316        for i, name in enumerate(["VAR", "VECM"]):
 317            start = time.time()
 318            regr = ClassicalMTS(model=name)
 319            regr.fit(X_train, **kwargs)
 320            self.models[name] = regr
 321            if self.h is None:
 322                X_pred = regr.predict(h=X_test.shape[0], **kwargs)
 323            else:
 324                assert self.h > 0, "h must be > 0"
 325                X_pred = regr.predict(h=self.h, **kwargs)
 326                try:
 327                    X_test = X_test[0: self.h, :]
 328                except Exception as e:
 329                    X_test = X_test.iloc[0: self.h, :]
 330
 331            if per_series == False:
 332                rmse = mean_squared_error(X_test, X_pred.mean, squared=False)
 333                mae = mean_absolute_error(X_test, X_pred.mean)
 334                mpl = mean_pinball_loss(X_test, X_pred.mean)
 335            else:
 336                rmse = mean_errors(
 337                    actual=X_test,
 338                    pred=X_pred.mean,
 339                    scoring="root_mean_squared_error",
 340                    per_series=True,
 341                )
 342                mae = mean_errors(
 343                    actual=X_test,
 344                    pred=X_pred.mean,
 345                    scoring="mean_absolute_error",
 346                    per_series=True,
 347                )
 348                mpl = mean_errors(
 349                    actual=X_test,
 350                    pred=X_pred.mean,
 351                    scoring="mean_pinball_loss",
 352                    per_series=True,
 353                )
 354
 355            names.append(name)
 356            RMSE.append(rmse)
 357            MAE.append(mae)
 358            MPL.append(mpl)
 359            if (self.replications is not None) or (self.type_pi == "gaussian"):
 360                winklerscore = winkler_score(
 361                    obj=X_pred, actual=X_test, level=95
 362                )
 363                coveragecalc = coverage(X_pred, X_test, level=95)
 364                WINKLERSCORE.append(winklerscore)
 365                COVERAGE.append(coveragecalc)
 366            TIME.append(time.time() - start)
 367
 368        if self.estimators == "all":
 369            if self.n_layers <= 1:
 370                self.regressors = REGRESSORSMTS
 371            else:
 372                self.regressors = DEEPREGRESSORSMTS
 373        else:
 374            if self.n_layers <= 1:
 375                self.regressors = [
 376                    ("MTS(" + est[0] + ")", est[1])
 377                    for est in all_estimators()
 378                    if (
 379                        issubclass(est[1], RegressorMixin)
 380                        and (est[0] in self.estimators)
 381                    )
 382                ]
 383            else:  # self.n_layers > 1
 384                self.regressors = [
 385                    ("DeepMTS(" + est[0] + ")", est[1])
 386                    for est in all_estimators()
 387                    if (
 388                        issubclass(est[1], RegressorMixin)
 389                        and (est[0] in self.estimators)
 390                    )
 391                ]
 392
 393        if self.preprocess is True:
 394            for name, model in tqdm(self.regressors):  # do parallel exec
 395                start = time.time()
 396                try:
 397                    if "random_state" in model().get_params().keys():
 398                        pipe = Pipeline(
 399                            steps=[
 400                                ("preprocessor", preprocessor),
 401                                (
 402                                    "regressor",
 403                                    DeepMTS(
 404                                        obj=model(
 405                                            random_state=self.random_state,
 406                                            **kwargs
 407                                        ),
 408                                        n_layers=self.n_layers,
 409                                        n_hidden_features=self.n_hidden_features,
 410                                        activation_name=self.activation_name,
 411                                        a=self.a,
 412                                        nodes_sim=self.nodes_sim,
 413                                        bias=self.bias,
 414                                        dropout=self.dropout,
 415                                        direct_link=self.direct_link,
 416                                        n_clusters=self.n_clusters,
 417                                        cluster_encode=self.cluster_encode,
 418                                        type_clust=self.type_clust,
 419                                        type_scaling=self.type_scaling,
 420                                        lags=self.lags,
 421                                        type_pi=self.type_pi,
 422                                        block_size=self.block_size,
 423                                        replications=self.replications,
 424                                        kernel=self.kernel,
 425                                        agg=self.agg,
 426                                        seed=self.seed,
 427                                        backend=self.backend,
 428                                        show_progress=self.show_progress,
 429                                    ),
 430                                ),
 431                            ]
 432                        )
 433                    else:  # "random_state" in model().get_params().keys()
 434                        pipe = Pipeline(
 435                            steps=[
 436                                ("preprocessor", preprocessor),
 437                                (
 438                                    "regressor",
 439                                    DeepMTS(
 440                                        obj=model(**kwargs),
 441                                        n_layers=self.n_layers,
 442                                        n_hidden_features=self.n_hidden_features,
 443                                        activation_name=self.activation_name,
 444                                        a=self.a,
 445                                        nodes_sim=self.nodes_sim,
 446                                        bias=self.bias,
 447                                        dropout=self.dropout,
 448                                        direct_link=self.direct_link,
 449                                        n_clusters=self.n_clusters,
 450                                        cluster_encode=self.cluster_encode,
 451                                        type_clust=self.type_clust,
 452                                        type_scaling=self.type_scaling,
 453                                        lags=self.lags,
 454                                        type_pi=self.type_pi,
 455                                        block_size=self.block_size,
 456                                        replications=self.replications,
 457                                        kernel=self.kernel,
 458                                        agg=self.agg,
 459                                        seed=self.seed,
 460                                        backend=self.backend,
 461                                        show_progress=self.show_progress,
 462                                    ),
 463                                ),
 464                            ]
 465                        )
 466
 467                    pipe.fit(X_train, **kwargs)
 468                    # pipe.fit(X_train, xreg=xreg)
 469
 470                    self.models[name] = pipe
 471
 472                    if self.h is None:
 473                        X_pred = pipe["regressor"].predict(h=self.h, **kwargs)
 474                    else:
 475                        assert self.h > 0, "h must be > 0"
 476                        X_pred = pipe["regressor"].predict(h=self.h, **kwargs)
 477
 478                    if (self.replications is not None) or (
 479                        self.type_pi == "gaussian"
 480                    ):
 481                        if per_series == False:
 482                            rmse = mean_squared_error(
 483                                X_test, X_pred.mean, squared=False
 484                            )
 485                            mae = mean_absolute_error(X_test, X_pred.mean)
 486                            mpl = mean_pinball_loss(X_test, X_pred.mean)
 487                            winklerscore = winkler_score(
 488                                obj=X_pred, actual=X_test, level=95
 489                            )
 490                            coveragecalc = coverage(X_pred, X_test, level=95)
 491                        else:
 492                            rmse = mean_errors(
 493                                actual=X_test,
 494                                pred=X_pred,
 495                                scoring="root_mean_squared_error",
 496                                per_series=True,
 497                            )
 498                            mae = mean_errors(
 499                                actual=X_test,
 500                                pred=X_pred,
 501                                scoring="mean_absolute_error",
 502                                per_series=True,
 503                            )
 504                            mpl = mean_errors(
 505                                actual=X_test,
 506                                pred=X_pred,
 507                                scoring="mean_pinball_loss",
 508                                per_series=True,
 509                            )
 510                            winklerscore = winkler_score(
 511                                obj=X_pred,
 512                                actual=X_test,
 513                                level=95,
 514                                per_series=True,
 515                            )
 516                            coveragecalc = coverage(
 517                                X_pred, X_test, level=95, per_series=True
 518                            )
 519                    else:
 520                        if per_series == False:
 521                            rmse = mean_squared_error(
 522                                X_test, X_pred, squared=False
 523                            )
 524                            mae = mean_absolute_error(X_test, X_pred)
 525                            mpl = mean_pinball_loss(X_test, X_pred)
 526                        else:
 527                            rmse = mean_errors(
 528                                actual=X_test,
 529                                pred=X_pred,
 530                                scoring="root_mean_squared_error",
 531                                per_series=True,
 532                            )
 533                            mae = mean_errors(
 534                                actual=X_test,
 535                                pred=X_pred,
 536                                scoring="mean_absolute_error",
 537                                per_series=True,
 538                            )
 539                            mpl = mean_errors(
 540                                actual=X_test,
 541                                pred=X_pred,
 542                                scoring="mean_pinball_loss",
 543                                per_series=True,
 544                            )
 545
 546                    names.append(name)
 547                    RMSE.append(rmse)
 548                    MAE.append(mae)
 549                    MPL.append(mpl)
 550
 551                    if (self.replications is not None) or (
 552                        self.type_pi == "gaussian"
 553                    ):
 554                        WINKLERSCORE.append(winklerscore)
 555                        COVERAGE.append(coveragecalc)
 556                    TIME.append(time.time() - start)
 557
 558                    if self.custom_metric:
 559                        custom_metric = self.custom_metric(X_test, X_pred)
 560                        CUSTOM_METRIC.append(custom_metric)
 561
 562                    if self.verbose > 0:
 563                        if (self.replications is not None) or (
 564                            self.type_pi == "gaussian"
 565                        ):
 566                            scores_verbose = {
 567                                "Model": name,
 568                                "RMSE": rmse,
 569                                "MAE": mae,
 570                                "MPL": mpl,
 571                                "WINKLERSCORE": winklerscore,
 572                                "COVERAGE": coveragecalc,
 573                                "Time taken": time.time() - start,
 574                            }
 575                        else:
 576                            scores_verbose = {
 577                                "Model": name,
 578                                "RMSE": rmse,
 579                                "MAE": mae,
 580                                "MPL": mpl,
 581                                "Time taken": time.time() - start,
 582                            }
 583
 584                        if self.custom_metric:
 585                            scores_verbose[self.custom_metric.__name__] = (
 586                                custom_metric
 587                            )
 588
 589                        print(scores_verbose)
 590                    if self.predictions:
 591                        predictions[name] = X_pred
 592                except Exception as exception:
 593                    if self.ignore_warnings is False:
 594                        print(name + " model failed to execute")
 595                        print(exception)
 596
 597        else:  # no preprocessing
 598
 599            for name, model in tqdm(self.regressors):  # do parallel exec
 600                start = time.time()
 601                try:
 602                    if "random_state" in model().get_params().keys():
 603                        pipe = DeepMTS(
 604                            obj=model(random_state=self.random_state, **kwargs),
 605                            n_layers=self.n_layers,
 606                            n_hidden_features=self.n_hidden_features,
 607                            activation_name=self.activation_name,
 608                            a=self.a,
 609                            nodes_sim=self.nodes_sim,
 610                            bias=self.bias,
 611                            dropout=self.dropout,
 612                            direct_link=self.direct_link,
 613                            n_clusters=self.n_clusters,
 614                            cluster_encode=self.cluster_encode,
 615                            type_clust=self.type_clust,
 616                            type_scaling=self.type_scaling,
 617                            lags=self.lags,
 618                            type_pi=self.type_pi,
 619                            block_size=self.block_size,
 620                            replications=self.replications,
 621                            kernel=self.kernel,
 622                            agg=self.agg,
 623                            seed=self.seed,
 624                            backend=self.backend,
 625                            show_progress=self.show_progress,
 626                        )
 627                    else:
 628                        pipe = DeepMTS(
 629                            obj=model(**kwargs),
 630                            n_layers=self.n_layers,
 631                            n_hidden_features=self.n_hidden_features,
 632                            activation_name=self.activation_name,
 633                            a=self.a,
 634                            nodes_sim=self.nodes_sim,
 635                            bias=self.bias,
 636                            dropout=self.dropout,
 637                            direct_link=self.direct_link,
 638                            n_clusters=self.n_clusters,
 639                            cluster_encode=self.cluster_encode,
 640                            type_clust=self.type_clust,
 641                            type_scaling=self.type_scaling,
 642                            lags=self.lags,
 643                            type_pi=self.type_pi,
 644                            block_size=self.block_size,
 645                            replications=self.replications,
 646                            kernel=self.kernel,
 647                            agg=self.agg,
 648                            seed=self.seed,
 649                            backend=self.backend,
 650                            show_progress=self.show_progress,
 651                        )
 652
 653                    pipe.fit(X_train, xreg, **kwargs)
 654                    # pipe.fit(X_train, xreg=xreg) # DO xreg like in `ahead`
 655
 656                    self.models[name] = pipe
 657
 658                    if self.preprocess is True:
 659                        if self.h is None:
 660                            X_pred = pipe["regressor"].predict(
 661                                h=X_test.shape[0], **kwargs
 662                            )
 663                        else:
 664                            assert (
 665                                self.h > 0 and self.h <= X_test.shape[0]
 666                            ), "h must be > 0 and < X_test.shape[0]"
 667                            X_pred = pipe["regressor"].predict(
 668                                h=self.h, **kwargs
 669                            )
 670
 671                    else:
 672                        if self.h is None:
 673                            X_pred = pipe.predict(
 674                                h=X_test.shape[0], **kwargs
 675                            )  # X_pred = pipe.predict(h=X_test.shape[0], new_xreg=new_xreg) ## DO xreg like in `ahead`
 676                        else:
 677                            assert (
 678                                self.h > 0 and self.h <= X_test.shape[0]
 679                            ), "h must be > 0 and < X_test.shape[0]"
 680                            X_pred = pipe.predict(h=self.h, **kwargs)
 681
 682                    if self.h is None:
 683                        if (self.replications is not None) or (
 684                            self.type_pi == "gaussian"
 685                        ):
 686
 687                            if per_series == True:
 688                                rmse = mean_errors(
 689                                    actual=X_test,
 690                                    pred=X_pred.mean,
 691                                    scoring="root_mean_squared_error",
 692                                    per_series=True,
 693                                )
 694                                mae = mean_errors(
 695                                    actual=X_test,
 696                                    pred=X_pred.mean,
 697                                    scoring="mean_absolute_error",
 698                                    per_series=True,
 699                                )
 700                                mpl = mean_errors(
 701                                    actual=X_test,
 702                                    pred=X_pred.mean,
 703                                    scoring="mean_pinball_loss",
 704                                    per_series=True,
 705                                )
 706                                winklerscore = winkler_score(
 707                                    obj=X_pred,
 708                                    actual=X_test,
 709                                    level=95,
 710                                    per_series=True,
 711                                )
 712                                coveragecalc = coverage(
 713                                    X_pred, X_test, level=95, per_series=True
 714                                )
 715                            else:
 716                                rmse = mean_squared_error(
 717                                    X_test, X_pred.mean, squared=False
 718                                )
 719                                mae = mean_absolute_error(X_test, X_pred.mean)
 720                                mpl = mean_pinball_loss(X_test, X_pred.mean)
 721                                winklerscore = winkler_score(
 722                                    obj=X_pred, actual=X_test, level=95
 723                                )
 724                                coveragecalc = coverage(
 725                                    X_pred, X_test, level=95
 726                                )
 727                        else:  # no prediction interval
 728                            if per_series == True:
 729                                rmse = mean_errors(
 730                                    actual=X_test,
 731                                    pred=X_pred,
 732                                    scoring="root_mean_squared_error",
 733                                    per_series=True,
 734                                )
 735                                mae = mean_errors(
 736                                    actual=X_test,
 737                                    pred=X_pred,
 738                                    scoring="mean_absolute_error",
 739                                    per_series=True,
 740                                )
 741                                mpl = mean_errors(
 742                                    actual=X_test,
 743                                    pred=X_pred,
 744                                    scoring="mean_pinball_loss",
 745                                    per_series=True,
 746                                )
 747                            else:
 748                                rmse = mean_squared_error(
 749                                    X_test, X_pred, squared=False
 750                                )
 751                                mae = mean_absolute_error(X_test, X_pred)
 752                                mpl = mean_pinball_loss(X_test, X_pred)
 753                    else:  # self.h is not None
 754                        if (self.replications is not None) or (
 755                            self.type_pi == "gaussian"
 756                        ):
 757
 758                            if per_series == False:
 759                                if isinstance(X_test, pd.DataFrame) == False:
 760                                    X_test_h = X_test[0: self.h, :]
 761                                    rmse = mean_squared_error(
 762                                        X_test_h, X_pred.mean, squared=False
 763                                    )
 764                                    mae = mean_absolute_error(
 765                                        X_test_h, X_pred.mean
 766                                    )
 767                                    mpl = mean_pinball_loss(
 768                                        X_test_h, X_pred.mean
 769                                    )
 770                                    winklerscore = winkler_score(
 771                                        obj=X_pred, actual=X_test_h, level=95
 772                                    )
 773                                    coveragecalc = coverage(
 774                                        X_pred, X_test_h, level=95
 775                                    )
 776                                else:
 777                                    X_test_h = X_test.iloc[0: self.h, :]
 778                                    rmse = mean_squared_error(
 779                                        X_test_h, X_pred.mean, squared=False
 780                                    )
 781                                    mae = mean_absolute_error(
 782                                        X_test_h, X_pred.mean
 783                                    )
 784                                    mpl = mean_pinball_loss(
 785                                        X_test_h, X_pred.mean
 786                                    )
 787                                    winklerscore = winkler_score(
 788                                        obj=X_pred, actual=X_test_h, level=95
 789                                    )
 790                                    coveragecalc = coverage(
 791                                        X_pred, X_test_h, level=95
 792                                    )
 793                            else:
 794                                if isinstance(X_test, pd.DataFrame):
 795                                    X_test_h = X_test.iloc[0: self.h, :]
 796                                    rmse = mean_errors(
 797                                        actual=X_test_h,
 798                                        pred=X_pred,
 799                                        scoring="root_mean_squared_error",
 800                                        per_series=True,
 801                                    )
 802                                    mae = mean_errors(
 803                                        actual=X_test_h,
 804                                        pred=X_pred,
 805                                        scoring="mean_absolute_error",
 806                                        per_series=True,
 807                                    )
 808                                    mpl = mean_errors(
 809                                        actual=X_test_h,
 810                                        pred=X_pred,
 811                                        scoring="mean_pinball_loss",
 812                                        per_series=True,
 813                                    )
 814                                    winklerscore = winkler_score(
 815                                        obj=X_pred,
 816                                        actual=X_test_h,
 817                                        level=95,
 818                                        per_series=True,
 819                                    )
 820                                    coveragecalc = coverage(
 821                                        X_pred,
 822                                        X_test_h,
 823                                        level=95,
 824                                        per_series=True,
 825                                    )
 826                                else:
 827                                    X_test_h = X_test[0: self.h, :]
 828                                    rmse = mean_errors(
 829                                        actual=X_test_h,
 830                                        pred=X_pred,
 831                                        scoring="root_mean_squared_error",
 832                                        per_series=True,
 833                                    )
 834                                    mae = mean_errors(
 835                                        actual=X_test_h,
 836                                        pred=X_pred,
 837                                        scoring="mean_absolute_error",
 838                                        per_series=True,
 839                                    )
 840                                    mpl = mean_errors(
 841                                        actual=X_test_h,
 842                                        pred=X_pred,
 843                                        scoring="mean_pinball_loss",
 844                                        per_series=True,
 845                                    )
 846                                    winklerscore = winkler_score(
 847                                        obj=X_pred,
 848                                        actual=X_test_h,
 849                                        level=95,
 850                                        per_series=True,
 851                                    )
 852                                    coveragecalc = coverage(
 853                                        X_pred,
 854                                        X_test_h,
 855                                        level=95,
 856                                        per_series=True,
 857                                    )
 858                        else:  # no prediction interval
 859                            if per_series == False:
 860                                if isinstance(X_test, pd.DataFrame):
 861                                    X_test_h = X_test.iloc[0: self.h, :]
 862                                    rmse = mean_squared_error(
 863                                        X_test_h, X_pred, squared=False
 864                                    )
 865                                    mae = mean_absolute_error(X_test_h, X_pred)
 866                                    mpl = mean_pinball_loss(X_test_h, X_pred)
 867                                else:
 868                                    X_test_h = X_test[0: self.h, :]
 869                                    rmse = mean_squared_error(
 870                                        X_test_h, X_pred, squared=False
 871                                    )
 872                                    mae = mean_absolute_error(X_test_h, X_pred)
 873                                    mpl = mean_pinball_loss(X_test_h, X_pred)
 874                            else:
 875                                if isinstance(X_test, pd.DataFrame):
 876                                    X_test_h = X_test.iloc[0: self.h, :]
 877                                    rmse = mean_errors(
 878                                        actual=X_test_h,
 879                                        pred=X_pred,
 880                                        scoring="root_mean_squared_error",
 881                                        per_series=True,
 882                                    )
 883                                    mae = mean_errors(
 884                                        actual=X_test_h,
 885                                        pred=X_pred,
 886                                        scoring="mean_absolute_error",
 887                                        per_series=True,
 888                                    )
 889                                    mpl = mean_errors(
 890                                        actual=X_test_h,
 891                                        pred=X_pred,
 892                                        scoring="mean_pinball_loss",
 893                                        per_series=True,
 894                                    )
 895                                else:
 896                                    X_test_h = X_test[0: self.h, :]
 897                                    rmse = mean_errors(
 898                                        actual=X_test_h,
 899                                        pred=X_pred,
 900                                        scoring="root_mean_squared_error",
 901                                        per_series=True,
 902                                    )
 903                                    mae = mean_errors(
 904                                        actual=X_test_h,
 905                                        pred=X_pred,
 906                                        scoring="mean_absolute_error",
 907                                        per_series=True,
 908                                    )
 909
 910                    names.append(name)
 911                    RMSE.append(rmse)
 912                    MAE.append(mae)
 913                    MPL.append(mpl)
 914                    if (self.replications is not None) or (
 915                        self.type_pi == "gaussian"
 916                    ):
 917                        WINKLERSCORE.append(winklerscore)
 918                        COVERAGE.append(coveragecalc)
 919                    TIME.append(time.time() - start)
 920
 921                    if self.custom_metric:
 922                        if self.h is None:
 923                            custom_metric = self.custom_metric(X_test, X_pred)
 924                        else:
 925                            custom_metric = self.custom_metric(X_test_h, X_pred)
 926
 927                        CUSTOM_METRIC.append(custom_metric)
 928
 929                    if self.verbose > 0:
 930                        if (self.replications is not None) or (
 931                            self.type_pi == "gaussian"
 932                        ):
 933                            scores_verbose = {
 934                                "Model": name,
 935                                "RMSE": rmse,
 936                                "MAE": mae,
 937                                "MPL": mpl,
 938                                "WINKLERSCORE": winklerscore,
 939                                "COVERAGE": coveragecalc,
 940                                "Time taken": time.time() - start,
 941                            }
 942                        else:
 943                            scores_verbose = {
 944                                "Model": name,
 945                                "RMSE": rmse,
 946                                "MAE": mae,
 947                                "MPL": mpl,
 948                                "Time taken": time.time() - start,
 949                            }
 950
 951                        if self.custom_metric:
 952                            scores_verbose[self.custom_metric.__name__] = (
 953                                custom_metric
 954                            )
 955
 956                        print(scores_verbose)
 957
 958                    if self.predictions:
 959                        predictions[name] = X_pred
 960
 961                except Exception as exception:
 962                    if self.ignore_warnings is False:
 963                        print(name + " model failed to execute")
 964                        print(exception)
 965
 966        if (self.replications is not None) or (self.type_pi == "gaussian"):
 967            scores = {
 968                "Model": names,
 969                "RMSE": RMSE,
 970                "MAE": MAE,
 971                "MPL": MPL,
 972                "WINKLERSCORE": WINKLERSCORE,
 973                "COVERAGE": COVERAGE,
 974                "Time Taken": TIME,
 975            }
 976        else:
 977            scores = {
 978                "Model": names,
 979                "RMSE": RMSE,
 980                "MAE": MAE,
 981                "MPL": MPL,
 982                "Time Taken": TIME,
 983            }
 984
 985        if self.custom_metric:
 986            scores[self.custom_metric.__name__] = CUSTOM_METRIC
 987
 988        if per_series:
 989            scores = dict_to_dataframe_series(scores, self.series_names)
 990        else:
 991            scores = pd.DataFrame(scores)
 992
 993        try:
 994            scores = scores.sort_values(
 995                by=self.sort_by, ascending=True
 996            ).set_index("Model")
 997        except:
 998            pass
 999
1000        if self.predictions:
1001            predictions_df = pd.DataFrame.from_dict(predictions)
1002
1003        return scores, predictions_df if self.predictions is True else scores

Fit Regression algorithms to X_train, predict and score on X_test.

Parameters:

X_train: array-like or data frame,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test: array-like or data frame,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

xreg: array-like, optional (default=None)
    Additional (external) regressors to be passed to self.obj
    xreg must be in 'increasing' order (most recent observations last)

per_series: bool, optional (default=False)
    When set to True, the metrics are computed series by series.

**kwargs: dict, optional (default=None)
    Additional parameters to be passed to `fit` method of `obj`.

Returns:

scores: Pandas DataFrame
    Returns metrics of all the models in a Pandas DataFrame.

predictions: Pandas DataFrame
    Returns predictions of all the models in a Pandas DataFrame.
def provide_models(self, X_train, X_test):
1005    def provide_models(self, X_train, X_test):
1006        """
1007        This function returns all the model objects trained in fit function.
1008        If fit is not called already, then we call fit and then return the models.
1009
1010        Parameters:
1011
1012            X_train : array-like,
1013                Training vectors, where rows is the number of samples
1014                and columns is the number of features.
1015
1016            X_test : array-like,
1017                Testing vectors, where rows is the number of samples
1018                and columns is the number of features.
1019
1020        Returns:
1021
1022            models: dict-object,
1023                Returns a dictionary with each model pipeline as value
1024                with key as name of models.
1025
1026        """
1027        if self.h is None:
1028            if len(self.models.keys()) == 0:
1029                self.fit(X_train, X_test)
1030        else:
1031            if len(self.models.keys()) == 0:
1032                if isinstance(X_test, pd.DataFrame):
1033                    self.fit(X_train, X_test.iloc[0: self.h, :])
1034                else:
1035                    self.fit(X_train, X_test[0: self.h, :])
1036
1037        return self.models

This function returns all the model objects trained in fit function. If fit is not called already, then we call fit and then return the models.

Parameters:

X_train : array-like,
    Training vectors, where rows is the number of samples
    and columns is the number of features.

X_test : array-like,
    Testing vectors, where rows is the number of samples
    and columns is the number of features.

Returns:

models: dict-object,
    Returns a dictionary with each model pipeline as value
    with key as name of models.
class MTS(nnetsauce.Base):
  33class MTS(Base):
  34    """Univariate and multivariate time series (MTS) forecasting with Quasi-Randomized networks
  35
  36    Parameters:
  37
  38        obj: object.
  39            any object containing a method fit (obj.fit()) and a method predict
  40            (obj.predict()).
  41
  42        n_hidden_features: int.
  43            number of nodes in the hidden layer.
  44
  45        activation_name: str.
  46            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'.
  47
  48        a: float.
  49            hyperparameter for 'prelu' or 'elu' activation function.
  50
  51        nodes_sim: str.
  52            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
  53            'uniform'.
  54
  55        bias: boolean.
  56            indicates if the hidden layer contains a bias term (True) or not
  57            (False).
  58
  59        dropout: float.
  60            regularization parameter; (random) percentage of nodes dropped out
  61            of the training.
  62
  63        direct_link: boolean.
  64            indicates if the original predictors are included (True) in model's fitting or not (False).
  65
  66        n_clusters: int.
  67            number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering).
  68
  69        cluster_encode: bool.
  70            defines how the variable containing clusters is treated (default is one-hot)
  71            if `False`, then labels are used, without one-hot encoding.
  72
  73        type_clust: str.
  74            type of clustering method: currently k-means ('kmeans') or Gaussian
  75            Mixture Model ('gmm').
  76
  77        type_scaling: a tuple of 3 strings.
  78            scaling methods for inputs, hidden layer, and clustering respectively
  79            (and when relevant).
  80            Currently available: standardization ('std') or MinMax scaling ('minmax').
  81
  82        lags: int.
  83            number of lags used for each time series.
  84
  85        type_pi: str.
  86            type of prediction interval; currently:
  87            - "gaussian": simple, fast, but: assumes stationarity of Gaussian in-sample residuals and independence in the multivariate case
  88            - "kde": based on Kernel Density Estimation of in-sample residuals
  89            - "bootstrap": based on independent bootstrap of in-sample residuals
  90            - "block-bootstrap": based on basic block bootstrap of in-sample residuals
  91            - "scp-kde": Sequential split conformal prediction with Kernel Density Estimation of calibrated residuals
  92            - "scp-bootstrap": Sequential split conformal prediction with independent bootstrap of calibrated residuals
  93            - "scp-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of calibrated residuals
  94            - "scp2-kde": Sequential split conformal prediction with Kernel Density Estimation of standardized calibrated residuals
  95            - "scp2-bootstrap": Sequential split conformal prediction with independent bootstrap of standardized calibrated residuals
  96            - "scp2-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of standardized calibrated residuals
  97            - based on copulas of in-sample residuals: 'vine-tll', 'vine-bb1', 'vine-bb6', 'vine-bb7', 'vine-bb8', 'vine-clayton',
  98            'vine-frank', 'vine-gaussian', 'vine-gumbel', 'vine-indep', 'vine-joe', 'vine-student'
  99            - 'scp-vine-tll', 'scp-vine-bb1', 'scp-vine-bb6', 'scp-vine-bb7', 'scp-vine-bb8', 'scp-vine-clayton',
 100            'scp-vine-frank', 'scp-vine-gaussian', 'scp-vine-gumbel', 'scp-vine-indep', 'scp-vine-joe', 'scp-vine-student'
 101            - 'scp2-vine-tll', 'scp2-vine-bb1', 'scp2-vine-bb6', 'scp2-vine-bb7', 'scp2-vine-bb8', 'scp2-vine-clayton',
 102            'scp2-vine-frank', 'scp2-vine-gaussian', 'scp2-vine-gumbel', 'scp2-vine-indep', 'scp2-vine-joe', 'scp2-vine-student'
 103
 104        block_size: int.
 105            size of block for 'type_pi' in ("block-bootstrap", "scp-block-bootstrap", "scp2-block-bootstrap").
 106            Default is round(3.15*(n_residuals^1/3))
 107
 108        replications: int.
 109            number of replications (if needed, for predictive simulation). Default is 'None'.
 110
 111        kernel: str.
 112            the kernel to use for residuals density estimation (used for predictive simulation). Currently, either 'gaussian' or 'tophat'.
 113
 114        agg: str.
 115            either "mean" or "median" for simulation of bootstrap aggregating
 116
 117        seed: int.
 118            reproducibility seed for nodes_sim=='uniform' or predictive simulation.
 119
 120        backend: str.
 121            "cpu" or "gpu" or "tpu".
 122
 123        verbose: int.
 124            0: not printing; 1: printing
 125
 126        show_progress: bool.
 127            True: progress bar when fitting each series; False: no progress bar when fitting each series
 128
 129    Attributes:
 130
 131        fit_objs_: dict
 132            objects adjusted to each individual time series
 133
 134        y_: {array-like}
 135            MTS responses (most recent observations first)
 136
 137        X_: {array-like}
 138            MTS lags
 139
 140        xreg_: {array-like}
 141            external regressors
 142
 143        y_means_: dict
 144            a dictionary of each series mean values
 145
 146        preds_: {array-like}
 147            successive model predictions
 148
 149        preds_std_: {array-like}
 150            standard deviation around the predictions for Bayesian base learners (`obj`)
 151
 152        gaussian_preds_std_: {array-like}
 153            standard deviation around the predictions for `type_pi='gaussian'`
 154
 155        return_std_: boolean
 156            return uncertainty or not (set in predict)
 157
 158        df_: data frame
 159            the input data frame, in case a data.frame is provided to `fit`
 160
 161        n_obs_: int
 162            number of time series observations (number of rows for multivariate)
 163
 164        level_: int
 165            level of confidence for prediction intervals (default is 95)
 166
 167        residuals_: {array-like}
 168            in-sample residuals (for `type_pi` not conformal prediction) or calibrated residuals
 169            (for `type_pi` in conformal prediction)
 170
 171        residuals_sims_: tuple of {array-like}
 172            simulations of in-sample residuals (for `type_pi` not conformal prediction) or
 173            calibrated residuals (for `type_pi` in conformal prediction)
 174
 175        kde_: A scikit-learn object, see https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KernelDensity.html
 176
 177        residuals_std_dev_: residuals standard deviation
 178
 179    Examples:
 180
 181    Example 1:
 182
 183    ```python
 184    import nnetsauce as ns
 185    import numpy as np
 186    from sklearn import linear_model
 187    np.random.seed(123)
 188
 189    M = np.random.rand(10, 3)
 190    M[:,0] = 10*M[:,0]
 191    M[:,2] = 25*M[:,2]
 192    print(M)
 193
 194    # Adjust Bayesian Ridge
 195    regr4 = linear_model.BayesianRidge()
 196    obj_MTS = ns.MTS(regr4, lags = 1, n_hidden_features=5)
 197    obj_MTS.fit(M)
 198    print(obj_MTS.predict())
 199
 200    # with credible intervals
 201    print(obj_MTS.predict(return_std=True, level=80))
 202
 203    print(obj_MTS.predict(return_std=True, level=95))
 204    ```
 205
 206    Example 2:
 207
 208    ```python
 209    import nnetsauce as ns
 210    import numpy as np
 211    from sklearn import linear_model
 212
 213    dataset = {
 214    'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'],
 215    'series1' : [34, 30, 35.6, 33.3, 38.1],
 216    'series2' : [4, 5.5, 5.6, 6.3, 5.1],
 217    'series3' : [100, 100.5, 100.6, 100.2, 100.1]}
 218    df = pd.DataFrame(dataset).set_index('date')
 219    print(df)
 220
 221    # Adjust Bayesian Ridge
 222    regr5 = linear_model.BayesianRidge()
 223    obj_MTS = ns.MTS(regr5, lags = 1, n_hidden_features=5)
 224    obj_MTS.fit(df)
 225    print(obj_MTS.predict())
 226
 227    # with credible intervals
 228    print(obj_MTS.predict(return_std=True, level=80))
 229
 230    print(obj_MTS.predict(return_std=True, level=95))
 231    ```
 232    """
 233
 234    # construct the object -----
 235
 236    def __init__(
 237        self,
 238        obj,
 239        n_hidden_features=5,
 240        activation_name="relu",
 241        a=0.01,
 242        nodes_sim="sobol",
 243        bias=True,
 244        dropout=0,
 245        direct_link=True,
 246        n_clusters=2,
 247        cluster_encode=True,
 248        type_clust="kmeans",
 249        type_scaling=("std", "std", "std"),
 250        lags=1,
 251        type_pi="kde",
 252        block_size=None,
 253        replications=None,
 254        kernel="gaussian",
 255        agg="mean",
 256        seed=123,
 257        backend="cpu",
 258        verbose=0,
 259        show_progress=True,
 260    ):
 261        assert int(lags) == lags, "parameter 'lags' should be an integer"
 262
 263        super().__init__(
 264            n_hidden_features=n_hidden_features,
 265            activation_name=activation_name,
 266            a=a,
 267            nodes_sim=nodes_sim,
 268            bias=bias,
 269            dropout=dropout,
 270            direct_link=direct_link,
 271            n_clusters=n_clusters,
 272            cluster_encode=cluster_encode,
 273            type_clust=type_clust,
 274            type_scaling=type_scaling,
 275            seed=seed,
 276            backend=backend,
 277        )
 278
 279        self.obj = obj
 280        self.n_series = None
 281        self.lags = lags
 282        self.type_pi = type_pi
 283        self.block_size = block_size
 284        self.replications = replications
 285        self.kernel = kernel
 286        self.agg = agg
 287        self.verbose = verbose
 288        self.show_progress = show_progress
 289        self.series_names = None
 290        self.input_dates = None
 291        self.fit_objs_ = {}
 292        self.y_ = None  # MTS responses (most recent observations first)
 293        self.X_ = None  # MTS lags
 294        self.xreg_ = None
 295        self.y_means_ = {}
 296        self.mean_ = None
 297        self.upper_ = None
 298        self.lower_ = None
 299        self.output_dates_ = None
 300        self.preds_std_ = []
 301        self.gaussian_preds_std_ = None
 302        self.alpha_ = None
 303        self.return_std_ = None
 304        self.df_ = None
 305        self.residuals_ = []
 306        self.abs_calib_residuals_ = None
 307        self.calib_residuals_quantile_ = None
 308        self.residuals_sims_ = None
 309        self.kde_ = None
 310        self.sims_ = None
 311        self.residuals_std_dev_ = None
 312        self.n_obs_ = None
 313        self.level_ = None
 314
 315    def fit(self, X, xreg=None, **kwargs):
 316        """Fit MTS model to training data X, with optional regressors xreg
 317
 318        Parameters:
 319
 320        X: {array-like}, shape = [n_samples, n_features]
 321            Training time series, where n_samples is the number
 322            of samples and n_features is the number of features;
 323            X must be in increasing order (most recent observations last)
 324
 325        xreg: {array-like}, shape = [n_samples, n_features_xreg]
 326            Additional (external) regressors to be passed to self.obj
 327            xreg must be in 'increasing' order (most recent observations last)
 328
 329        **kwargs: for now, additional parameters to be passed to for kernel density estimation, when needed (see sklearn.neighbors.KernelDensity)
 330
 331        Returns:
 332
 333        self: object
 334        """
 335
 336        if (
 337            isinstance(X, pd.DataFrame) is False
 338        ):  # input data set is a numpy array
 339
 340            if xreg is None:
 341                X = pd.DataFrame(X)
 342                self.series_names = [
 343                    "series" + str(i) for i in range(X.shape[1])
 344                ]
 345            else:  # xreg is not None
 346                X = mo.cbind(X, xreg)
 347                self.xreg_ = xreg
 348
 349        else:  # input data set is a DataFrame with column names
 350
 351            X_index = None
 352            if X.index is not None:
 353                X_index = X.index
 354            if xreg is None:
 355                X = copy.deepcopy(mo.convert_df_to_numeric(X))
 356            else:
 357                X = copy.deepcopy(mo.cbind(mo.convert_df_to_numeric(X), xreg))
 358                self.xreg_ = xreg
 359            if X_index is not None:
 360                X.index = X_index
 361            self.series_names = X.columns.tolist()
 362
 363        if isinstance(X, pd.DataFrame):
 364            self.df_ = X
 365            X = X.values
 366            self.df_.columns = self.series_names
 367            self.input_dates = ts.compute_input_dates(self.df_)
 368        else:
 369            self.df_ = pd.DataFrame(X, columns=self.series_names)
 370            self.input_dates = ts.compute_input_dates(self.df_)
 371
 372        try:
 373            # multivariate time series
 374            n, p = X.shape
 375        except:
 376            # univariate time series
 377            n = X.shape[0]
 378            p = 1
 379
 380        self.n_obs_ = n
 381
 382        rep_1_n = np.repeat(1, n)
 383
 384        self.y_ = None
 385        self.X_ = None
 386        self.n_series = p
 387        self.fit_objs_.clear()
 388        self.y_means_.clear()
 389        residuals_ = []
 390        self.residuals_ = None
 391        self.residuals_sims_ = None
 392        self.kde_ = None
 393        self.sims_ = None
 394        self.scaled_Z_ = None
 395        self.centered_y_is_ = []
 396
 397        if p > 1:
 398            # multivariate time series
 399            mts_input = ts.create_train_inputs(X[::-1], self.lags)
 400        else:
 401            # univariate time series
 402            mts_input = ts.create_train_inputs(
 403                X.reshape(-1, 1)[::-1], self.lags
 404            )
 405
 406        self.y_ = mts_input[0]
 407
 408        self.X_ = mts_input[1]
 409
 410        dummy_y, scaled_Z = self.cook_training_set(y=rep_1_n, X=self.X_)
 411
 412        self.scaled_Z_ = scaled_Z
 413
 414        # loop on all the time series and adjust self.obj.fit
 415        if self.verbose > 0:
 416            print(
 417                f"\n Adjusting {type(self.obj).__name__} to multivariate time series... \n "
 418            )
 419
 420        if self.show_progress is True:
 421            iterator = tqdm(range(p))
 422        else:
 423            iterator = range(p)
 424
 425        if self.type_pi in (
 426            "gaussian",
 427            "kde",
 428            "bootstrap",
 429            "block-bootstrap",
 430        ) or self.type_pi.startswith("vine"):
 431            for i in iterator:
 432                y_mean = np.mean(self.y_[:, i])
 433                self.y_means_[i] = y_mean
 434                centered_y_i = self.y_[:, i] - y_mean
 435                self.centered_y_is_.append(centered_y_i)
 436                self.obj.fit(X=scaled_Z, y=centered_y_i)
 437                self.fit_objs_[i] = deepcopy(self.obj)
 438                residuals_.append(
 439                    (
 440                        centered_y_i - self.fit_objs_[i].predict(scaled_Z)
 441                    ).tolist()
 442                )
 443
 444        if self.type_pi.startswith("scp"):
 445            # split conformal prediction
 446            for i in iterator:
 447                n_y = self.y_.shape[0]
 448                n_y_half = n_y // 2
 449                first_half_idx = range(0, n_y_half)
 450                second_half_idx = range(n_y_half, n_y)
 451                y_mean_temp = np.mean(self.y_[first_half_idx, i])
 452                centered_y_i_temp = self.y_[first_half_idx, i] - y_mean_temp
 453                self.obj.fit(X=scaled_Z[first_half_idx, :], y=centered_y_i_temp)
 454                # calibrated residuals actually
 455                residuals_.append(
 456                    (
 457                        self.y_[second_half_idx, i]
 458                        - (
 459                            y_mean_temp
 460                            + self.obj.predict(scaled_Z[second_half_idx, :])
 461                        )
 462                    ).tolist()
 463                )
 464                # fit on the second half
 465                y_mean = np.mean(self.y_[second_half_idx, i])
 466                self.y_means_[i] = y_mean
 467                centered_y_i = self.y_[second_half_idx, i] - y_mean
 468                self.obj.fit(X=scaled_Z[second_half_idx, :], y=centered_y_i)
 469                self.fit_objs_[i] = deepcopy(self.obj)
 470
 471        self.residuals_ = np.asarray(residuals_).T
 472
 473        if self.type_pi == "gaussian":
 474            self.gaussian_preds_std_ = np.std(self.residuals_, axis=0)
 475
 476        if self.type_pi.startswith("scp2"):
 477            # Calculate mean and standard deviation for each column
 478            data_mean = np.mean(self.residuals_, axis=0)
 479            self.residuals_std_dev_ = np.std(self.residuals_, axis=0)
 480            # Center and scale the array using broadcasting
 481            self.residuals_ = (
 482                self.residuals_ - data_mean[np.newaxis, :]
 483            ) / self.residuals_std_dev_[np.newaxis, :]
 484
 485        if self.replications != None and "kde" in self.type_pi:
 486            if self.verbose > 0:
 487                print(f"\n Simulate residuals using {self.kernel} kernel... \n")
 488            assert self.kernel in (
 489                "gaussian",
 490                "tophat",
 491            ), "currently, 'kernel' must be either 'gaussian' or 'tophat'"
 492            kernel_bandwidths = {"bandwidth": np.logspace(-6, 6, 150)}
 493            grid = GridSearchCV(
 494                KernelDensity(kernel=self.kernel, **kwargs),
 495                param_grid=kernel_bandwidths,
 496            )
 497            grid.fit(self.residuals_)
 498
 499            if self.verbose > 0:
 500                print(
 501                    f"\n Best parameters for {self.kernel} kernel: {grid.best_params_} \n"
 502                )
 503
 504            self.kde_ = grid.best_estimator_
 505
 506        return self
 507
 508    def predict(self, h=5, level=95, **kwargs):
 509        """Forecast all the time series, h steps ahead
 510
 511        Parameters:
 512
 513        h: {integer}
 514            Forecasting horizon
 515
 516        level: {integer}
 517            Level of confidence (if obj has option 'return_std' and the
 518            posterior is gaussian)
 519
 520        new_xreg: {array-like}, shape = [n_samples = h, n_new_xreg]
 521            New values of additional (deterministic) regressors on horizon = h
 522            new_xreg must be in increasing order (most recent observations last)
 523
 524        **kwargs: additional parameters to be passed to
 525                self.cook_test_set
 526
 527        Returns:
 528
 529        model predictions for horizon = h: {array-like}, data frame or tuple.
 530        Standard deviation and prediction intervals are returned when
 531        `obj.predict` can return standard deviation
 532
 533        """
 534
 535        self.output_dates_, frequency = ts.compute_output_dates(self.df_, h)
 536
 537        self.level_ = level
 538
 539        self.return_std_ = False  # do not remove (/!\)
 540
 541        self.mean_ = None  # do not remove (/!\)
 542
 543        self.mean_ = deepcopy(self.y_)  # do not remove (/!\)
 544
 545        self.lower_ = None  # do not remove (/!\)
 546
 547        self.upper_ = None  # do not remove (/!\)
 548
 549        self.sims_ = None  # do not remove (/!\)
 550
 551        y_means_ = np.asarray([self.y_means_[i] for i in range(self.n_series)])
 552
 553        n_features = self.n_series * self.lags
 554
 555        self.alpha_ = 100 - level
 556
 557        pi_multiplier = norm.ppf(1 - self.alpha_ / 200)
 558
 559        if "return_std" in kwargs:  # bayesian forecasting
 560            self.return_std_ = True
 561            self.preds_std_ = []
 562            DescribeResult = namedtuple(
 563                "DescribeResult", ("mean", "lower", "upper")
 564            )  # to be updated
 565
 566        if "return_pi" in kwargs:  # split conformal, without simulation
 567            mean_pi_ = []
 568            lower_pi_ = []
 569            upper_pi_ = []
 570            DescribeResult = namedtuple(
 571                "DescribeResult", ("mean", "lower", "upper")
 572            )  # to be updated
 573
 574        if self.kde_ != None and "kde" in self.type_pi:  # kde
 575            if self.verbose == 1:
 576                self.residuals_sims_ = tuple(
 577                    self.kde_.sample(
 578                        n_samples=h, random_state=self.seed + 100 * i
 579                    )
 580                    for i in tqdm(range(self.replications))
 581                )
 582            elif self.verbose == 0:
 583                self.residuals_sims_ = tuple(
 584                    self.kde_.sample(
 585                        n_samples=h, random_state=self.seed + 100 * i
 586                    )
 587                    for i in range(self.replications)
 588                )
 589
 590        if self.type_pi in ("bootstrap", "scp-bootstrap", "scp2-bootstrap"):
 591            assert self.replications is not None and isinstance(
 592                self.replications, int
 593            ), "'replications' must be provided and be an integer"
 594            if self.verbose == 1:
 595                self.residuals_sims_ = tuple(
 596                    ts.bootstrap(
 597                        self.residuals_,
 598                        h=h,
 599                        block_size=None,
 600                        seed=self.seed + 100 * i,
 601                    )
 602                    for i in tqdm(range(self.replications))
 603                )
 604            elif self.verbose == 0:
 605                self.residuals_sims_ = tuple(
 606                    ts.bootstrap(
 607                        self.residuals_,
 608                        h=h,
 609                        block_size=None,
 610                        seed=self.seed + 100 * i,
 611                    )
 612                    for i in range(self.replications)
 613                )
 614
 615        if self.type_pi in (
 616            "block-bootstrap",
 617            "scp-block-bootstrap",
 618            "scp2-block-bootstrap",
 619        ):
 620            if self.block_size is None:
 621                self.block_size = int(
 622                    np.ceil(3.15 * (self.residuals_.shape[0] ** (1 / 3)))
 623                )
 624
 625            assert self.replications is not None and isinstance(
 626                self.replications, int
 627            ), "'replications' must be provided and be an integer"
 628            if self.verbose == 1:
 629                self.residuals_sims_ = tuple(
 630                    ts.bootstrap(
 631                        self.residuals_,
 632                        h=h,
 633                        block_size=self.block_size,
 634                        seed=self.seed + 100 * i,
 635                    )
 636                    for i in tqdm(range(self.replications))
 637                )
 638            elif self.verbose == 0:
 639                self.residuals_sims_ = tuple(
 640                    ts.bootstrap(
 641                        self.residuals_,
 642                        h=h,
 643                        block_size=self.block_size,
 644                        seed=self.seed + 100 * i,
 645                    )
 646                    for i in range(self.replications)
 647                )
 648
 649        if "vine" in self.type_pi:
 650            if self.verbose == 1:
 651                self.residuals_sims_ = tuple(
 652                    vinecopula_sample(
 653                        x=self.residuals_,
 654                        n_samples=h,
 655                        method=self.type_pi,
 656                        random_state=self.seed + 100 * i,
 657                    )
 658                    for i in tqdm(range(self.replications))
 659                )
 660            elif self.verbose == 0:
 661                self.residuals_sims_ = tuple(
 662                    vinecopula_sample(
 663                        x=self.residuals_,
 664                        n_samples=h,
 665                        method=self.type_pi,
 666                        random_state=self.seed + 100 * i,
 667                    )
 668                    for i in range(self.replications)
 669                )
 670
 671        for _ in range(h):
 672
 673            new_obs = ts.reformat_response(self.mean_, self.lags)
 674
 675            new_X = new_obs.reshape(1, n_features)
 676
 677            cooked_new_X = self.cook_test_set(new_X, **kwargs)
 678
 679            if "return_std" in kwargs:
 680                self.preds_std_.append(
 681                    [
 682                        np.asarray(
 683                            self.fit_objs_[i].predict(
 684                                cooked_new_X, return_std=True
 685                            )[1]
 686                        ).item()
 687                        for i in range(self.n_series)
 688                    ]
 689                )
 690
 691            if "return_pi" in kwargs:
 692                for i in range(self.n_series):
 693                    preds_pi = self.fit_objs_[i].predict(
 694                        cooked_new_X, return_pi=True
 695                    )
 696                    mean_pi_.append(preds_pi.mean[0])
 697                    lower_pi_.append(preds_pi.lower[0])
 698                    upper_pi_.append(preds_pi.upper[0])
 699
 700            predicted_cooked_new_X = np.asarray(
 701                [
 702                    np.asarray(self.fit_objs_[i].predict(cooked_new_X)).item()
 703                    for i in range(self.n_series)
 704                ]
 705            )
 706
 707            preds = np.asarray(y_means_ + predicted_cooked_new_X)
 708
 709            self.mean_ = mo.rbind(preds, self.mean_)  # preallocate?
 710
 711        # function's return ----------------------------------------------------------------------
 712        self.mean_ = pd.DataFrame(
 713            self.mean_[0:h, :][::-1],
 714            columns=self.df_.columns,
 715            index=self.output_dates_,
 716        )
 717
 718        if (
 719            (("return_std" not in kwargs) and ("return_pi" not in kwargs))
 720            and (self.type_pi not in ("gaussian", "scp"))
 721        ) or ("vine" in self.type_pi):
 722
 723            if self.replications is None:
 724                return self.mean_
 725
 726            # if "return_std" not in kwargs and self.replications is not None
 727            meanf = []
 728            lower = []
 729            upper = []
 730
 731            if "scp2" in self.type_pi:
 732
 733                if self.verbose == 1:
 734                    self.sims_ = tuple(
 735                        (
 736                            self.mean_
 737                            + self.residuals_sims_[i]
 738                            * self.residuals_std_dev_[np.newaxis, :]
 739                            for i in tqdm(range(self.replications))
 740                        )
 741                    )
 742                elif self.verbose == 0:
 743                    self.sims_ = tuple(
 744                        (
 745                            self.mean_
 746                            + self.residuals_sims_[i]
 747                            * self.residuals_std_dev_[np.newaxis, :]
 748                            for i in range(self.replications)
 749                        )
 750                    )
 751            else:
 752
 753                if self.verbose == 1:
 754                    self.sims_ = tuple(
 755                        (
 756                            self.mean_ + self.residuals_sims_[i]
 757                            for i in tqdm(range(self.replications))
 758                        )
 759                    )
 760                elif self.verbose == 0:
 761                    self.sims_ = tuple(
 762                        (
 763                            self.mean_ + self.residuals_sims_[i]
 764                            for i in range(self.replications)
 765                        )
 766                    )
 767
 768            DescribeResult = namedtuple(
 769                "DescribeResult", ("mean", "sims", "lower", "upper")
 770            )
 771            for ix in range(self.n_series):
 772                sims_ix = getsims(self.sims_, ix)
 773                if self.agg == "mean":
 774                    meanf.append(np.mean(sims_ix, axis=1))
 775                else:
 776                    meanf.append(np.median(sims_ix, axis=1))
 777                lower.append(np.quantile(sims_ix, q=self.alpha_ / 200, axis=1))
 778                upper.append(
 779                    np.quantile(sims_ix, q=1 - self.alpha_ / 200, axis=1)
 780                )
 781
 782            self.mean_ = pd.DataFrame(
 783                np.asarray(meanf).T,
 784                columns=self.series_names,  # self.df_.columns,
 785                index=self.output_dates_,
 786            )
 787
 788            self.lower_ = pd.DataFrame(
 789                np.asarray(lower).T,
 790                columns=self.series_names,  # self.df_.columns,
 791                index=self.output_dates_,
 792            )
 793
 794            self.upper_ = pd.DataFrame(
 795                np.asarray(upper).T,
 796                columns=self.series_names,  # self.df_.columns,
 797                index=self.output_dates_,
 798            )
 799
 800            res = DescribeResult(
 801                self.mean_, self.sims_, self.lower_, self.upper_
 802            )
 803
 804            if self.xreg_ is not None:
 805
 806                if len(self.xreg_.shape) > 1:
 807
 808                    res2 = mx.tuple_map(
 809                        res,
 810                        lambda x: mo.delete_last_columns(
 811                            x, num_columns=self.xreg_.shape[1]
 812                        ),
 813                    )
 814
 815                else:
 816
 817                    res2 = mx.tuple_map(
 818                        res, lambda x: mo.delete_last_columns(x, num_columns=1)
 819                    )
 820
 821                return res2
 822
 823            else:
 824
 825                return res
 826
 827        if (
 828            (("return_std" in kwargs) or ("return_pi" in kwargs))
 829            and (self.type_pi not in ("gaussian", "scp"))
 830        ) or "vine" in self.type_pi:
 831            DescribeResult = namedtuple(
 832                "DescribeResult", ("mean", "lower", "upper")
 833            )
 834
 835            self.mean_ = pd.DataFrame(
 836                np.asarray(self.mean_),
 837                columns=self.series_names,  # self.df_.columns,
 838                index=self.output_dates_,
 839            )
 840
 841            if "return_std" in kwargs:
 842
 843                self.preds_std_ = np.asarray(self.preds_std_)
 844
 845                self.lower_ = pd.DataFrame(
 846                    self.mean_.values - pi_multiplier * self.preds_std_,
 847                    columns=self.series_names,  # self.df_.columns,
 848                    index=self.output_dates_,
 849                )
 850
 851                self.upper_ = pd.DataFrame(
 852                    self.mean_.values + pi_multiplier * self.preds_std_,
 853                    columns=self.series_names,  # self.df_.columns,
 854                    index=self.output_dates_,
 855                )
 856
 857            if "return_pi" in kwargs:
 858
 859                self.lower_ = pd.DataFrame(
 860                    np.asarray(lower_pi_).reshape(h, self.n_series)
 861                    + y_means_[np.newaxis, :],
 862                    columns=self.series_names,  # self.df_.columns,
 863                    index=self.output_dates_,
 864                )
 865
 866                self.upper_ = pd.DataFrame(
 867                    np.asarray(upper_pi_).reshape(h, self.n_series)
 868                    + y_means_[np.newaxis, :],
 869                    columns=self.series_names,  # self.df_.columns,
 870                    index=self.output_dates_,
 871                )
 872
 873            res = DescribeResult(self.mean_, self.lower_, self.upper_)
 874
 875            if self.xreg_ is not None:
 876                if len(self.xreg_.shape) > 1:
 877                    res2 = mx.tuple_map(
 878                        res,
 879                        lambda x: mo.delete_last_columns(
 880                            x, num_columns=self.xreg_.shape[1]
 881                        ),
 882                    )
 883                else:
 884                    res2 = mx.tuple_map(
 885                        res, lambda x: mo.delete_last_columns(x, num_columns=1)
 886                    )
 887                return DescribeResult(res2[0], res2[1], res2[2])
 888
 889            return res
 890
 891        if self.type_pi == "gaussian":
 892
 893            DescribeResult = namedtuple(
 894                "DescribeResult", ("mean", "lower", "upper")
 895            )
 896
 897            self.mean_ = pd.DataFrame(
 898                np.asarray(self.mean_),
 899                columns=self.series_names,  # self.df_.columns,
 900                index=self.output_dates_,
 901            )
 902
 903            self.lower_ = pd.DataFrame(
 904                self.mean_.values - pi_multiplier * self.gaussian_preds_std_,
 905                columns=self.series_names,  # self.df_.columns,
 906                index=self.output_dates_,
 907            )
 908
 909            self.upper_ = pd.DataFrame(
 910                self.mean_.values + pi_multiplier * self.gaussian_preds_std_,
 911                columns=self.series_names,  # self.df_.columns,
 912                index=self.output_dates_,
 913            )
 914
 915            res = DescribeResult(self.mean_, self.lower_, self.upper_)
 916
 917            if self.xreg_ is not None:
 918                if len(self.xreg_.shape) > 1:
 919                    res2 = mx.tuple_map(
 920                        res,
 921                        lambda x: mo.delete_last_columns(
 922                            x, num_columns=self.xreg_.shape[1]
 923                        ),
 924                    )
 925                else:
 926                    res2 = mx.tuple_map(
 927                        res, lambda x: mo.delete_last_columns(x, num_columns=1)
 928                    )
 929                return DescribeResult(res2[0], res2[1], res2[2])
 930
 931            return res
 932
 933    def score(self, X, training_index, testing_index, scoring=None, **kwargs):
 934        """Train on training_index, score on testing_index."""
 935
 936        assert (
 937            bool(set(training_index).intersection(set(testing_index))) == False
 938        ), "Non-overlapping 'training_index' and 'testing_index' required"
 939
 940        # Dimensions
 941        try:
 942            # multivariate time series
 943            n, p = X.shape
 944        except:
 945            # univariate time series
 946            n = X.shape[0]
 947            p = 1
 948
 949        # Training and testing sets
 950        if p > 1:
 951            X_train = X[training_index, :]
 952            X_test = X[testing_index, :]
 953        else:
 954            X_train = X[training_index]
 955            X_test = X[testing_index]
 956
 957        # Horizon
 958        h = len(testing_index)
 959        assert (
 960            len(training_index) + h
 961        ) <= n, "Please check lengths of training and testing windows"
 962
 963        # Fit and predict
 964        self.fit(X_train, **kwargs)
 965        preds = self.predict(h=h, **kwargs)
 966
 967        if scoring is None:
 968            scoring = "neg_root_mean_squared_error"
 969
 970        # check inputs
 971        assert scoring in (
 972            "explained_variance",
 973            "neg_mean_absolute_error",
 974            "neg_mean_squared_error",
 975            "neg_root_mean_squared_error",
 976            "neg_mean_squared_log_error",
 977            "neg_median_absolute_error",
 978            "r2",
 979        ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
 980                               'neg_mean_squared_error', 'neg_root_mean_squared_error', 'neg_mean_squared_log_error', \
 981                               'neg_median_absolute_error', 'r2')"
 982
 983        scoring_options = {
 984            "explained_variance": skm2.explained_variance_score,
 985            "neg_mean_absolute_error": skm2.mean_absolute_error,
 986            "neg_mean_squared_error": skm2.mean_squared_error,
 987            "neg_root_mean_squared_error": lambda x, y: np.sqrt(
 988                skm2.mean_squared_error(x, y)
 989            ),
 990            "neg_mean_squared_log_error": skm2.mean_squared_log_error,
 991            "neg_median_absolute_error": skm2.median_absolute_error,
 992            "r2": skm2.r2_score,
 993        }
 994
 995        # if p > 1:
 996        #     return tuple(
 997        #         [
 998        #             scoring_options[scoring](
 999        #                 X_test[:, i], preds[:, i]#, **kwargs
1000        #             )
1001        #             for i in range(p)
1002        #         ]
1003        #     )
1004        # else:
1005        return scoring_options[scoring](X_test, preds)
1006
1007    def plot(self, series=None, type_axis="dates", type_plot="pi"):
1008        """Plot time series forecast
1009
1010        Parameters:
1011
1012        series: {integer} or {string}
1013            series index or name
1014
1015        """
1016
1017        assert all(
1018            [
1019                self.mean_ is not None,
1020                self.lower_ is not None,
1021                self.upper_ is not None,
1022                self.output_dates_ is not None,
1023            ]
1024        ), "model forecasting must be obtained first (with predict)"
1025
1026        if series is None:
1027            assert (
1028                self.n_series == 1
1029            ), "please specify series index or name (n_series > 1)"
1030            series = 0
1031
1032        if isinstance(series, str):
1033            assert (
1034                series in self.series_names
1035            ), f"series {series} doesn't exist in the input dataset"
1036            series_idx = self.df_.columns.get_loc(series)
1037        else:
1038            assert isinstance(series, int) and (
1039                0 <= series < self.n_series
1040            ), f"check series index (< {self.n_series})"
1041            series_idx = series
1042
1043        y_all = list(self.df_.iloc[:, series_idx]) + list(
1044            self.mean_.iloc[:, series_idx]
1045        )
1046        y_test = list(self.mean_.iloc[:, series_idx])
1047        n_points_all = len(y_all)
1048        n_points_train = self.df_.shape[0]
1049
1050        if type_axis == "numeric":
1051            x_all = [i for i in range(n_points_all)]
1052            x_test = [i for i in range(n_points_train, n_points_all)]
1053
1054        if type_axis == "dates":  # use dates
1055            x_all = np.concatenate(
1056                (self.input_dates.values, self.output_dates_.values), axis=None
1057            )
1058            x_test = self.output_dates_.values
1059
1060        if type_plot == "pi":
1061            fig, ax = plt.subplots()
1062            ax.plot(x_all, y_all, "-")
1063            ax.plot(x_test, y_test, "-", color="orange")
1064            ax.fill_between(
1065                x_test,
1066                self.lower_.iloc[:, series_idx],
1067                self.upper_.iloc[:, series_idx],
1068                alpha=0.2,
1069                color="orange",
1070            )
1071            if self.replications is None:
1072                if self.n_series > 1:
1073                    plt.title(
1074                        f"prediction intervals for {series}",
1075                        loc="left",
1076                        fontsize=12,
1077                        fontweight=0,
1078                        color="black",
1079                    )
1080                else:
1081                    plt.title(
1082                        f"prediction intervals for input time series",
1083                        loc="left",
1084                        fontsize=12,
1085                        fontweight=0,
1086                        color="black",
1087                    )
1088                plt.show()
1089            else:  # self.replications is not None
1090                if self.n_series > 1:
1091                    plt.title(
1092                        f"prediction intervals for {self.replications} simulations of {series}",
1093                        loc="left",
1094                        fontsize=12,
1095                        fontweight=0,
1096                        color="black",
1097                    )
1098                else:
1099                    plt.title(
1100                        f"prediction intervals for {self.replications} simulations of input time series",
1101                        loc="left",
1102                        fontsize=12,
1103                        fontweight=0,
1104                        color="black",
1105                    )
1106                plt.show()
1107
1108        if type_plot == "spaghetti":
1109            palette = plt.get_cmap("Set1")
1110            sims_ix = getsims(self.sims_, series_idx)
1111            plt.plot(x_all, y_all, "-")
1112            for col_ix in range(
1113                sims_ix.shape[1]
1114            ):  # avoid this when there are thousands of simulations
1115                plt.plot(
1116                    x_test,
1117                    sims_ix[:, col_ix],
1118                    "-",
1119                    color=palette(col_ix),
1120                    linewidth=1,
1121                    alpha=0.9,
1122                )
1123            plt.plot(x_all, y_all, "-", color="black")
1124            plt.plot(x_test, y_test, "-", color="blue")
1125            # Add titles
1126            if self.n_series > 1:
1127                plt.title(
1128                    f"{self.replications} simulations of {series}",
1129                    loc="left",
1130                    fontsize=12,
1131                    fontweight=0,
1132                    color="black",
1133                )
1134            else:
1135                plt.title(
1136                    f"{self.replications} simulations of input time series",
1137                    loc="left",
1138                    fontsize=12,
1139                    fontweight=0,
1140                    color="black",
1141                )
1142            plt.xlabel("Time")
1143            plt.ylabel("Values")
1144            # Show the graph
1145            plt.show()
1146
1147    def cross_val_score(
1148        self,
1149        X,
1150        scoring="root_mean_squared_error",
1151        n_jobs=None,
1152        verbose=0,
1153        xreg=None,
1154        initial_window=5,
1155        horizon=3,
1156        fixed_window=False,
1157        show_progress=True,
1158        level=95,
1159        **kwargs,
1160    ):
1161        """Evaluate a score by time series cross-validation.
1162
1163        Parameters:
1164
1165            X: {array-like, sparse matrix} of shape (n_samples, n_features)
1166                The data to fit.
1167
1168            scoring: str or a function
1169                A str in ('root_mean_squared_error', 'mean_squared_error', 'mean_error',
1170                'mean_absolute_error', 'mean_error', 'mean_percentage_error',
1171                'mean_absolute_percentage_error',  'winkler_score', 'coverage')
1172                Or a function defined as 'coverage' and 'winkler_score' in `utils.timeseries`
1173
1174            n_jobs: int, default=None
1175                Number of jobs to run in parallel.
1176
1177            verbose: int, default=0
1178                The verbosity level.
1179
1180            xreg: array-like, optional (default=None)
1181                Additional (external) regressors to be passed to `fit`
1182                xreg must be in 'increasing' order (most recent observations last)
1183
1184            initial_window: int
1185                initial number of consecutive values in each training set sample
1186
1187            horizon: int
1188                number of consecutive values in test set sample
1189
1190            fixed_window: boolean
1191                if False, all training samples start at index 0, and the training
1192                window's size is increasing.
1193                if True, the training window's size is fixed, and the window is
1194                rolling forward
1195
1196            show_progress: boolean
1197                if True, a progress bar is printed
1198
1199            **kwargs: dict
1200                additional parameters to be passed to `fit` and `predict`
1201
1202        Returns:
1203
1204            A tuple: descriptive statistics or errors and raw errors
1205
1206        """
1207        tscv = TimeSeriesSplit()
1208
1209        tscv_obj = tscv.split(
1210            X,
1211            initial_window=initial_window,
1212            horizon=horizon,
1213            fixed_window=fixed_window,
1214        )
1215
1216        if isinstance(scoring, str):
1217
1218            assert scoring in (
1219                "root_mean_squared_error",
1220                "mean_squared_error",
1221                "mean_error",
1222                "mean_absolute_error",
1223                "mean_percentage_error",
1224                "mean_absolute_percentage_error",
1225                "winkler_score",
1226                "coverage",
1227            ), "must have scoring in ('root_mean_squared_error', 'mean_squared_error', 'mean_error', 'mean_absolute_error', 'mean_error', 'mean_percentage_error', 'mean_absolute_percentage_error',  'winkler_score', 'coverage')"
1228
1229            def err_func(X_test, X_pred, scoring):
1230                if (self.replications is not None) or (
1231                    self.type_pi == "gaussian"
1232                ):  # probabilistic
1233                    if scoring == "winkler_score":
1234                        return winkler_score(X_pred, X_test, level=level)
1235                    elif scoring == "coverage":
1236                        return coverage(X_pred, X_test, level=level)
1237                    else:
1238                        return mean_errors(
1239                            pred=X_pred.mean, actual=X_test, scoring=scoring
1240                        )
1241                else:  # not probabilistic
1242                    return mean_errors(
1243                        pred=X_pred, actual=X_test, scoring=scoring
1244                    )
1245
1246        else:  # isinstance(scoring, str) = False
1247
1248            err_func = scoring
1249
1250        errors = []
1251
1252        train_indices = []
1253
1254        test_indices = []
1255
1256        for train_index, test_index in tscv_obj:
1257            train_indices.append(train_index)
1258            test_indices.append(test_index)
1259
1260        if show_progress is True:
1261            iterator = tqdm(
1262                zip(train_indices, test_indices), total=len(train_indices)
1263            )
1264        else:
1265            iterator = zip(train_indices, test_indices)
1266
1267        for train_index, test_index in iterator:
1268
1269            if verbose == 1:
1270                print(f"TRAIN: {train_index}")
1271                print(f"TEST: {test_index}")
1272
1273            if isinstance(X, pd.DataFrame):
1274                self.fit(X.iloc[train_index, :], xreg=xreg, **kwargs)
1275                X_test = X.iloc[test_index, :]
1276            else:
1277                self.fit(X[train_index, :], xreg=xreg, **kwargs)
1278                X_test = X[test_index, :]
1279            X_pred = self.predict(h=int(len(test_index)), level=level, **kwargs)
1280
1281            errors.append(err_func(X_test, X_pred, scoring))
1282
1283        res = np.asarray(errors)
1284
1285        return res, describe(res)

Univariate and multivariate time series (MTS) forecasting with Quasi-Randomized networks

Parameters:

obj: object.
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict()).

n_hidden_features: int.
    number of nodes in the hidden layer.

activation_name: str.
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'.

a: float.
    hyperparameter for 'prelu' or 'elu' activation function.

nodes_sim: str.
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'.

bias: boolean.
    indicates if the hidden layer contains a bias term (True) or not
    (False).

dropout: float.
    regularization parameter; (random) percentage of nodes dropped out
    of the training.

direct_link: boolean.
    indicates if the original predictors are included (True) in model's fitting or not (False).

n_clusters: int.
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0: no clustering).

cluster_encode: bool.
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding.

type_clust: str.
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm').

type_scaling: a tuple of 3 strings.
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax').

lags: int.
    number of lags used for each time series.

type_pi: str.
    type of prediction interval; currently:
    - "gaussian": simple, fast, but: assumes stationarity of Gaussian in-sample residuals and independence in the multivariate case
    - "kde": based on Kernel Density Estimation of in-sample residuals
    - "bootstrap": based on independent bootstrap of in-sample residuals
    - "block-bootstrap": based on basic block bootstrap of in-sample residuals
    - "scp-kde": Sequential split conformal prediction with Kernel Density Estimation of calibrated residuals
    - "scp-bootstrap": Sequential split conformal prediction with independent bootstrap of calibrated residuals
    - "scp-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of calibrated residuals
    - "scp2-kde": Sequential split conformal prediction with Kernel Density Estimation of standardized calibrated residuals
    - "scp2-bootstrap": Sequential split conformal prediction with independent bootstrap of standardized calibrated residuals
    - "scp2-block-bootstrap": Sequential split conformal prediction with basic block bootstrap of standardized calibrated residuals
    - based on copulas of in-sample residuals: 'vine-tll', 'vine-bb1', 'vine-bb6', 'vine-bb7', 'vine-bb8', 'vine-clayton',
    'vine-frank', 'vine-gaussian', 'vine-gumbel', 'vine-indep', 'vine-joe', 'vine-student'
    - 'scp-vine-tll', 'scp-vine-bb1', 'scp-vine-bb6', 'scp-vine-bb7', 'scp-vine-bb8', 'scp-vine-clayton',
    'scp-vine-frank', 'scp-vine-gaussian', 'scp-vine-gumbel', 'scp-vine-indep', 'scp-vine-joe', 'scp-vine-student'
    - 'scp2-vine-tll', 'scp2-vine-bb1', 'scp2-vine-bb6', 'scp2-vine-bb7', 'scp2-vine-bb8', 'scp2-vine-clayton',
    'scp2-vine-frank', 'scp2-vine-gaussian', 'scp2-vine-gumbel', 'scp2-vine-indep', 'scp2-vine-joe', 'scp2-vine-student'

block_size: int.
    size of block for 'type_pi' in ("block-bootstrap", "scp-block-bootstrap", "scp2-block-bootstrap").
    Default is round(3.15*(n_residuals^1/3))

replications: int.
    number of replications (if needed, for predictive simulation). Default is 'None'.

kernel: str.
    the kernel to use for residuals density estimation (used for predictive simulation). Currently, either 'gaussian' or 'tophat'.

agg: str.
    either "mean" or "median" for simulation of bootstrap aggregating

seed: int.
    reproducibility seed for nodes_sim=='uniform' or predictive simulation.

backend: str.
    "cpu" or "gpu" or "tpu".

verbose: int.
    0: not printing; 1: printing

show_progress: bool.
    True: progress bar when fitting each series; False: no progress bar when fitting each series

Attributes:

fit_objs_: dict
    objects adjusted to each individual time series

y_: {array-like}
    MTS responses (most recent observations first)

X_: {array-like}
    MTS lags

xreg_: {array-like}
    external regressors

y_means_: dict
    a dictionary of each series mean values

preds_: {array-like}
    successive model predictions

preds_std_: {array-like}
    standard deviation around the predictions for Bayesian base learners (`obj`)

gaussian_preds_std_: {array-like}
    standard deviation around the predictions for `type_pi='gaussian'`

return_std_: boolean
    return uncertainty or not (set in predict)

df_: data frame
    the input data frame, in case a data.frame is provided to `fit`

n_obs_: int
    number of time series observations (number of rows for multivariate)

level_: int
    level of confidence for prediction intervals (default is 95)

residuals_: {array-like}
    in-sample residuals (for `type_pi` not conformal prediction) or calibrated residuals
    (for `type_pi` in conformal prediction)

residuals_sims_: tuple of {array-like}
    simulations of in-sample residuals (for `type_pi` not conformal prediction) or
    calibrated residuals (for `type_pi` in conformal prediction)

kde_: A scikit-learn object, see https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KernelDensity.html

residuals_std_dev_: residuals standard deviation

Examples:

Example 1:

import nnetsauce as ns
import numpy as np
from sklearn import linear_model
np.random.seed(123)

M = np.random.rand(10, 3)
M[:,0] = 10*M[:,0]
M[:,2] = 25*M[:,2]
print(M)

# Adjust Bayesian Ridge
regr4 = linear_model.BayesianRidge()
obj_MTS = ns.MTS(regr4, lags = 1, n_hidden_features=5)
obj_MTS.fit(M)
print(obj_MTS.predict())

# with credible intervals
print(obj_MTS.predict(return_std=True, level=80))

print(obj_MTS.predict(return_std=True, level=95))

Example 2:

import nnetsauce as ns
import numpy as np
from sklearn import linear_model

dataset = {
'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'],
'series1' : [34, 30, 35.6, 33.3, 38.1],
'series2' : [4, 5.5, 5.6, 6.3, 5.1],
'series3' : [100, 100.5, 100.6, 100.2, 100.1]}
df = pd.DataFrame(dataset).set_index('date')
print(df)

# Adjust Bayesian Ridge
regr5 = linear_model.BayesianRidge()
obj_MTS = ns.MTS(regr5, lags = 1, n_hidden_features=5)
obj_MTS.fit(df)
print(obj_MTS.predict())

# with credible intervals
print(obj_MTS.predict(return_std=True, level=80))

print(obj_MTS.predict(return_std=True, level=95))
def fit(self, X, xreg=None, **kwargs):
315    def fit(self, X, xreg=None, **kwargs):
316        """Fit MTS model to training data X, with optional regressors xreg
317
318        Parameters:
319
320        X: {array-like}, shape = [n_samples, n_features]
321            Training time series, where n_samples is the number
322            of samples and n_features is the number of features;
323            X must be in increasing order (most recent observations last)
324
325        xreg: {array-like}, shape = [n_samples, n_features_xreg]
326            Additional (external) regressors to be passed to self.obj
327            xreg must be in 'increasing' order (most recent observations last)
328
329        **kwargs: for now, additional parameters to be passed to for kernel density estimation, when needed (see sklearn.neighbors.KernelDensity)
330
331        Returns:
332
333        self: object
334        """
335
336        if (
337            isinstance(X, pd.DataFrame) is False
338        ):  # input data set is a numpy array
339
340            if xreg is None:
341                X = pd.DataFrame(X)
342                self.series_names = [
343                    "series" + str(i) for i in range(X.shape[1])
344                ]
345            else:  # xreg is not None
346                X = mo.cbind(X, xreg)
347                self.xreg_ = xreg
348
349        else:  # input data set is a DataFrame with column names
350
351            X_index = None
352            if X.index is not None:
353                X_index = X.index
354            if xreg is None:
355                X = copy.deepcopy(mo.convert_df_to_numeric(X))
356            else:
357                X = copy.deepcopy(mo.cbind(mo.convert_df_to_numeric(X), xreg))
358                self.xreg_ = xreg
359            if X_index is not None:
360                X.index = X_index
361            self.series_names = X.columns.tolist()
362
363        if isinstance(X, pd.DataFrame):
364            self.df_ = X
365            X = X.values
366            self.df_.columns = self.series_names
367            self.input_dates = ts.compute_input_dates(self.df_)
368        else:
369            self.df_ = pd.DataFrame(X, columns=self.series_names)
370            self.input_dates = ts.compute_input_dates(self.df_)
371
372        try:
373            # multivariate time series
374            n, p = X.shape
375        except:
376            # univariate time series
377            n = X.shape[0]
378            p = 1
379
380        self.n_obs_ = n
381
382        rep_1_n = np.repeat(1, n)
383
384        self.y_ = None
385        self.X_ = None
386        self.n_series = p
387        self.fit_objs_.clear()
388        self.y_means_.clear()
389        residuals_ = []
390        self.residuals_ = None
391        self.residuals_sims_ = None
392        self.kde_ = None
393        self.sims_ = None
394        self.scaled_Z_ = None
395        self.centered_y_is_ = []
396
397        if p > 1:
398            # multivariate time series
399            mts_input = ts.create_train_inputs(X[::-1], self.lags)
400        else:
401            # univariate time series
402            mts_input = ts.create_train_inputs(
403                X.reshape(-1, 1)[::-1], self.lags
404            )
405
406        self.y_ = mts_input[0]
407
408        self.X_ = mts_input[1]
409
410        dummy_y, scaled_Z = self.cook_training_set(y=rep_1_n, X=self.X_)
411
412        self.scaled_Z_ = scaled_Z
413
414        # loop on all the time series and adjust self.obj.fit
415        if self.verbose > 0:
416            print(
417                f"\n Adjusting {type(self.obj).__name__} to multivariate time series... \n "
418            )
419
420        if self.show_progress is True:
421            iterator = tqdm(range(p))
422        else:
423            iterator = range(p)
424
425        if self.type_pi in (
426            "gaussian",
427            "kde",
428            "bootstrap",
429            "block-bootstrap",
430        ) or self.type_pi.startswith("vine"):
431            for i in iterator:
432                y_mean = np.mean(self.y_[:, i])
433                self.y_means_[i] = y_mean
434                centered_y_i = self.y_[:, i] - y_mean
435                self.centered_y_is_.append(centered_y_i)
436                self.obj.fit(X=scaled_Z, y=centered_y_i)
437                self.fit_objs_[i] = deepcopy(self.obj)
438                residuals_.append(
439                    (
440                        centered_y_i - self.fit_objs_[i].predict(scaled_Z)
441                    ).tolist()
442                )
443
444        if self.type_pi.startswith("scp"):
445            # split conformal prediction
446            for i in iterator:
447                n_y = self.y_.shape[0]
448                n_y_half = n_y // 2
449                first_half_idx = range(0, n_y_half)
450                second_half_idx = range(n_y_half, n_y)
451                y_mean_temp = np.mean(self.y_[first_half_idx, i])
452                centered_y_i_temp = self.y_[first_half_idx, i] - y_mean_temp
453                self.obj.fit(X=scaled_Z[first_half_idx, :], y=centered_y_i_temp)
454                # calibrated residuals actually
455                residuals_.append(
456                    (
457                        self.y_[second_half_idx, i]
458                        - (
459                            y_mean_temp
460                            + self.obj.predict(scaled_Z[second_half_idx, :])
461                        )
462                    ).tolist()
463                )
464                # fit on the second half
465                y_mean = np.mean(self.y_[second_half_idx, i])
466                self.y_means_[i] = y_mean
467                centered_y_i = self.y_[second_half_idx, i] - y_mean
468                self.obj.fit(X=scaled_Z[second_half_idx, :], y=centered_y_i)
469                self.fit_objs_[i] = deepcopy(self.obj)
470
471        self.residuals_ = np.asarray(residuals_).T
472
473        if self.type_pi == "gaussian":
474            self.gaussian_preds_std_ = np.std(self.residuals_, axis=0)
475
476        if self.type_pi.startswith("scp2"):
477            # Calculate mean and standard deviation for each column
478            data_mean = np.mean(self.residuals_, axis=0)
479            self.residuals_std_dev_ = np.std(self.residuals_, axis=0)
480            # Center and scale the array using broadcasting
481            self.residuals_ = (
482                self.residuals_ - data_mean[np.newaxis, :]
483            ) / self.residuals_std_dev_[np.newaxis, :]
484
485        if self.replications != None and "kde" in self.type_pi:
486            if self.verbose > 0:
487                print(f"\n Simulate residuals using {self.kernel} kernel... \n")
488            assert self.kernel in (
489                "gaussian",
490                "tophat",
491            ), "currently, 'kernel' must be either 'gaussian' or 'tophat'"
492            kernel_bandwidths = {"bandwidth": np.logspace(-6, 6, 150)}
493            grid = GridSearchCV(
494                KernelDensity(kernel=self.kernel, **kwargs),
495                param_grid=kernel_bandwidths,
496            )
497            grid.fit(self.residuals_)
498
499            if self.verbose > 0:
500                print(
501                    f"\n Best parameters for {self.kernel} kernel: {grid.best_params_} \n"
502                )
503
504            self.kde_ = grid.best_estimator_
505
506        return self

Fit MTS model to training data X, with optional regressors xreg

Parameters:

X: {array-like}, shape = [n_samples, n_features] Training time series, where n_samples is the number of samples and n_features is the number of features; X must be in increasing order (most recent observations last)

xreg: {array-like}, shape = [n_samples, n_features_xreg] Additional (external) regressors to be passed to self.obj xreg must be in 'increasing' order (most recent observations last)

**kwargs: for now, additional parameters to be passed to for kernel density estimation, when needed (see sklearn.neighbors.KernelDensity)

Returns:

self: object

def predict(self, h=5, level=95, **kwargs):
508    def predict(self, h=5, level=95, **kwargs):
509        """Forecast all the time series, h steps ahead
510
511        Parameters:
512
513        h: {integer}
514            Forecasting horizon
515
516        level: {integer}
517            Level of confidence (if obj has option 'return_std' and the
518            posterior is gaussian)
519
520        new_xreg: {array-like}, shape = [n_samples = h, n_new_xreg]
521            New values of additional (deterministic) regressors on horizon = h
522            new_xreg must be in increasing order (most recent observations last)
523
524        **kwargs: additional parameters to be passed to
525                self.cook_test_set
526
527        Returns:
528
529        model predictions for horizon = h: {array-like}, data frame or tuple.
530        Standard deviation and prediction intervals are returned when
531        `obj.predict` can return standard deviation
532
533        """
534
535        self.output_dates_, frequency = ts.compute_output_dates(self.df_, h)
536
537        self.level_ = level
538
539        self.return_std_ = False  # do not remove (/!\)
540
541        self.mean_ = None  # do not remove (/!\)
542
543        self.mean_ = deepcopy(self.y_)  # do not remove (/!\)
544
545        self.lower_ = None  # do not remove (/!\)
546
547        self.upper_ = None  # do not remove (/!\)
548
549        self.sims_ = None  # do not remove (/!\)
550
551        y_means_ = np.asarray([self.y_means_[i] for i in range(self.n_series)])
552
553        n_features = self.n_series * self.lags
554
555        self.alpha_ = 100 - level
556
557        pi_multiplier = norm.ppf(1 - self.alpha_ / 200)
558
559        if "return_std" in kwargs:  # bayesian forecasting
560            self.return_std_ = True
561            self.preds_std_ = []
562            DescribeResult = namedtuple(
563                "DescribeResult", ("mean", "lower", "upper")
564            )  # to be updated
565
566        if "return_pi" in kwargs:  # split conformal, without simulation
567            mean_pi_ = []
568            lower_pi_ = []
569            upper_pi_ = []
570            DescribeResult = namedtuple(
571                "DescribeResult", ("mean", "lower", "upper")
572            )  # to be updated
573
574        if self.kde_ != None and "kde" in self.type_pi:  # kde
575            if self.verbose == 1:
576                self.residuals_sims_ = tuple(
577                    self.kde_.sample(
578                        n_samples=h, random_state=self.seed + 100 * i
579                    )
580                    for i in tqdm(range(self.replications))
581                )
582            elif self.verbose == 0:
583                self.residuals_sims_ = tuple(
584                    self.kde_.sample(
585                        n_samples=h, random_state=self.seed + 100 * i
586                    )
587                    for i in range(self.replications)
588                )
589
590        if self.type_pi in ("bootstrap", "scp-bootstrap", "scp2-bootstrap"):
591            assert self.replications is not None and isinstance(
592                self.replications, int
593            ), "'replications' must be provided and be an integer"
594            if self.verbose == 1:
595                self.residuals_sims_ = tuple(
596                    ts.bootstrap(
597                        self.residuals_,
598                        h=h,
599                        block_size=None,
600                        seed=self.seed + 100 * i,
601                    )
602                    for i in tqdm(range(self.replications))
603                )
604            elif self.verbose == 0:
605                self.residuals_sims_ = tuple(
606                    ts.bootstrap(
607                        self.residuals_,
608                        h=h,
609                        block_size=None,
610                        seed=self.seed + 100 * i,
611                    )
612                    for i in range(self.replications)
613                )
614
615        if self.type_pi in (
616            "block-bootstrap",
617            "scp-block-bootstrap",
618            "scp2-block-bootstrap",
619        ):
620            if self.block_size is None:
621                self.block_size = int(
622                    np.ceil(3.15 * (self.residuals_.shape[0] ** (1 / 3)))
623                )
624
625            assert self.replications is not None and isinstance(
626                self.replications, int
627            ), "'replications' must be provided and be an integer"
628            if self.verbose == 1:
629                self.residuals_sims_ = tuple(
630                    ts.bootstrap(
631                        self.residuals_,
632                        h=h,
633                        block_size=self.block_size,
634                        seed=self.seed + 100 * i,
635                    )
636                    for i in tqdm(range(self.replications))
637                )
638            elif self.verbose == 0:
639                self.residuals_sims_ = tuple(
640                    ts.bootstrap(
641                        self.residuals_,
642                        h=h,
643                        block_size=self.block_size,
644                        seed=self.seed + 100 * i,
645                    )
646                    for i in range(self.replications)
647                )
648
649        if "vine" in self.type_pi:
650            if self.verbose == 1:
651                self.residuals_sims_ = tuple(
652                    vinecopula_sample(
653                        x=self.residuals_,
654                        n_samples=h,
655                        method=self.type_pi,
656                        random_state=self.seed + 100 * i,
657                    )
658                    for i in tqdm(range(self.replications))
659                )
660            elif self.verbose == 0:
661                self.residuals_sims_ = tuple(
662                    vinecopula_sample(
663                        x=self.residuals_,
664                        n_samples=h,
665                        method=self.type_pi,
666                        random_state=self.seed + 100 * i,
667                    )
668                    for i in range(self.replications)
669                )
670
671        for _ in range(h):
672
673            new_obs = ts.reformat_response(self.mean_, self.lags)
674
675            new_X = new_obs.reshape(1, n_features)
676
677            cooked_new_X = self.cook_test_set(new_X, **kwargs)
678
679            if "return_std" in kwargs:
680                self.preds_std_.append(
681                    [
682                        np.asarray(
683                            self.fit_objs_[i].predict(
684                                cooked_new_X, return_std=True
685                            )[1]
686                        ).item()
687                        for i in range(self.n_series)
688                    ]
689                )
690
691            if "return_pi" in kwargs:
692                for i in range(self.n_series):
693                    preds_pi = self.fit_objs_[i].predict(
694                        cooked_new_X, return_pi=True
695                    )
696                    mean_pi_.append(preds_pi.mean[0])
697                    lower_pi_.append(preds_pi.lower[0])
698                    upper_pi_.append(preds_pi.upper[0])
699
700            predicted_cooked_new_X = np.asarray(
701                [
702                    np.asarray(self.fit_objs_[i].predict(cooked_new_X)).item()
703                    for i in range(self.n_series)
704                ]
705            )
706
707            preds = np.asarray(y_means_ + predicted_cooked_new_X)
708
709            self.mean_ = mo.rbind(preds, self.mean_)  # preallocate?
710
711        # function's return ----------------------------------------------------------------------
712        self.mean_ = pd.DataFrame(
713            self.mean_[0:h, :][::-1],
714            columns=self.df_.columns,
715            index=self.output_dates_,
716        )
717
718        if (
719            (("return_std" not in kwargs) and ("return_pi" not in kwargs))
720            and (self.type_pi not in ("gaussian", "scp"))
721        ) or ("vine" in self.type_pi):
722
723            if self.replications is None:
724                return self.mean_
725
726            # if "return_std" not in kwargs and self.replications is not None
727            meanf = []
728            lower = []
729            upper = []
730
731            if "scp2" in self.type_pi:
732
733                if self.verbose == 1:
734                    self.sims_ = tuple(
735                        (
736                            self.mean_
737                            + self.residuals_sims_[i]
738                            * self.residuals_std_dev_[np.newaxis, :]
739                            for i in tqdm(range(self.replications))
740                        )
741                    )
742                elif self.verbose == 0:
743                    self.sims_ = tuple(
744                        (
745                            self.mean_
746                            + self.residuals_sims_[i]
747                            * self.residuals_std_dev_[np.newaxis, :]
748                            for i in range(self.replications)
749                        )
750                    )
751            else:
752
753                if self.verbose == 1:
754                    self.sims_ = tuple(
755                        (
756                            self.mean_ + self.residuals_sims_[i]
757                            for i in tqdm(range(self.replications))
758                        )
759                    )
760                elif self.verbose == 0:
761                    self.sims_ = tuple(
762                        (
763                            self.mean_ + self.residuals_sims_[i]
764                            for i in range(self.replications)
765                        )
766                    )
767
768            DescribeResult = namedtuple(
769                "DescribeResult", ("mean", "sims", "lower", "upper")
770            )
771            for ix in range(self.n_series):
772                sims_ix = getsims(self.sims_, ix)
773                if self.agg == "mean":
774                    meanf.append(np.mean(sims_ix, axis=1))
775                else:
776                    meanf.append(np.median(sims_ix, axis=1))
777                lower.append(np.quantile(sims_ix, q=self.alpha_ / 200, axis=1))
778                upper.append(
779                    np.quantile(sims_ix, q=1 - self.alpha_ / 200, axis=1)
780                )
781
782            self.mean_ = pd.DataFrame(
783                np.asarray(meanf).T,
784                columns=self.series_names,  # self.df_.columns,
785                index=self.output_dates_,
786            )
787
788            self.lower_ = pd.DataFrame(
789                np.asarray(lower).T,
790                columns=self.series_names,  # self.df_.columns,
791                index=self.output_dates_,
792            )
793
794            self.upper_ = pd.DataFrame(
795                np.asarray(upper).T,
796                columns=self.series_names,  # self.df_.columns,
797                index=self.output_dates_,
798            )
799
800            res = DescribeResult(
801                self.mean_, self.sims_, self.lower_, self.upper_
802            )
803
804            if self.xreg_ is not None:
805
806                if len(self.xreg_.shape) > 1:
807
808                    res2 = mx.tuple_map(
809                        res,
810                        lambda x: mo.delete_last_columns(
811                            x, num_columns=self.xreg_.shape[1]
812                        ),
813                    )
814
815                else:
816
817                    res2 = mx.tuple_map(
818                        res, lambda x: mo.delete_last_columns(x, num_columns=1)
819                    )
820
821                return res2
822
823            else:
824
825                return res
826
827        if (
828            (("return_std" in kwargs) or ("return_pi" in kwargs))
829            and (self.type_pi not in ("gaussian", "scp"))
830        ) or "vine" in self.type_pi:
831            DescribeResult = namedtuple(
832                "DescribeResult", ("mean", "lower", "upper")
833            )
834
835            self.mean_ = pd.DataFrame(
836                np.asarray(self.mean_),
837                columns=self.series_names,  # self.df_.columns,
838                index=self.output_dates_,
839            )
840
841            if "return_std" in kwargs:
842
843                self.preds_std_ = np.asarray(self.preds_std_)
844
845                self.lower_ = pd.DataFrame(
846                    self.mean_.values - pi_multiplier * self.preds_std_,
847                    columns=self.series_names,  # self.df_.columns,
848                    index=self.output_dates_,
849                )
850
851                self.upper_ = pd.DataFrame(
852                    self.mean_.values + pi_multiplier * self.preds_std_,
853                    columns=self.series_names,  # self.df_.columns,
854                    index=self.output_dates_,
855                )
856
857            if "return_pi" in kwargs:
858
859                self.lower_ = pd.DataFrame(
860                    np.asarray(lower_pi_).reshape(h, self.n_series)
861                    + y_means_[np.newaxis, :],
862                    columns=self.series_names,  # self.df_.columns,
863                    index=self.output_dates_,
864                )
865
866                self.upper_ = pd.DataFrame(
867                    np.asarray(upper_pi_).reshape(h, self.n_series)
868                    + y_means_[np.newaxis, :],
869                    columns=self.series_names,  # self.df_.columns,
870                    index=self.output_dates_,
871                )
872
873            res = DescribeResult(self.mean_, self.lower_, self.upper_)
874
875            if self.xreg_ is not None:
876                if len(self.xreg_.shape) > 1:
877                    res2 = mx.tuple_map(
878                        res,
879                        lambda x: mo.delete_last_columns(
880                            x, num_columns=self.xreg_.shape[1]
881                        ),
882                    )
883                else:
884                    res2 = mx.tuple_map(
885                        res, lambda x: mo.delete_last_columns(x, num_columns=1)
886                    )
887                return DescribeResult(res2[0], res2[1], res2[2])
888
889            return res
890
891        if self.type_pi == "gaussian":
892
893            DescribeResult = namedtuple(
894                "DescribeResult", ("mean", "lower", "upper")
895            )
896
897            self.mean_ = pd.DataFrame(
898                np.asarray(self.mean_),
899                columns=self.series_names,  # self.df_.columns,
900                index=self.output_dates_,
901            )
902
903            self.lower_ = pd.DataFrame(
904                self.mean_.values - pi_multiplier * self.gaussian_preds_std_,
905                columns=self.series_names,  # self.df_.columns,
906                index=self.output_dates_,
907            )
908
909            self.upper_ = pd.DataFrame(
910                self.mean_.values + pi_multiplier * self.gaussian_preds_std_,
911                columns=self.series_names,  # self.df_.columns,
912                index=self.output_dates_,
913            )
914
915            res = DescribeResult(self.mean_, self.lower_, self.upper_)
916
917            if self.xreg_ is not None:
918                if len(self.xreg_.shape) > 1:
919                    res2 = mx.tuple_map(
920                        res,
921                        lambda x: mo.delete_last_columns(
922                            x, num_columns=self.xreg_.shape[1]
923                        ),
924                    )
925                else:
926                    res2 = mx.tuple_map(
927                        res, lambda x: mo.delete_last_columns(x, num_columns=1)
928                    )
929                return DescribeResult(res2[0], res2[1], res2[2])
930
931            return res

Forecast all the time series, h steps ahead

Parameters:

h: {integer} Forecasting horizon

level: {integer} Level of confidence (if obj has option 'return_std' and the posterior is gaussian)

new_xreg: {array-like}, shape = [n_samples = h, n_new_xreg] New values of additional (deterministic) regressors on horizon = h new_xreg must be in increasing order (most recent observations last)

**kwargs: additional parameters to be passed to self.cook_test_set

Returns:

model predictions for horizon = h: {array-like}, data frame or tuple. Standard deviation and prediction intervals are returned when obj.predict can return standard deviation

def score(self, X, training_index, testing_index, scoring=None, **kwargs):
 933    def score(self, X, training_index, testing_index, scoring=None, **kwargs):
 934        """Train on training_index, score on testing_index."""
 935
 936        assert (
 937            bool(set(training_index).intersection(set(testing_index))) == False
 938        ), "Non-overlapping 'training_index' and 'testing_index' required"
 939
 940        # Dimensions
 941        try:
 942            # multivariate time series
 943            n, p = X.shape
 944        except:
 945            # univariate time series
 946            n = X.shape[0]
 947            p = 1
 948
 949        # Training and testing sets
 950        if p > 1:
 951            X_train = X[training_index, :]
 952            X_test = X[testing_index, :]
 953        else:
 954            X_train = X[training_index]
 955            X_test = X[testing_index]
 956
 957        # Horizon
 958        h = len(testing_index)
 959        assert (
 960            len(training_index) + h
 961        ) <= n, "Please check lengths of training and testing windows"
 962
 963        # Fit and predict
 964        self.fit(X_train, **kwargs)
 965        preds = self.predict(h=h, **kwargs)
 966
 967        if scoring is None:
 968            scoring = "neg_root_mean_squared_error"
 969
 970        # check inputs
 971        assert scoring in (
 972            "explained_variance",
 973            "neg_mean_absolute_error",
 974            "neg_mean_squared_error",
 975            "neg_root_mean_squared_error",
 976            "neg_mean_squared_log_error",
 977            "neg_median_absolute_error",
 978            "r2",
 979        ), "'scoring' should be in ('explained_variance', 'neg_mean_absolute_error', \
 980                               'neg_mean_squared_error', 'neg_root_mean_squared_error', 'neg_mean_squared_log_error', \
 981                               'neg_median_absolute_error', 'r2')"
 982
 983        scoring_options = {
 984            "explained_variance": skm2.explained_variance_score,
 985            "neg_mean_absolute_error": skm2.mean_absolute_error,
 986            "neg_mean_squared_error": skm2.mean_squared_error,
 987            "neg_root_mean_squared_error": lambda x, y: np.sqrt(
 988                skm2.mean_squared_error(x, y)
 989            ),
 990            "neg_mean_squared_log_error": skm2.mean_squared_log_error,
 991            "neg_median_absolute_error": skm2.median_absolute_error,
 992            "r2": skm2.r2_score,
 993        }
 994
 995        # if p > 1:
 996        #     return tuple(
 997        #         [
 998        #             scoring_options[scoring](
 999        #                 X_test[:, i], preds[:, i]#, **kwargs
1000        #             )
1001        #             for i in range(p)
1002        #         ]
1003        #     )
1004        # else:
1005        return scoring_options[scoring](X_test, preds)

Train on training_index, score on testing_index.

class MultitaskClassifier(nnetsauce.Base, sklearn.base.ClassifierMixin):
 16class MultitaskClassifier(Base, ClassifierMixin):
 17    """Multitask Classification model based on regression models, with shared covariates
 18
 19    Parameters:
 20
 21        obj: object
 22            any object (must be a regression model) containing a method fit (obj.fit())
 23            and a method predict (obj.predict())
 24
 25        n_hidden_features: int
 26            number of nodes in the hidden layer
 27
 28        activation_name: str
 29            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 30
 31        a: float
 32            hyperparameter for 'prelu' or 'elu' activation function
 33
 34        nodes_sim: str
 35            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 36            'uniform'
 37
 38        bias: boolean
 39            indicates if the hidden layer contains a bias term (True) or not
 40            (False)
 41
 42        dropout: float
 43            regularization parameter; (random) percentage of nodes dropped out
 44            of the training
 45
 46        direct_link: boolean
 47            indicates if the original predictors are included (True) in model's
 48            fitting or not (False)
 49
 50        n_clusters: int
 51            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 52                no clustering)
 53
 54        cluster_encode: bool
 55            defines how the variable containing clusters is treated (default is one-hot)
 56            if `False`, then labels are used, without one-hot encoding
 57
 58        type_clust: str
 59            type of clustering method: currently k-means ('kmeans') or Gaussian
 60            Mixture Model ('gmm')
 61
 62        type_scaling: a tuple of 3 strings
 63            scaling methods for inputs, hidden layer, and clustering respectively
 64            (and when relevant).
 65            Currently available: standardization ('std') or MinMax scaling ('minmax')
 66
 67        col_sample: float
 68            percentage of covariates randomly chosen for training
 69
 70        row_sample: float
 71            percentage of rows chosen for training, by stratified bootstrapping
 72
 73        seed: int
 74            reproducibility seed for nodes_sim=='uniform'
 75
 76        backend: str
 77            "cpu" or "gpu" or "tpu"
 78
 79    Attributes:
 80
 81        fit_objs_: dict
 82            objects adjusted to each individual time series
 83
 84        n_classes_: int
 85            number of classes for the classifier
 86
 87    Examples:
 88
 89    See also [https://github.com/Techtonique/nnetsauce/blob/master/examples/mtask_classification.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/mtask_classification.py)
 90
 91    ```python
 92    import nnetsauce as ns
 93    import numpy as np
 94    from sklearn.datasets import load_breast_cancer
 95    from sklearn.linear_model import LinearRegression
 96    from sklearn.model_selection import train_test_split
 97    from sklearn import metrics
 98    from time import time
 99
100    breast_cancer = load_breast_cancer()
101    Z = breast_cancer.data
102    t = breast_cancer.target
103
104    X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2,
105                                                        random_state=123+2*10)
106
107    # Linear Regression is used
108    regr = LinearRegression()
109    fit_obj = ns.MultitaskClassifier(regr, n_hidden_features=5,
110                                n_clusters=2, type_clust="gmm")
111
112    start = time()
113    fit_obj.fit(X_train, y_train)
114    print(f"Elapsed {time() - start}")
115
116    print(fit_obj.score(X_test, y_test))
117    print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
118
119    start = time()
120    preds = fit_obj.predict(X_test)
121    print(f"Elapsed {time() - start}")
122    print(metrics.classification_report(preds, y_test))
123    ```
124
125    """
126
127    # construct the object -----
128
129    def __init__(
130        self,
131        obj,
132        n_hidden_features=5,
133        activation_name="relu",
134        a=0.01,
135        nodes_sim="sobol",
136        bias=True,
137        dropout=0,
138        direct_link=True,
139        n_clusters=2,
140        cluster_encode=True,
141        type_clust="kmeans",
142        type_scaling=("std", "std", "std"),
143        col_sample=1,
144        row_sample=1,
145        seed=123,
146        backend="cpu",
147    ):
148        super().__init__(
149            n_hidden_features=n_hidden_features,
150            activation_name=activation_name,
151            a=a,
152            nodes_sim=nodes_sim,
153            bias=bias,
154            dropout=dropout,
155            direct_link=direct_link,
156            n_clusters=n_clusters,
157            cluster_encode=cluster_encode,
158            type_clust=type_clust,
159            type_scaling=type_scaling,
160            col_sample=col_sample,
161            row_sample=row_sample,
162            seed=seed,
163            backend=backend,
164        )
165
166        self.type_fit = "classification"
167        self.obj = obj
168        self.fit_objs_ = {}
169
170    def fit(self, X, y, sample_weight=None, **kwargs):
171        """Fit MultitaskClassifier to training data (X, y).
172
173        Args:
174
175            X: {array-like}, shape = [n_samples, n_features]
176                Training vectors, where n_samples is the number
177                of samples and n_features is the number of features.
178
179            y: array-like, shape = [n_samples]
180                Target values.
181
182            **kwargs: additional parameters to be passed to
183                    self.cook_training_set or self.obj.fit
184
185        Returns:
186
187            self: object
188
189        """
190
191        assert mx.is_factor(y), "y must contain only integers"
192
193        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
194
195        self.classes_ = np.unique(y)  # for compatibility with sklearn
196        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
197
198        # multitask response
199        Y = mo.one_hot_encode2(output_y, self.n_classes_)
200
201        # if sample_weight is None:
202        for i in range(self.n_classes_):
203            self.fit_objs_[i] = pickle.loads(
204                pickle.dumps(self.obj.fit(scaled_Z, Y[:, i], **kwargs), -1)
205            )
206
207        self.classes_ = np.unique(y)
208        return self
209
210    def predict(self, X, **kwargs):
211        """Predict test data X.
212
213        Args:
214
215            X: {array-like}, shape = [n_samples, n_features]
216                Training vectors, where n_samples is the number
217                of samples and n_features is the number of features.
218
219            **kwargs: additional parameters to be passed to
220                    self.cook_test_set
221
222        Returns:
223
224            model predictions: {array-like}
225
226        """
227
228        return np.argmax(self.predict_proba(X, **kwargs), axis=1)
229
230    def predict_proba(self, X, **kwargs):
231        """Predict probabilities for test data X.
232
233        Args:
234
235            X: {array-like}, shape = [n_samples, n_features]
236                Training vectors, where n_samples is the number
237                of samples and n_features is the number of features.
238
239            **kwargs: additional parameters to be passed to
240                    self.cook_test_set
241
242        Returns:
243
244            probability estimates for test data: {array-like}
245
246        """
247
248        shape_X = X.shape
249
250        probs = np.zeros((shape_X[0], self.n_classes_))
251
252        if len(shape_X) == 1:
253            n_features = shape_X[0]
254
255            new_X = mo.rbind(
256                X.reshape(1, n_features),
257                np.ones(n_features).reshape(1, n_features),
258            )
259
260            Z = self.cook_test_set(new_X, **kwargs)
261
262            # loop on all the classes
263            for i in range(self.n_classes_):
264                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)[0]
265
266        else:
267            Z = self.cook_test_set(X, **kwargs)
268
269            # loop on all the classes
270            for i in range(self.n_classes_):
271                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)
272
273        expit_raw_probs = expit(probs)
274
275        return expit_raw_probs / expit_raw_probs.sum(axis=1)[:, None]

Multitask Classification model based on regression models, with shared covariates

Parameters:

obj: object
    any object (must be a regression model) containing a method fit (obj.fit())
    and a method predict (obj.predict())

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

col_sample: float
    percentage of covariates randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

fit_objs_: dict
    objects adjusted to each individual time series

n_classes_: int
    number of classes for the classifier

Examples:

See also https://github.com/Techtonique/nnetsauce/blob/master/examples/mtask_classification.py

import nnetsauce as ns
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn import metrics
from time import time

breast_cancer = load_breast_cancer()
Z = breast_cancer.data
t = breast_cancer.target

X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2,
                                                    random_state=123+2*10)

# Linear Regression is used
regr = LinearRegression()
fit_obj = ns.MultitaskClassifier(regr, n_hidden_features=5,
                            n_clusters=2, type_clust="gmm")

start = time()
fit_obj.fit(X_train, y_train)
print(f"Elapsed {time() - start}")

print(fit_obj.score(X_test, y_test))
print(fit_obj.score(X_test, y_test, scoring="roc_auc"))

start = time()
preds = fit_obj.predict(X_test)
print(f"Elapsed {time() - start}")
print(metrics.classification_report(preds, y_test))
def fit(self, X, y, sample_weight=None, **kwargs):
170    def fit(self, X, y, sample_weight=None, **kwargs):
171        """Fit MultitaskClassifier to training data (X, y).
172
173        Args:
174
175            X: {array-like}, shape = [n_samples, n_features]
176                Training vectors, where n_samples is the number
177                of samples and n_features is the number of features.
178
179            y: array-like, shape = [n_samples]
180                Target values.
181
182            **kwargs: additional parameters to be passed to
183                    self.cook_training_set or self.obj.fit
184
185        Returns:
186
187            self: object
188
189        """
190
191        assert mx.is_factor(y), "y must contain only integers"
192
193        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
194
195        self.classes_ = np.unique(y)  # for compatibility with sklearn
196        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
197
198        # multitask response
199        Y = mo.one_hot_encode2(output_y, self.n_classes_)
200
201        # if sample_weight is None:
202        for i in range(self.n_classes_):
203            self.fit_objs_[i] = pickle.loads(
204                pickle.dumps(self.obj.fit(scaled_Z, Y[:, i], **kwargs), -1)
205            )
206
207        self.classes_ = np.unique(y)
208        return self

Fit MultitaskClassifier to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
210    def predict(self, X, **kwargs):
211        """Predict test data X.
212
213        Args:
214
215            X: {array-like}, shape = [n_samples, n_features]
216                Training vectors, where n_samples is the number
217                of samples and n_features is the number of features.
218
219            **kwargs: additional parameters to be passed to
220                    self.cook_test_set
221
222        Returns:
223
224            model predictions: {array-like}
225
226        """
227
228        return np.argmax(self.predict_proba(X, **kwargs), axis=1)

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
230    def predict_proba(self, X, **kwargs):
231        """Predict probabilities for test data X.
232
233        Args:
234
235            X: {array-like}, shape = [n_samples, n_features]
236                Training vectors, where n_samples is the number
237                of samples and n_features is the number of features.
238
239            **kwargs: additional parameters to be passed to
240                    self.cook_test_set
241
242        Returns:
243
244            probability estimates for test data: {array-like}
245
246        """
247
248        shape_X = X.shape
249
250        probs = np.zeros((shape_X[0], self.n_classes_))
251
252        if len(shape_X) == 1:
253            n_features = shape_X[0]
254
255            new_X = mo.rbind(
256                X.reshape(1, n_features),
257                np.ones(n_features).reshape(1, n_features),
258            )
259
260            Z = self.cook_test_set(new_X, **kwargs)
261
262            # loop on all the classes
263            for i in range(self.n_classes_):
264                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)[0]
265
266        else:
267            Z = self.cook_test_set(X, **kwargs)
268
269            # loop on all the classes
270            for i in range(self.n_classes_):
271                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)
272
273        expit_raw_probs = expit(probs)
274
275        return expit_raw_probs / expit_raw_probs.sum(axis=1)[:, None]

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class PredictionInterval(sklearn.base.BaseEstimator, sklearn.base.RegressorMixin):
 20class PredictionInterval(BaseEstimator, RegressorMixin):
 21    """Class PredictionInterval: Obtain prediction intervals.
 22
 23    Attributes:
 24
 25        obj: an object;
 26            fitted object containing methods `fit` and `predict`
 27
 28        method: a string;
 29            method for constructing the prediction intervals.
 30            Currently "splitconformal" (default) and "localconformal"
 31
 32        level: a float;
 33            Confidence level for prediction intervals. Default is 95,
 34            equivalent to a miscoverage error of 5 (%)
 35
 36        replications: an integer;
 37            Number of replications for simulated conformal (default is `None`)
 38
 39        type_pi: a string;
 40            type of prediction interval: currently "kde" (default) or "bootstrap"
 41
 42        type_split: a string;
 43            "random" (random split of data) or "sequential" (sequential split of data)
 44
 45        seed: an integer;
 46            Reproducibility of fit (there's a random split between fitting and calibration data)
 47    """
 48
 49    def __init__(
 50        self,
 51        obj,
 52        method="splitconformal",
 53        level=95,
 54        type_pi="bootstrap",
 55        type_split="random",
 56        replications=None,
 57        kernel=None,
 58        agg="mean",
 59        seed=123,
 60    ):
 61
 62        self.obj = obj
 63        self.method = method
 64        self.level = level
 65        self.type_pi = type_pi
 66        self.type_split = type_split
 67        self.replications = replications
 68        self.kernel = kernel
 69        self.agg = agg
 70        self.seed = seed
 71        self.alpha_ = 1 - self.level / 100
 72        self.quantile_ = None
 73        self.icp_ = None
 74        self.calibrated_residuals_ = None
 75        self.scaled_calibrated_residuals_ = None
 76        self.calibrated_residuals_scaler_ = None
 77        self.kde_ = None
 78
 79    def fit(self, X, y, sample_weight=None, **kwargs):
 80        """Fit the `method` to training data (X, y).
 81
 82        Args:
 83
 84            X: array-like, shape = [n_samples, n_features];
 85                Training set vectors, where n_samples is the number
 86                of samples and n_features is the number of features.
 87
 88            y: array-like, shape = [n_samples, ]; Target values.
 89
 90            sample_weight: array-like, shape = [n_samples]
 91                Sample weights.
 92
 93        """
 94
 95        if self.type_split == "random":
 96            X_train, X_calibration, y_train, y_calibration = train_test_split(
 97                X, y, test_size=0.5, random_state=self.seed
 98            )
 99        elif self.type_split == "sequential":
100            n_x = X.shape[0]
101            n_x_half = n_x // 2
102            first_half_idx = range(0, n_x_half)
103            second_half_idx = range(n_x_half, n_x)
104            X_train = X[first_half_idx, :]
105            X_calibration = X[second_half_idx, :]
106            y_train = y[first_half_idx]
107            y_calibration = y[second_half_idx]
108
109        if self.method == "splitconformal":
110
111            n_samples_calibration = X_calibration.shape[0]
112            self.obj.fit(X_train, y_train)
113            preds_calibration = self.obj.predict(X_calibration)
114            self.calibrated_residuals_ = y_calibration - preds_calibration
115            absolute_residuals = np.abs(self.calibrated_residuals_)
116            self.calibrated_residuals_scaler_ = StandardScaler(
117                with_mean=True, with_std=True
118            )
119            self.scaled_calibrated_residuals_ = (
120                self.calibrated_residuals_scaler_.fit_transform(
121                    self.calibrated_residuals_.reshape(-1, 1)
122                ).ravel()
123            )
124            try:
125                # numpy version >= 1.22
126                self.quantile_ = np.quantile(
127                    a=absolute_residuals, q=self.level / 100, method="higher"
128                )
129            except:
130                # numpy version < 1.22
131                self.quantile_ = np.quantile(
132                    a=absolute_residuals,
133                    q=self.level / 100,
134                    interpolation="higher",
135                )
136
137        if self.method == "localconformal":
138
139            mad_estimator = ExtraTreesRegressor()
140            normalizer = RegressorNormalizer(
141                self.obj, mad_estimator, AbsErrorErrFunc()
142            )
143            nc = RegressorNc(self.obj, AbsErrorErrFunc(), normalizer)
144            self.icp_ = IcpRegressor(nc)
145            self.icp_.fit(X_train, y_train)
146            self.icp_.calibrate(X_calibration, y_calibration)
147
148        return self
149
150    def predict(self, X, return_pi=False):
151        """Obtain predictions and prediction intervals
152
153        Args:
154
155            X: array-like, shape = [n_samples, n_features];
156                Testing set vectors, where n_samples is the number
157                of samples and n_features is the number of features.
158
159            return_pi: boolean
160                Whether the prediction interval is returned or not.
161                Default is False, for compatibility with other _estimators_.
162                If True, a tuple containing the predictions + lower and upper
163                bounds is returned.
164
165        """
166
167        pred = self.obj.predict(X)
168
169        if self.method == "splitconformal":
170
171            if self.replications is None:
172
173                if return_pi:
174
175                    DescribeResult = namedtuple(
176                        "DescribeResult", ("mean", "lower", "upper")
177                    )
178
179                    return DescribeResult(
180                        pred, pred - self.quantile_, pred + self.quantile_
181                    )
182
183                else:
184
185                    return pred
186
187            else:  # if self.replications is not None
188
189                assert self.type_pi in (
190                    "bootstrap",
191                    "kde",
192                ), "`self.type_pi` must be in ('bootstrap', 'kde')"
193
194                if self.type_pi == "bootstrap":
195                    np.random.seed(self.seed)
196                    self.residuals_sims_ = np.asarray(
197                        [
198                            np.random.choice(
199                                a=self.scaled_calibrated_residuals_,
200                                size=X.shape[0],
201                            )
202                            for _ in range(self.replications)
203                        ]
204                    ).T
205                    self.sims_ = np.asarray(
206                        [
207                            pred
208                            + self.calibrated_residuals_scaler_.scale_[0]
209                            * self.residuals_sims_[:, i].ravel()
210                            for i in range(self.replications)
211                        ]
212                    ).T
213                elif self.type_pi == "kde":
214                    self.kde_ = gaussian_kde(
215                        dataset=self.scaled_calibrated_residuals_
216                    )
217                    self.sims_ = np.asarray(
218                        [
219                            pred
220                            + self.calibrated_residuals_scaler_.scale_[0]
221                            * self.kde_.resample(
222                                size=X.shape[0], seed=self.seed + i
223                            ).ravel()
224                            for i in range(self.replications)
225                        ]
226                    ).T
227
228                self.mean_ = np.mean(self.sims_, axis=1)
229                self.lower_ = np.quantile(
230                    self.sims_, q=self.alpha_ / 200, axis=1
231                )
232                self.upper_ = np.quantile(
233                    self.sims_, q=1 - self.alpha_ / 200, axis=1
234                )
235
236                DescribeResult = namedtuple(
237                    "DescribeResult", ("mean", "sims", "lower", "upper")
238                )
239
240                return DescribeResult(
241                    self.mean_, self.sims_, self.lower_, self.upper_
242                )
243
244        if self.method == "localconformal":
245
246            if self.replications is None:
247
248                if return_pi:
249
250                    predictions_bounds = self.icp_.predict(
251                        X, significance=1 - self.level
252                    )
253                    DescribeResult = namedtuple(
254                        "DescribeResult", ("mean", "lower", "upper")
255                    )
256                    return DescribeResult(
257                        pred, predictions_bounds[:, 0], predictions_bounds[:, 1]
258                    )
259
260                else:
261
262                    return pred
263
264            else:  # if self.replications is not None
265
266                assert self.type_pi in (
267                    "bootstrap",
268                    "kde",
269                ), "`self.type_pi` must be in ('bootstrap', 'kde')"
270
271                if self.type_pi == "bootstrap":
272                    np.random.seed(self.seed)
273                    self.residuals_sims_ = np.asarray(
274                        [
275                            np.random.choice(
276                                a=self.scaled_calibrated_residuals_,
277                                size=X.shape[0],
278                            )
279                            for _ in range(self.replications)
280                        ]
281                    ).T
282                    self.sims_ = np.asarray(
283                        [
284                            pred
285                            + self.calibrated_residuals_scaler_.scale_[0]
286                            * self.residuals_sims_[:, i].ravel()
287                            for i in tqdm(range(self.replications))
288                        ]
289                    ).T
290                elif self.type_pi == "kde":
291                    self.kde_ = gaussian_kde(
292                        dataset=self.scaled_calibrated_residuals_
293                    )
294                    self.sims_ = np.asarray(
295                        [
296                            pred
297                            + self.calibrated_residuals_scaler_.scale_[0]
298                            * self.kde_.resample(
299                                size=X.shape[0], seed=self.seed + i
300                            ).ravel()
301                            for i in tqdm(range(self.replications))
302                        ]
303                    ).T
304
305                self.mean_ = np.mean(self.sims_, axis=1)
306                self.lower_ = np.quantile(
307                    self.sims_, q=self.alpha_ / 200, axis=1
308                )
309                self.upper_ = np.quantile(
310                    self.sims_, q=1 - self.alpha_ / 200, axis=1
311                )
312
313                DescribeResult = namedtuple(
314                    "DescribeResult", ("mean", "sims", "lower", "upper")
315                )
316
317                return DescribeResult(
318                    self.mean_, self.sims_, self.lower_, self.upper_
319                )

Class PredictionInterval: Obtain prediction intervals.

Attributes:

obj: an object;
    fitted object containing methods `fit` and `predict`

method: a string;
    method for constructing the prediction intervals.
    Currently "splitconformal" (default) and "localconformal"

level: a float;
    Confidence level for prediction intervals. Default is 95,
    equivalent to a miscoverage error of 5 (%)

replications: an integer;
    Number of replications for simulated conformal (default is `None`)

type_pi: a string;
    type of prediction interval: currently "kde" (default) or "bootstrap"

type_split: a string;
    "random" (random split of data) or "sequential" (sequential split of data)

seed: an integer;
    Reproducibility of fit (there's a random split between fitting and calibration data)
def fit(self, X, y, sample_weight=None, **kwargs):
 79    def fit(self, X, y, sample_weight=None, **kwargs):
 80        """Fit the `method` to training data (X, y).
 81
 82        Args:
 83
 84            X: array-like, shape = [n_samples, n_features];
 85                Training set vectors, where n_samples is the number
 86                of samples and n_features is the number of features.
 87
 88            y: array-like, shape = [n_samples, ]; Target values.
 89
 90            sample_weight: array-like, shape = [n_samples]
 91                Sample weights.
 92
 93        """
 94
 95        if self.type_split == "random":
 96            X_train, X_calibration, y_train, y_calibration = train_test_split(
 97                X, y, test_size=0.5, random_state=self.seed
 98            )
 99        elif self.type_split == "sequential":
100            n_x = X.shape[0]
101            n_x_half = n_x // 2
102            first_half_idx = range(0, n_x_half)
103            second_half_idx = range(n_x_half, n_x)
104            X_train = X[first_half_idx, :]
105            X_calibration = X[second_half_idx, :]
106            y_train = y[first_half_idx]
107            y_calibration = y[second_half_idx]
108
109        if self.method == "splitconformal":
110
111            n_samples_calibration = X_calibration.shape[0]
112            self.obj.fit(X_train, y_train)
113            preds_calibration = self.obj.predict(X_calibration)
114            self.calibrated_residuals_ = y_calibration - preds_calibration
115            absolute_residuals = np.abs(self.calibrated_residuals_)
116            self.calibrated_residuals_scaler_ = StandardScaler(
117                with_mean=True, with_std=True
118            )
119            self.scaled_calibrated_residuals_ = (
120                self.calibrated_residuals_scaler_.fit_transform(
121                    self.calibrated_residuals_.reshape(-1, 1)
122                ).ravel()
123            )
124            try:
125                # numpy version >= 1.22
126                self.quantile_ = np.quantile(
127                    a=absolute_residuals, q=self.level / 100, method="higher"
128                )
129            except:
130                # numpy version < 1.22
131                self.quantile_ = np.quantile(
132                    a=absolute_residuals,
133                    q=self.level / 100,
134                    interpolation="higher",
135                )
136
137        if self.method == "localconformal":
138
139            mad_estimator = ExtraTreesRegressor()
140            normalizer = RegressorNormalizer(
141                self.obj, mad_estimator, AbsErrorErrFunc()
142            )
143            nc = RegressorNc(self.obj, AbsErrorErrFunc(), normalizer)
144            self.icp_ = IcpRegressor(nc)
145            self.icp_.fit(X_train, y_train)
146            self.icp_.calibrate(X_calibration, y_calibration)
147
148        return self

Fit the method to training data (X, y).

Args:

X: array-like, shape = [n_samples, n_features];
    Training set vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples, ]; Target values.

sample_weight: array-like, shape = [n_samples]
    Sample weights.
def predict(self, X, return_pi=False):
150    def predict(self, X, return_pi=False):
151        """Obtain predictions and prediction intervals
152
153        Args:
154
155            X: array-like, shape = [n_samples, n_features];
156                Testing set vectors, where n_samples is the number
157                of samples and n_features is the number of features.
158
159            return_pi: boolean
160                Whether the prediction interval is returned or not.
161                Default is False, for compatibility with other _estimators_.
162                If True, a tuple containing the predictions + lower and upper
163                bounds is returned.
164
165        """
166
167        pred = self.obj.predict(X)
168
169        if self.method == "splitconformal":
170
171            if self.replications is None:
172
173                if return_pi:
174
175                    DescribeResult = namedtuple(
176                        "DescribeResult", ("mean", "lower", "upper")
177                    )
178
179                    return DescribeResult(
180                        pred, pred - self.quantile_, pred + self.quantile_
181                    )
182
183                else:
184
185                    return pred
186
187            else:  # if self.replications is not None
188
189                assert self.type_pi in (
190                    "bootstrap",
191                    "kde",
192                ), "`self.type_pi` must be in ('bootstrap', 'kde')"
193
194                if self.type_pi == "bootstrap":
195                    np.random.seed(self.seed)
196                    self.residuals_sims_ = np.asarray(
197                        [
198                            np.random.choice(
199                                a=self.scaled_calibrated_residuals_,
200                                size=X.shape[0],
201                            )
202                            for _ in range(self.replications)
203                        ]
204                    ).T
205                    self.sims_ = np.asarray(
206                        [
207                            pred
208                            + self.calibrated_residuals_scaler_.scale_[0]
209                            * self.residuals_sims_[:, i].ravel()
210                            for i in range(self.replications)
211                        ]
212                    ).T
213                elif self.type_pi == "kde":
214                    self.kde_ = gaussian_kde(
215                        dataset=self.scaled_calibrated_residuals_
216                    )
217                    self.sims_ = np.asarray(
218                        [
219                            pred
220                            + self.calibrated_residuals_scaler_.scale_[0]
221                            * self.kde_.resample(
222                                size=X.shape[0], seed=self.seed + i
223                            ).ravel()
224                            for i in range(self.replications)
225                        ]
226                    ).T
227
228                self.mean_ = np.mean(self.sims_, axis=1)
229                self.lower_ = np.quantile(
230                    self.sims_, q=self.alpha_ / 200, axis=1
231                )
232                self.upper_ = np.quantile(
233                    self.sims_, q=1 - self.alpha_ / 200, axis=1
234                )
235
236                DescribeResult = namedtuple(
237                    "DescribeResult", ("mean", "sims", "lower", "upper")
238                )
239
240                return DescribeResult(
241                    self.mean_, self.sims_, self.lower_, self.upper_
242                )
243
244        if self.method == "localconformal":
245
246            if self.replications is None:
247
248                if return_pi:
249
250                    predictions_bounds = self.icp_.predict(
251                        X, significance=1 - self.level
252                    )
253                    DescribeResult = namedtuple(
254                        "DescribeResult", ("mean", "lower", "upper")
255                    )
256                    return DescribeResult(
257                        pred, predictions_bounds[:, 0], predictions_bounds[:, 1]
258                    )
259
260                else:
261
262                    return pred
263
264            else:  # if self.replications is not None
265
266                assert self.type_pi in (
267                    "bootstrap",
268                    "kde",
269                ), "`self.type_pi` must be in ('bootstrap', 'kde')"
270
271                if self.type_pi == "bootstrap":
272                    np.random.seed(self.seed)
273                    self.residuals_sims_ = np.asarray(
274                        [
275                            np.random.choice(
276                                a=self.scaled_calibrated_residuals_,
277                                size=X.shape[0],
278                            )
279                            for _ in range(self.replications)
280                        ]
281                    ).T
282                    self.sims_ = np.asarray(
283                        [
284                            pred
285                            + self.calibrated_residuals_scaler_.scale_[0]
286                            * self.residuals_sims_[:, i].ravel()
287                            for i in tqdm(range(self.replications))
288                        ]
289                    ).T
290                elif self.type_pi == "kde":
291                    self.kde_ = gaussian_kde(
292                        dataset=self.scaled_calibrated_residuals_
293                    )
294                    self.sims_ = np.asarray(
295                        [
296                            pred
297                            + self.calibrated_residuals_scaler_.scale_[0]
298                            * self.kde_.resample(
299                                size=X.shape[0], seed=self.seed + i
300                            ).ravel()
301                            for i in tqdm(range(self.replications))
302                        ]
303                    ).T
304
305                self.mean_ = np.mean(self.sims_, axis=1)
306                self.lower_ = np.quantile(
307                    self.sims_, q=self.alpha_ / 200, axis=1
308                )
309                self.upper_ = np.quantile(
310                    self.sims_, q=1 - self.alpha_ / 200, axis=1
311                )
312
313                DescribeResult = namedtuple(
314                    "DescribeResult", ("mean", "sims", "lower", "upper")
315                )
316
317                return DescribeResult(
318                    self.mean_, self.sims_, self.lower_, self.upper_
319                )

Obtain predictions and prediction intervals

Args:

X: array-like, shape = [n_samples, n_features];
    Testing set vectors, where n_samples is the number
    of samples and n_features is the number of features.

return_pi: boolean
    Whether the prediction interval is returned or not.
    Default is False, for compatibility with other _estimators_.
    If True, a tuple containing the predictions + lower and upper
    bounds is returned.
class SimpleMultitaskClassifier(nnetsauce.Base, sklearn.base.ClassifierMixin):
 17class SimpleMultitaskClassifier(Base, ClassifierMixin):
 18    """Multitask Classification model based on regression models, with shared covariates
 19
 20    Parameters:
 21
 22        obj: object
 23            any object (must be a regression model) containing a method fit (obj.fit())
 24            and a method predict (obj.predict())
 25
 26        seed: int
 27            reproducibility seed
 28
 29    Attributes:
 30
 31        fit_objs_: dict
 32            objects adjusted to each individual time series
 33
 34        n_classes_: int
 35            number of classes for the classifier
 36
 37    Examples:
 38
 39    ```python
 40    import nnetsauce as ns
 41    import numpy as np
 42    from sklearn.datasets import load_breast_cancer
 43    from sklearn.linear_model import LinearRegression
 44    from sklearn.model_selection import train_test_split
 45    from sklearn import metrics
 46    from time import time
 47
 48    breast_cancer = load_breast_cancer()
 49    Z = breast_cancer.data
 50    t = breast_cancer.target
 51
 52    X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2,
 53                                                        random_state=123+2*10)
 54
 55    # Linear Regression is used
 56    regr = LinearRegression()
 57    fit_obj = ns.SimpleMultitaskClassifier(regr)
 58
 59    start = time()
 60    fit_obj.fit(X_train, y_train)
 61    print(f"Elapsed {time() - start}")
 62
 63    print(fit_obj.score(X_test, y_test))
 64    print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
 65
 66    start = time()
 67    preds = fit_obj.predict(X_test)
 68    print(f"Elapsed {time() - start}")
 69    print(metrics.classification_report(preds, y_test))
 70    ```
 71
 72    """
 73
 74    # construct the object -----
 75
 76    def __init__(
 77        self,
 78        obj,
 79    ):
 80        self.type_fit = "classification"
 81        self.obj = obj
 82        self.fit_objs_ = {}
 83        self.X_scaler_ = StandardScaler()
 84        self.scaled_X_ = None
 85
 86    def fit(self, X, y, sample_weight=None, **kwargs):
 87        """Fit SimpleMultitaskClassifier to training data (X, y).
 88
 89        Args:
 90
 91            X: {array-like}, shape = [n_samples, n_features]
 92                Training vectors, where n_samples is the number
 93                of samples and n_features is the number of features.
 94
 95            y: array-like, shape = [n_samples]
 96                Target values.
 97
 98            **kwargs: additional parameters to be passed to
 99                    self.cook_training_set or self.obj.fit
100
101        Returns:
102
103            self: object
104
105        """
106
107        assert mx.is_factor(y), "y must contain only integers"
108
109        self.classes_ = np.unique(y)  # for compatibility with sklearn
110        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
111
112        self.scaled_X_ = self.X_scaler_.fit_transform(X)
113
114        # multitask response
115        Y = mo.one_hot_encode2(y, self.n_classes_)
116
117        # if sample_weight is None:
118        for i in range(self.n_classes_):
119            self.fit_objs_[i] = deepcopy(
120                self.obj.fit(self.scaled_X_, Y[:, i], **kwargs)
121            )
122
123        self.classes_ = np.unique(y)
124        return self
125
126    def predict(self, X, **kwargs):
127        """Predict test data X.
128
129        Args:
130
131            X: {array-like}, shape = [n_samples, n_features]
132                Training vectors, where n_samples is the number
133                of samples and n_features is the number of features.
134
135            **kwargs: additional parameters
136
137        Returns:
138
139            model predictions: {array-like}
140
141        """
142
143        return np.argmax(self.predict_proba(X, **kwargs), axis=1)
144
145    def predict_proba(self, X, **kwargs):
146        """Predict probabilities for test data X.
147
148        Args:
149
150            X: {array-like}, shape = [n_samples, n_features]
151                Training vectors, where n_samples is the number
152                of samples and n_features is the number of features.
153
154            **kwargs: additional parameters
155
156        Returns:
157
158            probability estimates for test data: {array-like}
159
160        """
161
162        shape_X = X.shape
163
164        probs = np.zeros((shape_X[0], self.n_classes_))
165
166        if len(shape_X) == 1:
167            n_features = shape_X[0]
168
169            new_X = mo.rbind(
170                X.reshape(1, n_features),
171                np.ones(n_features).reshape(1, n_features),
172            )
173
174            Z = self.X_scaler_.transform(new_X, **kwargs)
175
176            # loop on all the classes
177            for i in range(self.n_classes_):
178                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)[0]
179
180        else:
181            Z = self.X_scaler_.transform(X, **kwargs)
182
183            # loop on all the classes
184            for i in range(self.n_classes_):
185                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)
186
187        expit_raw_probs = expit(probs)
188
189        return expit_raw_probs / expit_raw_probs.sum(axis=1)[:, None]

Multitask Classification model based on regression models, with shared covariates

Parameters:

obj: object
    any object (must be a regression model) containing a method fit (obj.fit())
    and a method predict (obj.predict())

seed: int
    reproducibility seed

Attributes:

fit_objs_: dict
    objects adjusted to each individual time series

n_classes_: int
    number of classes for the classifier

Examples:

import nnetsauce as ns
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn import metrics
from time import time

breast_cancer = load_breast_cancer()
Z = breast_cancer.data
t = breast_cancer.target

X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2,
                                                    random_state=123+2*10)

# Linear Regression is used
regr = LinearRegression()
fit_obj = ns.SimpleMultitaskClassifier(regr)

start = time()
fit_obj.fit(X_train, y_train)
print(f"Elapsed {time() - start}")

print(fit_obj.score(X_test, y_test))
print(fit_obj.score(X_test, y_test, scoring="roc_auc"))

start = time()
preds = fit_obj.predict(X_test)
print(f"Elapsed {time() - start}")
print(metrics.classification_report(preds, y_test))
def fit(self, X, y, sample_weight=None, **kwargs):
 86    def fit(self, X, y, sample_weight=None, **kwargs):
 87        """Fit SimpleMultitaskClassifier to training data (X, y).
 88
 89        Args:
 90
 91            X: {array-like}, shape = [n_samples, n_features]
 92                Training vectors, where n_samples is the number
 93                of samples and n_features is the number of features.
 94
 95            y: array-like, shape = [n_samples]
 96                Target values.
 97
 98            **kwargs: additional parameters to be passed to
 99                    self.cook_training_set or self.obj.fit
100
101        Returns:
102
103            self: object
104
105        """
106
107        assert mx.is_factor(y), "y must contain only integers"
108
109        self.classes_ = np.unique(y)  # for compatibility with sklearn
110        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
111
112        self.scaled_X_ = self.X_scaler_.fit_transform(X)
113
114        # multitask response
115        Y = mo.one_hot_encode2(y, self.n_classes_)
116
117        # if sample_weight is None:
118        for i in range(self.n_classes_):
119            self.fit_objs_[i] = deepcopy(
120                self.obj.fit(self.scaled_X_, Y[:, i], **kwargs)
121            )
122
123        self.classes_ = np.unique(y)
124        return self

Fit SimpleMultitaskClassifier to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
126    def predict(self, X, **kwargs):
127        """Predict test data X.
128
129        Args:
130
131            X: {array-like}, shape = [n_samples, n_features]
132                Training vectors, where n_samples is the number
133                of samples and n_features is the number of features.
134
135            **kwargs: additional parameters
136
137        Returns:
138
139            model predictions: {array-like}
140
141        """
142
143        return np.argmax(self.predict_proba(X, **kwargs), axis=1)

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
145    def predict_proba(self, X, **kwargs):
146        """Predict probabilities for test data X.
147
148        Args:
149
150            X: {array-like}, shape = [n_samples, n_features]
151                Training vectors, where n_samples is the number
152                of samples and n_features is the number of features.
153
154            **kwargs: additional parameters
155
156        Returns:
157
158            probability estimates for test data: {array-like}
159
160        """
161
162        shape_X = X.shape
163
164        probs = np.zeros((shape_X[0], self.n_classes_))
165
166        if len(shape_X) == 1:
167            n_features = shape_X[0]
168
169            new_X = mo.rbind(
170                X.reshape(1, n_features),
171                np.ones(n_features).reshape(1, n_features),
172            )
173
174            Z = self.X_scaler_.transform(new_X, **kwargs)
175
176            # loop on all the classes
177            for i in range(self.n_classes_):
178                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)[0]
179
180        else:
181            Z = self.X_scaler_.transform(X, **kwargs)
182
183            # loop on all the classes
184            for i in range(self.n_classes_):
185                probs[:, i] = self.fit_objs_[i].predict(Z, **kwargs)
186
187        expit_raw_probs = expit(probs)
188
189        return expit_raw_probs / expit_raw_probs.sum(axis=1)[:, None]

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters

Returns:

probability estimates for test data: {array-like}
class Optimizer:
  9class Optimizer:
 10    """Optimizer class
 11
 12    Attributes:
 13
 14        type_optim: str
 15            type of optimizer, (currently) either 'sgd' (stochastic minibatch gradient descent)
 16            or 'scd' (stochastic minibatch coordinate descent)
 17
 18        num_iters: int
 19            number of iterations of the optimizer
 20
 21        learning_rate: float
 22            step size
 23
 24        batch_prop: float
 25            proportion of the initial data used at each optimization step
 26
 27        learning_method: str
 28            "poly" - learning rate decreasing as a polynomial function
 29            of # of iterations (default)
 30            "exp" - learning rate decreasing as an exponential function
 31            of # of iterations
 32            "momentum" - gradient descent using momentum
 33
 34        randomization: str
 35            type of randomization applied at each step
 36            "strat" - stratified subsampling (default)
 37            "shuffle" - random subsampling
 38
 39        mass: float
 40            mass on velocity, for `method` == "momentum"
 41
 42        decay: float
 43            coefficient of decrease of the learning rate for
 44            `method` == "poly" and `method` == "exp"
 45
 46        tolerance: float
 47            early stopping parameter (convergence of loss function)
 48
 49        verbose: int
 50            controls verbosity of gradient descent
 51            0 - nothing is printed
 52            1 - a progress bar is printed
 53            2 - successive loss function values are printed
 54
 55    """
 56
 57    # construct the object -----
 58
 59    def __init__(
 60        self,
 61        type_optim="sgd",
 62        num_iters=100,
 63        learning_rate=0.01,
 64        batch_prop=1.0,
 65        learning_method="momentum",
 66        randomization="strat",
 67        mass=0.9,
 68        decay=0.1,
 69        tolerance=1e-3,
 70        verbose=1,
 71    ):
 72        self.type_optim = type_optim
 73        self.num_iters = num_iters
 74        self.learning_rate = learning_rate
 75        self.batch_prop = batch_prop
 76        self.learning_method = learning_method
 77        self.randomization = randomization
 78        self.mass = mass
 79        self.decay = decay
 80        self.tolerance = tolerance
 81        self.verbose = verbose
 82        self.opt = None
 83
 84    def fit(self, loss_func, response, x0, **kwargs):
 85        """Fit GLM model to training data (X, y).
 86
 87        Args:
 88
 89            loss_func: loss function
 90
 91            response: array-like, shape = [n_samples]
 92            target variable (used for subsampling)
 93
 94            x0: array-like, shape = [n_features]
 95                initial value provided to the optimizer
 96
 97            **kwargs: additional parameters to be passed to
 98                    loss function
 99
100        Returns:
101
102            self: object
103
104        """
105
106        if self.type_optim == "scd":
107            self.results = scd(
108                loss_func,
109                response=response,
110                x=x0,
111                num_iters=self.num_iters,
112                batch_prop=self.batch_prop,
113                learning_rate=self.learning_rate,
114                learning_method=self.learning_method,
115                mass=self.mass,
116                decay=self.decay,
117                randomization=self.randomization,
118                tolerance=self.tolerance,
119                verbose=self.verbose,
120                **kwargs
121            )
122
123        if self.type_optim == "sgd":
124            self.results = sgd(
125                loss_func,
126                response=response,
127                x=x0,
128                num_iters=self.num_iters,
129                batch_prop=self.batch_prop,
130                learning_rate=self.learning_rate,
131                learning_method=self.learning_method,
132                mass=self.mass,
133                decay=self.decay,
134                randomization=self.randomization,
135                tolerance=self.tolerance,
136                verbose=self.verbose,
137                **kwargs
138            )
139
140        return self
141
142    def one_hot_encode(self, y, n_classes):
143        return one_hot_encode(y, n_classes)

Optimizer class

Attributes:

type_optim: str
    type of optimizer, (currently) either 'sgd' (stochastic minibatch gradient descent)
    or 'scd' (stochastic minibatch coordinate descent)

num_iters: int
    number of iterations of the optimizer

learning_rate: float
    step size

batch_prop: float
    proportion of the initial data used at each optimization step

learning_method: str
    "poly" - learning rate decreasing as a polynomial function
    of # of iterations (default)
    "exp" - learning rate decreasing as an exponential function
    of # of iterations
    "momentum" - gradient descent using momentum

randomization: str
    type of randomization applied at each step
    "strat" - stratified subsampling (default)
    "shuffle" - random subsampling

mass: float
    mass on velocity, for `method` == "momentum"

decay: float
    coefficient of decrease of the learning rate for
    `method` == "poly" and `method` == "exp"

tolerance: float
    early stopping parameter (convergence of loss function)

verbose: int
    controls verbosity of gradient descent
    0 - nothing is printed
    1 - a progress bar is printed
    2 - successive loss function values are printed
def fit(self, loss_func, response, x0, **kwargs):
 84    def fit(self, loss_func, response, x0, **kwargs):
 85        """Fit GLM model to training data (X, y).
 86
 87        Args:
 88
 89            loss_func: loss function
 90
 91            response: array-like, shape = [n_samples]
 92            target variable (used for subsampling)
 93
 94            x0: array-like, shape = [n_features]
 95                initial value provided to the optimizer
 96
 97            **kwargs: additional parameters to be passed to
 98                    loss function
 99
100        Returns:
101
102            self: object
103
104        """
105
106        if self.type_optim == "scd":
107            self.results = scd(
108                loss_func,
109                response=response,
110                x=x0,
111                num_iters=self.num_iters,
112                batch_prop=self.batch_prop,
113                learning_rate=self.learning_rate,
114                learning_method=self.learning_method,
115                mass=self.mass,
116                decay=self.decay,
117                randomization=self.randomization,
118                tolerance=self.tolerance,
119                verbose=self.verbose,
120                **kwargs
121            )
122
123        if self.type_optim == "sgd":
124            self.results = sgd(
125                loss_func,
126                response=response,
127                x=x0,
128                num_iters=self.num_iters,
129                batch_prop=self.batch_prop,
130                learning_rate=self.learning_rate,
131                learning_method=self.learning_method,
132                mass=self.mass,
133                decay=self.decay,
134                randomization=self.randomization,
135                tolerance=self.tolerance,
136                verbose=self.verbose,
137                **kwargs
138            )
139
140        return self

Fit GLM model to training data (X, y).

Args:

loss_func: loss function

response: array-like, shape = [n_samples]
target variable (used for subsampling)

x0: array-like, shape = [n_features]
    initial value provided to the optimizer

**kwargs: additional parameters to be passed to
        loss function

Returns:

self: object
class RandomBagRegressor(nnetsauce.randombag.bag.RandomBag, sklearn.base.RegressorMixin):
 18class RandomBagRegressor(RandomBag, RegressorMixin):
 19    """Randomized 'Bagging' Regression model
 20
 21    Parameters:
 22
 23        obj: object
 24            any object containing a method fit (obj.fit()) and a method predict
 25            (obj.predict())
 26
 27        n_estimators: int
 28            number of boosting iterations
 29
 30        n_hidden_features: int
 31            number of nodes in the hidden layer
 32
 33        activation_name: str
 34            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 35
 36        a: float
 37            hyperparameter for 'prelu' or 'elu' activation function
 38
 39        nodes_sim: str
 40            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 41            'uniform'
 42
 43        bias: boolean
 44            indicates if the hidden layer contains a bias term (True) or not
 45            (False)
 46
 47        dropout: float
 48            regularization parameter; (random) percentage of nodes dropped out
 49            of the training
 50
 51        direct_link: boolean
 52            indicates if the original predictors are included (True) in model''s
 53            fitting or not (False)
 54
 55        n_clusters: int
 56            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 57                no clustering)
 58
 59        cluster_encode: bool
 60            defines how the variable containing clusters is treated (default is one-hot)
 61            if `False`, then labels are used, without one-hot encoding
 62
 63        type_clust: str
 64            type of clustering method: currently k-means ('kmeans') or Gaussian
 65            Mixture Model ('gmm')
 66
 67        type_scaling: a tuple of 3 strings
 68            scaling methods for inputs, hidden layer, and clustering respectively
 69            (and when relevant).
 70            Currently available: standardization ('std') or MinMax scaling ('minmax')
 71
 72        col_sample: float
 73            percentage of covariates randomly chosen for training
 74
 75        row_sample: float
 76            percentage of rows chosen for training, by stratified bootstrapping
 77
 78        seed: int
 79            reproducibility seed for nodes_sim=='uniform'
 80
 81        backend: str
 82            "cpu" or "gpu" or "tpu"
 83
 84    Attributes:
 85
 86        voter_: dict
 87            dictionary containing all the fitted base-learners
 88
 89
 90    Examples:
 91
 92    ```python
 93    import numpy as np
 94    import nnetsauce as ns
 95    from sklearn.datasets import fetch_california_housing
 96    from sklearn.tree import DecisionTreeRegressor
 97    from sklearn.model_selection import train_test_split
 98
 99    X, y = fetch_california_housing(return_X_y=True, as_frame=False)
100
101    # split data into training test and test set
102    X_train, X_test, y_train, y_test = train_test_split(X, y,
103                                                        test_size=0.2, random_state=13)
104
105    # Requires further tuning
106    obj = DecisionTreeRegressor(max_depth=3, random_state=123)
107    obj2 = ns.RandomBagRegressor(obj=obj, direct_link=False,
108                                n_estimators=50,
109                                col_sample=0.9, row_sample=0.9,
110                                dropout=0, n_clusters=0, verbose=1)
111
112    obj2.fit(X_train, y_train)
113
114    print(np.sqrt(obj2.score(X_test, y_test))) # RMSE
115
116    ```
117
118    """
119
120    # construct the object -----
121
122    def __init__(
123        self,
124        obj,
125        n_estimators=10,
126        n_hidden_features=1,
127        activation_name="relu",
128        a=0.01,
129        nodes_sim="sobol",
130        bias=True,
131        dropout=0,
132        direct_link=False,
133        n_clusters=2,
134        cluster_encode=True,
135        type_clust="kmeans",
136        type_scaling=("std", "std", "std"),
137        col_sample=1,
138        row_sample=1,
139        n_jobs=None,
140        seed=123,
141        verbose=1,
142        backend="cpu",
143    ):
144        super().__init__(
145            obj=obj,
146            n_estimators=n_estimators,
147            n_hidden_features=n_hidden_features,
148            activation_name=activation_name,
149            a=a,
150            nodes_sim=nodes_sim,
151            bias=bias,
152            dropout=dropout,
153            direct_link=direct_link,
154            n_clusters=n_clusters,
155            cluster_encode=cluster_encode,
156            type_clust=type_clust,
157            type_scaling=type_scaling,
158            col_sample=col_sample,
159            row_sample=row_sample,
160            seed=seed,
161            backend=backend,
162        )
163
164        self.type_fit = "regression"
165        self.verbose = verbose
166        self.n_jobs = n_jobs
167        self.voter_ = {}
168
169    def fit(self, X, y, **kwargs):
170        """Fit Random 'Bagging' model to training data (X, y).
171
172        Args:
173
174            X: {array-like}, shape = [n_samples, n_features]
175                Training vectors, where n_samples is the number
176                of samples and n_features is the number of features.
177
178            y: array-like, shape = [n_samples]
179                Target values.
180
181            **kwargs: additional parameters to be passed to
182                    self.cook_training_set or self.obj.fit
183
184        Returns:
185
186            self: object
187
188        """
189
190        base_learner = CustomRegressor(
191            self.obj,
192            n_hidden_features=self.n_hidden_features,
193            activation_name=self.activation_name,
194            a=self.a,
195            nodes_sim=self.nodes_sim,
196            bias=self.bias,
197            dropout=self.dropout,
198            direct_link=self.direct_link,
199            n_clusters=self.n_clusters,
200            type_clust=self.type_clust,
201            type_scaling=self.type_scaling,
202            col_sample=self.col_sample,
203            row_sample=self.row_sample,
204            seed=self.seed,
205        )
206
207        # 1 - Sequential training -----
208
209        if self.n_jobs is None:
210            self.voter_ = rbagloop_regression(
211                base_learner, X, y, self.n_estimators, self.verbose, self.seed
212            )
213
214            self.n_estimators = len(self.voter_)
215
216            return self
217
218        # 2 - Parallel training -----
219        # buggy
220        # if self.n_jobs is not None:
221        def fit_estimators(m):
222            base_learner__ = pickle.loads(pickle.dumps(base_learner, -1))
223            base_learner__.set_params(seed=self.seed + m * 1000)
224            base_learner__.fit(X, y, **kwargs)
225            return base_learner__
226
227        if self.verbose == 1:
228            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
229                delayed(fit_estimators)(m)
230                for m in tqdm(range(self.n_estimators))
231            )
232        else:
233            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
234                delayed(fit_estimators)(m) for m in range(self.n_estimators)
235            )
236
237        self.voter_ = {i: elt for i, elt in enumerate(voters_list)}
238
239        self.n_estimators = len(self.voter_)
240
241        return self
242
243    def predict(self, X, weights=None, **kwargs):
244        """Predict for test data X.
245
246        Args:
247
248            X: {array-like}, shape = [n_samples, n_features]
249                Training vectors, where n_samples is the number
250                of samples and n_features is the number of features.
251
252            **kwargs: additional parameters to be passed to
253                    self.cook_test_set
254
255        Returns:
256
257            estimates for test data: {array-like}
258
259        """
260
261        def calculate_preds(voter, weights=None):
262            ensemble_preds = 0
263
264            n_iter = len(voter)
265
266            assert n_iter > 0, "no estimator found in `RandomBag` ensemble"
267
268            if weights is None:
269                for idx, elt in voter.items():
270                    ensemble_preds += elt.predict(X)
271
272                return ensemble_preds / n_iter
273
274            # if weights is not None:
275            for idx, elt in voter.items():
276                ensemble_preds += weights[idx] * elt.predict(X)
277
278            return ensemble_preds
279
280        # end calculate_preds ----
281
282        if weights is None:
283            return calculate_preds(self.voter_)
284
285        # if weights is not None:
286        self.weights = weights
287
288        return calculate_preds(self.voter_, weights)

Randomized 'Bagging' Regression model

Parameters:

obj: object
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict())

n_estimators: int
    number of boosting iterations

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model''s
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

col_sample: float
    percentage of covariates randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

voter_: dict
    dictionary containing all the fitted base-learners

Examples:

import numpy as np
import nnetsauce as ns
from sklearn.datasets import fetch_california_housing
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split

X, y = fetch_california_housing(return_X_y=True, as_frame=False)

# split data into training test and test set
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    test_size=0.2, random_state=13)

# Requires further tuning
obj = DecisionTreeRegressor(max_depth=3, random_state=123)
obj2 = ns.RandomBagRegressor(obj=obj, direct_link=False,
                            n_estimators=50,
                            col_sample=0.9, row_sample=0.9,
                            dropout=0, n_clusters=0, verbose=1)

obj2.fit(X_train, y_train)

print(np.sqrt(obj2.score(X_test, y_test))) # RMSE
def fit(self, X, y, **kwargs):
169    def fit(self, X, y, **kwargs):
170        """Fit Random 'Bagging' model to training data (X, y).
171
172        Args:
173
174            X: {array-like}, shape = [n_samples, n_features]
175                Training vectors, where n_samples is the number
176                of samples and n_features is the number of features.
177
178            y: array-like, shape = [n_samples]
179                Target values.
180
181            **kwargs: additional parameters to be passed to
182                    self.cook_training_set or self.obj.fit
183
184        Returns:
185
186            self: object
187
188        """
189
190        base_learner = CustomRegressor(
191            self.obj,
192            n_hidden_features=self.n_hidden_features,
193            activation_name=self.activation_name,
194            a=self.a,
195            nodes_sim=self.nodes_sim,
196            bias=self.bias,
197            dropout=self.dropout,
198            direct_link=self.direct_link,
199            n_clusters=self.n_clusters,
200            type_clust=self.type_clust,
201            type_scaling=self.type_scaling,
202            col_sample=self.col_sample,
203            row_sample=self.row_sample,
204            seed=self.seed,
205        )
206
207        # 1 - Sequential training -----
208
209        if self.n_jobs is None:
210            self.voter_ = rbagloop_regression(
211                base_learner, X, y, self.n_estimators, self.verbose, self.seed
212            )
213
214            self.n_estimators = len(self.voter_)
215
216            return self
217
218        # 2 - Parallel training -----
219        # buggy
220        # if self.n_jobs is not None:
221        def fit_estimators(m):
222            base_learner__ = pickle.loads(pickle.dumps(base_learner, -1))
223            base_learner__.set_params(seed=self.seed + m * 1000)
224            base_learner__.fit(X, y, **kwargs)
225            return base_learner__
226
227        if self.verbose == 1:
228            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
229                delayed(fit_estimators)(m)
230                for m in tqdm(range(self.n_estimators))
231            )
232        else:
233            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
234                delayed(fit_estimators)(m) for m in range(self.n_estimators)
235            )
236
237        self.voter_ = {i: elt for i, elt in enumerate(voters_list)}
238
239        self.n_estimators = len(self.voter_)
240
241        return self

Fit Random 'Bagging' model to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, weights=None, **kwargs):
243    def predict(self, X, weights=None, **kwargs):
244        """Predict for test data X.
245
246        Args:
247
248            X: {array-like}, shape = [n_samples, n_features]
249                Training vectors, where n_samples is the number
250                of samples and n_features is the number of features.
251
252            **kwargs: additional parameters to be passed to
253                    self.cook_test_set
254
255        Returns:
256
257            estimates for test data: {array-like}
258
259        """
260
261        def calculate_preds(voter, weights=None):
262            ensemble_preds = 0
263
264            n_iter = len(voter)
265
266            assert n_iter > 0, "no estimator found in `RandomBag` ensemble"
267
268            if weights is None:
269                for idx, elt in voter.items():
270                    ensemble_preds += elt.predict(X)
271
272                return ensemble_preds / n_iter
273
274            # if weights is not None:
275            for idx, elt in voter.items():
276                ensemble_preds += weights[idx] * elt.predict(X)
277
278            return ensemble_preds
279
280        # end calculate_preds ----
281
282        if weights is None:
283            return calculate_preds(self.voter_)
284
285        # if weights is not None:
286        self.weights = weights
287
288        return calculate_preds(self.voter_, weights)

Predict for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

estimates for test data: {array-like}
class RandomBagClassifier(nnetsauce.randombag.bag.RandomBag, sklearn.base.ClassifierMixin):
 18class RandomBagClassifier(RandomBag, ClassifierMixin):
 19    """Randomized 'Bagging' Classification model
 20
 21    Parameters:
 22
 23        obj: object
 24            any object containing a method fit (obj.fit()) and a method predict
 25            (obj.predict())
 26
 27        n_estimators: int
 28            number of boosting iterations
 29
 30        n_hidden_features: int
 31            number of nodes in the hidden layer
 32
 33        activation_name: str
 34            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 35
 36        a: float
 37            hyperparameter for 'prelu' or 'elu' activation function
 38
 39        nodes_sim: str
 40            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 41            'uniform'
 42
 43        bias: boolean
 44            indicates if the hidden layer contains a bias term (True) or not
 45            (False)
 46
 47        dropout: float
 48            regularization parameter; (random) percentage of nodes dropped out
 49            of the training
 50
 51        direct_link: boolean
 52            indicates if the original predictors are included (True) in model's
 53            fitting or not (False)
 54
 55        n_clusters: int
 56            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 57                no clustering)
 58
 59        cluster_encode: bool
 60            defines how the variable containing clusters is treated (default is one-hot)
 61            if `False`, then labels are used, without one-hot encoding
 62
 63        type_clust: str
 64            type of clustering method: currently k-means ('kmeans') or Gaussian
 65            Mixture Model ('gmm')
 66
 67        type_scaling: a tuple of 3 strings
 68            scaling methods for inputs, hidden layer, and clustering respectively
 69            (and when relevant).
 70            Currently available: standardization ('std') or MinMax scaling ('minmax')
 71
 72        col_sample: float
 73            percentage of covariates randomly chosen for training
 74
 75        row_sample: float
 76            percentage of rows chosen for training, by stratified bootstrapping
 77
 78        seed: int
 79            reproducibility seed for nodes_sim=='uniform'
 80
 81        backend: str
 82            "cpu" or "gpu" or "tpu"
 83
 84    Attributes:
 85
 86        voter_: dict
 87            dictionary containing all the fitted base-learners
 88
 89
 90    Examples:
 91
 92    See also [https://github.com/Techtonique/nnetsauce/blob/master/examples/randombag_classification.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/randombag_classification.py)
 93
 94    ```python
 95    import nnetsauce as ns
 96    from sklearn.datasets import load_breast_cancer
 97    from sklearn.tree import DecisionTreeClassifier
 98    from sklearn.model_selection import train_test_split
 99    from sklearn import metrics
100    from time import time
101
102
103    breast_cancer = load_breast_cancer()
104    Z = breast_cancer.data
105    t = breast_cancer.target
106    np.random.seed(123)
107    X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2)
108
109    # decision tree
110    clf = DecisionTreeClassifier(max_depth=2, random_state=123)
111    fit_obj = ns.RandomBagClassifier(clf, n_hidden_features=2,
112                                    direct_link=True,
113                                    n_estimators=100,
114                                    col_sample=0.9, row_sample=0.9,
115                                    dropout=0.3, n_clusters=0, verbose=1)
116
117    start = time()
118    fit_obj.fit(X_train, y_train)
119    print(f"Elapsed {time() - start}")
120
121    print(fit_obj.score(X_test, y_test))
122    print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
123
124    start = time()
125    preds = fit_obj.predict(X_test)
126    print(f"Elapsed {time() - start}")
127    print(metrics.classification_report(preds, y_test))
128    ```
129
130    """
131
132    # construct the object -----
133
134    def __init__(
135        self,
136        obj,
137        n_estimators=10,
138        n_hidden_features=1,
139        activation_name="relu",
140        a=0.01,
141        nodes_sim="sobol",
142        bias=True,
143        dropout=0,
144        direct_link=False,
145        n_clusters=2,
146        cluster_encode=True,
147        type_clust="kmeans",
148        type_scaling=("std", "std", "std"),
149        col_sample=1,
150        row_sample=1,
151        n_jobs=None,
152        seed=123,
153        verbose=1,
154        backend="cpu",
155    ):
156        super().__init__(
157            obj=obj,
158            n_estimators=n_estimators,
159            n_hidden_features=n_hidden_features,
160            activation_name=activation_name,
161            a=a,
162            nodes_sim=nodes_sim,
163            bias=bias,
164            dropout=dropout,
165            direct_link=direct_link,
166            n_clusters=n_clusters,
167            cluster_encode=cluster_encode,
168            type_clust=type_clust,
169            type_scaling=type_scaling,
170            col_sample=col_sample,
171            row_sample=row_sample,
172            seed=seed,
173            backend=backend,
174        )
175
176        self.type_fit = "classification"
177        self.verbose = verbose
178        self.n_jobs = n_jobs
179        self.voter_ = {}
180
181    def fit(self, X, y, **kwargs):
182        """Fit Random 'Bagging' model to training data (X, y).
183
184        Args:
185
186            X: {array-like}, shape = [n_samples, n_features]
187                Training vectors, where n_samples is the number
188                of samples and n_features is the number of features.
189
190            y: array-like, shape = [n_samples]
191                Target values.
192
193            **kwargs: additional parameters to be passed to
194                    self.cook_training_set or self.obj.fit
195
196        Returns:
197
198            self: object
199
200        """
201
202        assert mx.is_factor(y), "y must contain only integers"
203
204        self.n_classes_ = len(np.unique(y))  # for compatibility with sklearn
205
206        # training
207        self.n_classes = len(np.unique(y))
208
209        base_learner = CustomClassifier(
210            self.obj,
211            n_hidden_features=self.n_hidden_features,
212            activation_name=self.activation_name,
213            a=self.a,
214            nodes_sim=self.nodes_sim,
215            bias=self.bias,
216            dropout=self.dropout,
217            direct_link=self.direct_link,
218            n_clusters=self.n_clusters,
219            type_clust=self.type_clust,
220            type_scaling=self.type_scaling,
221            col_sample=self.col_sample,
222            row_sample=self.row_sample,
223            seed=self.seed,
224        )
225
226        # 1 - Sequential training -----
227
228        if self.n_jobs is None:
229            self.voter_ = rbagloop_classification(
230                base_learner, X, y, self.n_estimators, self.verbose, self.seed
231            )
232
233            self.n_estimators = len(self.voter_)
234
235            return self
236
237        # 2 - Parallel training -----
238        # buggy
239        # if self.n_jobs is not None:
240        def fit_estimators(m):
241            base_learner__ = pickle.loads(pickle.dumps(base_learner, -1))
242            base_learner__.set_params(seed=self.seed + m * 1000)
243            base_learner__.fit(X, y, **kwargs)
244            return base_learner__
245
246        if self.verbose == 1:
247            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
248                delayed(fit_estimators)(m)
249                for m in tqdm(range(self.n_estimators))
250            )
251        else:
252            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
253                delayed(fit_estimators)(m) for m in range(self.n_estimators)
254            )
255
256        self.voter_ = {idx: elt for idx, elt in enumerate(voters_list)}
257
258        self.n_estimators = len(self.voter_)
259        self.classes_ = np.unique(y)
260        return self
261
262    def predict(self, X, weights=None, **kwargs):
263        """Predict test data X.
264
265        Args:
266
267            X: {array-like}, shape = [n_samples, n_features]
268                Training vectors, where n_samples is the number
269                of samples and n_features is the number of features.
270
271            **kwargs: additional parameters to be passed to
272                    self.cook_test_set
273
274        Returns:
275
276            model predictions: {array-like}
277
278        """
279        return self.predict_proba(X, weights, **kwargs).argmax(axis=1)
280
281    def predict_proba(self, X, weights=None, **kwargs):
282        """Predict probabilities for test data X.
283
284        Args:
285
286            X: {array-like}, shape = [n_samples, n_features]
287                Training vectors, where n_samples is the number
288                of samples and n_features is the number of features.
289
290            **kwargs: additional parameters to be passed to
291                    self.cook_test_set
292
293        Returns:
294
295            probability estimates for test data: {array-like}
296
297        """
298
299        def calculate_probas(voter, weights=None, verbose=None):
300            ensemble_proba = 0
301
302            n_iter = len(voter)
303
304            assert n_iter > 0, "no estimator found in `RandomBag` ensemble"
305
306            if weights is None:
307                for idx, elt in voter.items():
308                    try:
309                        ensemble_proba += elt.predict_proba(X)
310
311                        # if verbose == 1:
312                        #    pbar.update(idx)
313
314                    except:
315                        continue
316
317                # if verbose == 1:
318                #    pbar.update(n_iter)
319
320                return ensemble_proba / n_iter
321
322            # if weights is not None:
323            for idx, elt in voter.items():
324                ensemble_proba += weights[idx] * elt.predict_proba(X)
325
326                # if verbose == 1:
327                #    pbar.update(idx)
328
329            # if verbose == 1:
330            #    pbar.update(n_iter)
331
332            return ensemble_proba
333
334        # end calculate_probas ----
335
336        if self.n_jobs is None:
337            # if self.verbose == 1:
338            #    pbar = Progbar(self.n_estimators)
339
340            if weights is None:
341                return calculate_probas(self.voter_, verbose=self.verbose)
342
343            # if weights is not None:
344            self.weights = weights
345
346            return calculate_probas(self.voter_, weights, verbose=self.verbose)
347
348        # if self.n_jobs is not None:
349        def predict_estimator(m):
350            try:
351                return self.voter_[m].predict_proba(X)
352            except:
353                pass
354
355        if self.verbose == 1:
356            preds = Parallel(n_jobs=self.n_jobs, prefer="threads")(
357                delayed(predict_estimator)(m)
358                for m in tqdm(range(self.n_estimators))
359            )
360
361        else:
362            preds = Parallel(n_jobs=self.n_jobs, prefer="threads")(
363                delayed(predict_estimator)(m) for m in range(self.n_estimators)
364            )
365
366        ensemble_proba = 0
367
368        if weights is None:
369            for i in range(self.n_estimators):
370                ensemble_proba += preds[i]
371
372            return ensemble_proba / self.n_estimators
373
374        for i in range(self.n_estimators):
375            ensemble_proba += weights[i] * preds[i]
376
377        return ensemble_proba

Randomized 'Bagging' Classification model

Parameters:

obj: object
    any object containing a method fit (obj.fit()) and a method predict
    (obj.predict())

n_estimators: int
    number of boosting iterations

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

col_sample: float
    percentage of covariates randomly chosen for training

row_sample: float
    percentage of rows chosen for training, by stratified bootstrapping

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

voter_: dict
    dictionary containing all the fitted base-learners

Examples:

See also https://github.com/Techtonique/nnetsauce/blob/master/examples/randombag_classification.py

import nnetsauce as ns
from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn import metrics
from time import time


breast_cancer = load_breast_cancer()
Z = breast_cancer.data
t = breast_cancer.target
np.random.seed(123)
X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2)

# decision tree
clf = DecisionTreeClassifier(max_depth=2, random_state=123)
fit_obj = ns.RandomBagClassifier(clf, n_hidden_features=2,
                                direct_link=True,
                                n_estimators=100,
                                col_sample=0.9, row_sample=0.9,
                                dropout=0.3, n_clusters=0, verbose=1)

start = time()
fit_obj.fit(X_train, y_train)
print(f"Elapsed {time() - start}")

print(fit_obj.score(X_test, y_test))
print(fit_obj.score(X_test, y_test, scoring="roc_auc"))

start = time()
preds = fit_obj.predict(X_test)
print(f"Elapsed {time() - start}")
print(metrics.classification_report(preds, y_test))
def fit(self, X, y, **kwargs):
181    def fit(self, X, y, **kwargs):
182        """Fit Random 'Bagging' model to training data (X, y).
183
184        Args:
185
186            X: {array-like}, shape = [n_samples, n_features]
187                Training vectors, where n_samples is the number
188                of samples and n_features is the number of features.
189
190            y: array-like, shape = [n_samples]
191                Target values.
192
193            **kwargs: additional parameters to be passed to
194                    self.cook_training_set or self.obj.fit
195
196        Returns:
197
198            self: object
199
200        """
201
202        assert mx.is_factor(y), "y must contain only integers"
203
204        self.n_classes_ = len(np.unique(y))  # for compatibility with sklearn
205
206        # training
207        self.n_classes = len(np.unique(y))
208
209        base_learner = CustomClassifier(
210            self.obj,
211            n_hidden_features=self.n_hidden_features,
212            activation_name=self.activation_name,
213            a=self.a,
214            nodes_sim=self.nodes_sim,
215            bias=self.bias,
216            dropout=self.dropout,
217            direct_link=self.direct_link,
218            n_clusters=self.n_clusters,
219            type_clust=self.type_clust,
220            type_scaling=self.type_scaling,
221            col_sample=self.col_sample,
222            row_sample=self.row_sample,
223            seed=self.seed,
224        )
225
226        # 1 - Sequential training -----
227
228        if self.n_jobs is None:
229            self.voter_ = rbagloop_classification(
230                base_learner, X, y, self.n_estimators, self.verbose, self.seed
231            )
232
233            self.n_estimators = len(self.voter_)
234
235            return self
236
237        # 2 - Parallel training -----
238        # buggy
239        # if self.n_jobs is not None:
240        def fit_estimators(m):
241            base_learner__ = pickle.loads(pickle.dumps(base_learner, -1))
242            base_learner__.set_params(seed=self.seed + m * 1000)
243            base_learner__.fit(X, y, **kwargs)
244            return base_learner__
245
246        if self.verbose == 1:
247            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
248                delayed(fit_estimators)(m)
249                for m in tqdm(range(self.n_estimators))
250            )
251        else:
252            voters_list = Parallel(n_jobs=self.n_jobs, prefer="threads")(
253                delayed(fit_estimators)(m) for m in range(self.n_estimators)
254            )
255
256        self.voter_ = {idx: elt for idx, elt in enumerate(voters_list)}
257
258        self.n_estimators = len(self.voter_)
259        self.classes_ = np.unique(y)
260        return self

Fit Random 'Bagging' model to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, weights=None, **kwargs):
262    def predict(self, X, weights=None, **kwargs):
263        """Predict test data X.
264
265        Args:
266
267            X: {array-like}, shape = [n_samples, n_features]
268                Training vectors, where n_samples is the number
269                of samples and n_features is the number of features.
270
271            **kwargs: additional parameters to be passed to
272                    self.cook_test_set
273
274        Returns:
275
276            model predictions: {array-like}
277
278        """
279        return self.predict_proba(X, weights, **kwargs).argmax(axis=1)

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, weights=None, **kwargs):
281    def predict_proba(self, X, weights=None, **kwargs):
282        """Predict probabilities for test data X.
283
284        Args:
285
286            X: {array-like}, shape = [n_samples, n_features]
287                Training vectors, where n_samples is the number
288                of samples and n_features is the number of features.
289
290            **kwargs: additional parameters to be passed to
291                    self.cook_test_set
292
293        Returns:
294
295            probability estimates for test data: {array-like}
296
297        """
298
299        def calculate_probas(voter, weights=None, verbose=None):
300            ensemble_proba = 0
301
302            n_iter = len(voter)
303
304            assert n_iter > 0, "no estimator found in `RandomBag` ensemble"
305
306            if weights is None:
307                for idx, elt in voter.items():
308                    try:
309                        ensemble_proba += elt.predict_proba(X)
310
311                        # if verbose == 1:
312                        #    pbar.update(idx)
313
314                    except:
315                        continue
316
317                # if verbose == 1:
318                #    pbar.update(n_iter)
319
320                return ensemble_proba / n_iter
321
322            # if weights is not None:
323            for idx, elt in voter.items():
324                ensemble_proba += weights[idx] * elt.predict_proba(X)
325
326                # if verbose == 1:
327                #    pbar.update(idx)
328
329            # if verbose == 1:
330            #    pbar.update(n_iter)
331
332            return ensemble_proba
333
334        # end calculate_probas ----
335
336        if self.n_jobs is None:
337            # if self.verbose == 1:
338            #    pbar = Progbar(self.n_estimators)
339
340            if weights is None:
341                return calculate_probas(self.voter_, verbose=self.verbose)
342
343            # if weights is not None:
344            self.weights = weights
345
346            return calculate_probas(self.voter_, weights, verbose=self.verbose)
347
348        # if self.n_jobs is not None:
349        def predict_estimator(m):
350            try:
351                return self.voter_[m].predict_proba(X)
352            except:
353                pass
354
355        if self.verbose == 1:
356            preds = Parallel(n_jobs=self.n_jobs, prefer="threads")(
357                delayed(predict_estimator)(m)
358                for m in tqdm(range(self.n_estimators))
359            )
360
361        else:
362            preds = Parallel(n_jobs=self.n_jobs, prefer="threads")(
363                delayed(predict_estimator)(m) for m in range(self.n_estimators)
364            )
365
366        ensemble_proba = 0
367
368        if weights is None:
369            for i in range(self.n_estimators):
370                ensemble_proba += preds[i]
371
372            return ensemble_proba / self.n_estimators
373
374        for i in range(self.n_estimators):
375            ensemble_proba += weights[i] * preds[i]
376
377        return ensemble_proba

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class Ridge2Regressor(nnetsauce.ridge2.ridge2.Ridge2, sklearn.base.RegressorMixin):
 21class Ridge2Regressor(Ridge2, RegressorMixin):
 22    """Ridge regression with 2 regularization parameters derived from class Ridge
 23
 24    Parameters:
 25
 26        n_hidden_features: int
 27            number of nodes in the hidden layer
 28
 29        activation_name: str
 30            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 31
 32        a: float
 33            hyperparameter for 'prelu' or 'elu' activation function
 34
 35        nodes_sim: str
 36            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 37            'uniform'
 38
 39        bias: boolean
 40            indicates if the hidden layer contains a bias term (True) or not
 41            (False)
 42
 43        dropout: float
 44            regularization parameter; (random) percentage of nodes dropped out
 45            of the training
 46
 47        n_clusters: int
 48            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 49                no clustering)
 50
 51        cluster_encode: bool
 52            defines how the variable containing clusters is treated (default is one-hot)
 53            if `False`, then labels are used, without one-hot encoding
 54
 55        type_clust: str
 56            type of clustering method: currently k-means ('kmeans') or Gaussian
 57            Mixture Model ('gmm')
 58
 59        type_scaling: a tuple of 3 strings
 60            scaling methods for inputs, hidden layer, and clustering respectively
 61            (and when relevant).
 62            Currently available: standardization ('std') or MinMax scaling ('minmax')
 63
 64        lambda1: float
 65            regularization parameter on direct link
 66
 67        lambda2: float
 68            regularization parameter on hidden layer
 69
 70        seed: int
 71            reproducibility seed for nodes_sim=='uniform'
 72
 73        backend: str
 74            'cpu' or 'gpu' or 'tpu'
 75
 76    Attributes:
 77
 78        beta_: {array-like}
 79            regression coefficients
 80
 81        y_mean_: float
 82            average response
 83
 84    """
 85
 86    # construct the object -----
 87
 88    def __init__(
 89        self,
 90        n_hidden_features=5,
 91        activation_name="relu",
 92        a=0.01,
 93        nodes_sim="sobol",
 94        bias=True,
 95        dropout=0,
 96        n_clusters=2,
 97        cluster_encode=True,
 98        type_clust="kmeans",
 99        type_scaling=("std", "std", "std"),
100        lambda1=0.1,
101        lambda2=0.1,
102        seed=123,
103        backend="cpu",
104    ):
105        super().__init__(
106            n_hidden_features=n_hidden_features,
107            activation_name=activation_name,
108            a=a,
109            nodes_sim=nodes_sim,
110            bias=bias,
111            dropout=dropout,
112            n_clusters=n_clusters,
113            cluster_encode=cluster_encode,
114            type_clust=type_clust,
115            type_scaling=type_scaling,
116            lambda1=lambda1,
117            lambda2=lambda2,
118            seed=seed,
119            backend=backend,
120        )
121
122        self.type_fit = "regression"
123
124    def fit(self, X, y, **kwargs):
125        """Fit Ridge model to training data (X, y).
126
127        Args:
128
129            X: {array-like}, shape = [n_samples, n_features]
130                Training vectors, where n_samples is the number
131                of samples and n_features is the number of features.
132
133            y: array-like, shape = [n_samples]
134                Target values.
135
136            **kwargs: additional parameters to be passed to
137                    self.cook_training_set or self.obj.fit
138
139        Returns:
140
141            self: object
142
143        """
144
145        sys_platform = platform.system()
146
147        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
148
149        n_X, p_X = X.shape
150        n_Z, p_Z = scaled_Z.shape
151
152        if self.n_clusters > 0:
153            if self.encode_clusters == True:
154                n_features = p_X + self.n_clusters
155            else:
156                n_features = p_X + 1
157        else:
158            n_features = p_X
159
160        X_ = scaled_Z[:, 0:n_features]
161        Phi_X_ = scaled_Z[:, n_features:p_Z]
162
163        B = mo.crossprod(x=X_, backend=self.backend) + self.lambda1 * np.diag(
164            np.repeat(1, n_features)
165        )
166        C = mo.crossprod(x=Phi_X_, y=X_, backend=self.backend)
167        D = mo.crossprod(
168            x=Phi_X_, backend=self.backend
169        ) + self.lambda2 * np.diag(np.repeat(1, Phi_X_.shape[1]))
170
171        if sys_platform in ("Linux", "Darwin"):
172            B_inv = pinv(B) if self.backend == "cpu" else jpinv(B)
173        else:
174            B_inv = pinv(B)
175
176        W = mo.safe_sparse_dot(a=C, b=B_inv, backend=self.backend)
177        S_mat = D - mo.tcrossprod(x=W, y=C, backend=self.backend)
178
179        if sys_platform in ("Linux", "Darwin"):
180            S_inv = pinv(S_mat) if self.backend == "cpu" else jpinv(S_mat)
181        else:
182            S_inv = pinv(S_mat)
183
184        Y = mo.safe_sparse_dot(a=S_inv, b=W, backend=self.backend)
185        inv = mo.rbind(
186            mo.cbind(
187                x=B_inv + mo.crossprod(x=W, y=Y, backend=self.backend),
188                y=-np.transpose(Y),
189                backend=self.backend,
190            ),
191            mo.cbind(x=-Y, y=S_inv, backend=self.backend),
192            backend=self.backend,
193        )
194
195        self.beta_ = mo.safe_sparse_dot(
196            a=inv,
197            b=mo.crossprod(x=scaled_Z, y=centered_y, backend=self.backend),
198            backend=self.backend,
199        )
200
201        return self
202
203    def predict(self, X, **kwargs):
204        """Predict test data X.
205
206        Args:
207
208            X: {array-like}, shape = [n_samples, n_features]
209                Training vectors, where n_samples is the number
210                of samples and n_features is the number of features.
211
212            **kwargs: additional parameters to be passed to
213                    self.cook_test_set
214
215        Returns:
216
217            model predictions: {array-like}
218
219        """
220
221        if len(X.shape) == 1:
222            n_features = X.shape[0]
223            new_X = mo.rbind(
224                x=X.reshape(1, n_features),
225                y=np.ones(n_features).reshape(1, n_features),
226                backend=self.backend,
227            )
228
229            return (
230                self.y_mean_
231                + mo.safe_sparse_dot(
232                    a=self.cook_test_set(new_X, **kwargs),
233                    b=self.beta_,
234                    backend=self.backend,
235                )
236            )[0]
237
238        return self.y_mean_ + mo.safe_sparse_dot(
239            a=self.cook_test_set(X, **kwargs),
240            b=self.beta_,
241            backend=self.backend,
242        )

Ridge regression with 2 regularization parameters derived from class Ridge

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

lambda1: float
    regularization parameter on direct link

lambda2: float
    regularization parameter on hidden layer

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    'cpu' or 'gpu' or 'tpu'

Attributes:

beta_: {array-like}
    regression coefficients

y_mean_: float
    average response
def fit(self, X, y, **kwargs):
124    def fit(self, X, y, **kwargs):
125        """Fit Ridge model to training data (X, y).
126
127        Args:
128
129            X: {array-like}, shape = [n_samples, n_features]
130                Training vectors, where n_samples is the number
131                of samples and n_features is the number of features.
132
133            y: array-like, shape = [n_samples]
134                Target values.
135
136            **kwargs: additional parameters to be passed to
137                    self.cook_training_set or self.obj.fit
138
139        Returns:
140
141            self: object
142
143        """
144
145        sys_platform = platform.system()
146
147        centered_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
148
149        n_X, p_X = X.shape
150        n_Z, p_Z = scaled_Z.shape
151
152        if self.n_clusters > 0:
153            if self.encode_clusters == True:
154                n_features = p_X + self.n_clusters
155            else:
156                n_features = p_X + 1
157        else:
158            n_features = p_X
159
160        X_ = scaled_Z[:, 0:n_features]
161        Phi_X_ = scaled_Z[:, n_features:p_Z]
162
163        B = mo.crossprod(x=X_, backend=self.backend) + self.lambda1 * np.diag(
164            np.repeat(1, n_features)
165        )
166        C = mo.crossprod(x=Phi_X_, y=X_, backend=self.backend)
167        D = mo.crossprod(
168            x=Phi_X_, backend=self.backend
169        ) + self.lambda2 * np.diag(np.repeat(1, Phi_X_.shape[1]))
170
171        if sys_platform in ("Linux", "Darwin"):
172            B_inv = pinv(B) if self.backend == "cpu" else jpinv(B)
173        else:
174            B_inv = pinv(B)
175
176        W = mo.safe_sparse_dot(a=C, b=B_inv, backend=self.backend)
177        S_mat = D - mo.tcrossprod(x=W, y=C, backend=self.backend)
178
179        if sys_platform in ("Linux", "Darwin"):
180            S_inv = pinv(S_mat) if self.backend == "cpu" else jpinv(S_mat)
181        else:
182            S_inv = pinv(S_mat)
183
184        Y = mo.safe_sparse_dot(a=S_inv, b=W, backend=self.backend)
185        inv = mo.rbind(
186            mo.cbind(
187                x=B_inv + mo.crossprod(x=W, y=Y, backend=self.backend),
188                y=-np.transpose(Y),
189                backend=self.backend,
190            ),
191            mo.cbind(x=-Y, y=S_inv, backend=self.backend),
192            backend=self.backend,
193        )
194
195        self.beta_ = mo.safe_sparse_dot(
196            a=inv,
197            b=mo.crossprod(x=scaled_Z, y=centered_y, backend=self.backend),
198            backend=self.backend,
199        )
200
201        return self

Fit Ridge model to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
203    def predict(self, X, **kwargs):
204        """Predict test data X.
205
206        Args:
207
208            X: {array-like}, shape = [n_samples, n_features]
209                Training vectors, where n_samples is the number
210                of samples and n_features is the number of features.
211
212            **kwargs: additional parameters to be passed to
213                    self.cook_test_set
214
215        Returns:
216
217            model predictions: {array-like}
218
219        """
220
221        if len(X.shape) == 1:
222            n_features = X.shape[0]
223            new_X = mo.rbind(
224                x=X.reshape(1, n_features),
225                y=np.ones(n_features).reshape(1, n_features),
226                backend=self.backend,
227            )
228
229            return (
230                self.y_mean_
231                + mo.safe_sparse_dot(
232                    a=self.cook_test_set(new_X, **kwargs),
233                    b=self.beta_,
234                    backend=self.backend,
235                )
236            )[0]
237
238        return self.y_mean_ + mo.safe_sparse_dot(
239            a=self.cook_test_set(X, **kwargs),
240            b=self.beta_,
241            backend=self.backend,
242        )

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
class Ridge2Classifier(nnetsauce.ridge2.ridge2.Ridge2, sklearn.base.ClassifierMixin):
 18class Ridge2Classifier(Ridge2, ClassifierMixin):
 19    """Multinomial logit classification with 2 regularization parameters
 20
 21    Parameters:
 22
 23        n_hidden_features: int
 24            number of nodes in the hidden layer
 25
 26        activation_name: str
 27            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 28
 29        a: float
 30            hyperparameter for 'prelu' or 'elu' activation function
 31
 32        nodes_sim: str
 33            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 34            'uniform'
 35
 36        bias: boolean
 37            indicates if the hidden layer contains a bias term (True) or not
 38            (False)
 39
 40        dropout: float
 41            regularization parameter; (random) percentage of nodes dropped out
 42            of the training
 43
 44        direct_link: boolean
 45            indicates if the original predictors are included (True) in model's
 46            fitting or not (False)
 47
 48        n_clusters: int
 49            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 50                no clustering)
 51
 52        cluster_encode: bool
 53            defines how the variable containing clusters is treated (default is one-hot)
 54            if `False`, then labels are used, without one-hot encoding
 55
 56        type_clust: str
 57            type of clustering method: currently k-means ('kmeans') or Gaussian
 58            Mixture Model ('gmm')
 59
 60        type_scaling: a tuple of 3 strings
 61            scaling methods for inputs, hidden layer, and clustering respectively
 62            (and when relevant).
 63            Currently available: standardization ('std') or MinMax scaling ('minmax')
 64
 65        lambda1: float
 66            regularization parameter on direct link
 67
 68        lambda2: float
 69            regularization parameter on hidden layer
 70
 71        solver: str
 72            optimization function "L-BFGS-B",  "Newton-CG",
 73            "trust-ncg", "L-BFGS-B-lstsq", "Newton-CG-lstsq",
 74            "trust-ncg-lstsq" (see scipy.optimize.minimize)
 75            When using "L-BFGS-B-lstsq", "Newton-CG-lstsq", or "trust-ncg-lstsq",
 76            the initial value for the optimization is set to the least squares solution
 77
 78        seed: int
 79            reproducibility seed for nodes_sim=='uniform'
 80
 81        backend: str
 82            "cpu" or "gpu" or "tpu"
 83
 84    Attributes:
 85
 86        beta_: {array-like}
 87            regression coefficients
 88
 89        classes_: {array-like}
 90            unique classes in the target variable
 91
 92        minloglik_: float
 93            minimum value of the negative log-likelihood
 94
 95    Examples:
 96
 97    See also [https://github.com/Techtonique/nnetsauce/blob/master/examples/ridge_classification.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/ridge_classification.py)
 98
 99    ```python
100    import nnetsauce as ns
101    import numpy as np
102    from sklearn.datasets import load_breast_cancer
103    from sklearn.model_selection import train_test_split
104    from time import time
105
106
107    breast_cancer = load_breast_cancer()
108    X = breast_cancer.data
109    y = breast_cancer.target
110
111    # split data into training test and test set
112    np.random.seed(123)
113    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
114
115    # create the model with nnetsauce
116    fit_obj = ns.Ridge2Classifier(lambda1 = 6.90185578e+04,
117                                lambda2 = 3.17392781e+02,
118                                n_hidden_features=95,
119                                n_clusters=2,
120                                dropout = 3.62817383e-01,
121                                type_clust = "gmm")
122
123    # fit the model on training set
124    start = time()
125    fit_obj.fit(X_train, y_train)
126    print(f"Elapsed {time() - start}")
127
128    # get the accuracy on test set
129    start = time()
130    print(fit_obj.score(X_test, y_test))
131    print(f"Elapsed {time() - start}")
132
133    # get area under the curve on test set (auc)
134    print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
135    ```
136
137
138    """
139
140    # construct the object -----
141
142    def __init__(
143        self,
144        n_hidden_features=5,
145        activation_name="relu",
146        a=0.01,
147        nodes_sim="sobol",
148        bias=True,
149        dropout=0,
150        direct_link=True,
151        n_clusters=2,
152        cluster_encode=True,
153        type_clust="kmeans",
154        type_scaling=("std", "std", "std"),
155        lambda1=0.1,
156        lambda2=0.1,
157        solver="L-BFGS-B",
158        seed=123,
159        backend="cpu",
160    ):
161        super().__init__(
162            n_hidden_features=n_hidden_features,
163            activation_name=activation_name,
164            a=a,
165            nodes_sim=nodes_sim,
166            bias=bias,
167            dropout=dropout,
168            direct_link=direct_link,
169            n_clusters=n_clusters,
170            cluster_encode=cluster_encode,
171            type_clust=type_clust,
172            type_scaling=type_scaling,
173            lambda1=lambda1,
174            lambda2=lambda2,
175            seed=seed,
176            backend=backend,
177        )
178
179        self.type_fit = "classification"
180        self.solver = solver
181        self.beta_ = None
182        self.classes_ = None
183        self.minloglik_ = None
184
185    def loglik(self, X, Y, **kwargs):
186        """Log-likelihood for training data (X, Y).
187
188        Args:
189
190            X: {array-like}, shape = [n_samples, n_features]
191                Training vectors, where n_samples is the number
192                of samples and n_features is the number of features.
193
194            Y: array-like, shape = [n_samples]
195                One-hot encode target values.
196
197            **kwargs: additional parameters to be passed to
198                    self.cook_training_set or self.obj.fit
199
200        Returns:
201
202        """
203
204        def loglik_grad_hess(Y, X, B, XB, hessian=True, **kwargs):
205            # nobs, n_classes
206            n, K = Y.shape
207
208            # total number of covariates
209            p = X.shape[1]
210
211            # initial number of covariates
212            init_p = p - self.n_hidden_features
213
214            max_double = 709.0
215            XB[XB > max_double] = max_double
216            exp_XB = np.exp(XB)
217            probs = exp_XB / exp_XB.sum(axis=1)[:, None]
218
219            # gradient -----
220            # (Y - p) -> (n, K)
221            # X -> (n, p)
222            # (K, n) %*% (n, p) -> (K, p)
223            if hessian is False:
224                grad = (
225                    -mo.safe_sparse_dot(
226                        a=(Y - probs).T, b=X, backend=self.backend
227                    )
228                    / n
229                )
230                grad += self.lambda1 * B[0:init_p, :].sum(axis=0)[:, None]
231                grad += self.lambda2 * B[init_p:p, :].sum(axis=0)[:, None]
232
233                return grad.flatten()
234
235            # hessian -----
236            if hessian is True:
237                Kp = K * p
238                hess = np.zeros((Kp, Kp), float)
239                for k1 in range(K):
240                    x_index = range(k1 * p, (k1 + 1) * p)
241                    for k2 in range(k1, K):
242                        y_index = range(k2 * p, (k2 + 1) * p)
243                        H_sub = (
244                            -mo.safe_sparse_dot(
245                                a=X.T,
246                                b=(probs[:, k1] * probs[:, k2])[:, None] * X,
247                                backend=self.backend,
248                            )
249                            / n
250                        )  # do not store
251                        hess[np.ix_(x_index, y_index)] = hess[
252                            np.ix_(y_index, x_index)
253                        ] = H_sub
254
255                return hess + (self.lambda1 + self.lambda2) * np.identity(Kp)
256
257        # total number of covariates
258        p = X.shape[1]
259
260        # initial number of covariates
261        init_p = p - self.n_hidden_features
262
263        # log-likelihood (1st return)
264        def loglik_func(x):
265            # (p, K)
266            B = x.reshape(Y.shape[1], p).T
267
268            # (n, K)
269            XB = mo.safe_sparse_dot(X, B, backend=self.backend)
270
271            res = -(np.sum(Y * XB, axis=1) - logsumexp(XB)).mean()
272
273            res += (
274                0.5
275                * self.lambda1
276                * mo.squared_norm(B[0:init_p, :], backend=self.backend)
277            )
278            res += (
279                0.5
280                * self.lambda2
281                * mo.squared_norm(B[init_p:p, :], backend=self.backend)
282            )
283
284            return res
285
286        # gradient of log-likelihood
287        def grad_func(x):
288            # (p, K)
289            B = x.reshape(Y.shape[1], p).T
290
291            return loglik_grad_hess(
292                Y=Y,
293                X=X,
294                B=B,
295                XB=mo.safe_sparse_dot(X, B, backend=self.backend),
296                hessian=False,
297                **kwargs
298            )
299
300        # hessian of log-likelihood
301        def hessian_func(x):
302            # (p, K)
303            B = x.reshape(Y.shape[1], p).T
304
305            return loglik_grad_hess(
306                Y=Y,
307                X=X,
308                B=B,
309                XB=mo.safe_sparse_dot(X, B, backend=self.backend),
310                hessian=True,
311                **kwargs
312            )
313
314        return loglik_func, grad_func, hessian_func
315
316    # newton-cg
317    # L-BFGS-B
318    def fit(self, X, y, **kwargs):
319        """Fit Ridge model to training data (X, y).
320
321        for beta: regression coeffs (beta11, ..., beta1p, ..., betaK1, ..., betaKp)
322        for K classes and p covariates.
323
324        Args:
325
326            X: {array-like}, shape = [n_samples, n_features]
327                Training vectors, where n_samples is the number
328                of samples and n_features is the number of features.
329
330            y: array-like, shape = [n_samples]
331                Target values.
332
333            **kwargs: additional parameters to be passed to
334                    self.cook_training_set or self.obj.fit
335
336        Returns:
337
338            self: object
339
340        """
341
342        assert mx.is_factor(y), "y must contain only integers"
343
344        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
345
346        self.n_classes = len(np.unique(y))
347        self.classes_ = np.unique(y)  # for compatibility with sklearn
348        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
349
350        Y = mo.one_hot_encode2(output_y, self.n_classes)
351
352        # optimize for beta, minimize self.loglik (maximize loglik) -----
353        loglik_func, grad_func, hessian_func = self.loglik(X=scaled_Z, Y=Y)
354
355        if self.solver == "L-BFGS-B":
356            opt = minimize(
357                fun=loglik_func,
358                x0=np.zeros(scaled_Z.shape[1] * self.n_classes),
359                jac=grad_func,
360                method=self.solver,
361            )
362            self.beta_ = opt.x
363            self.minloglik_ = opt.fun
364
365        if self.solver in ("Newton-CG", "trust-ncg"):
366            opt = minimize(
367                fun=loglik_func,
368                x0=np.zeros(scaled_Z.shape[1] * self.n_classes),
369                jac=grad_func,
370                hess=hessian_func,
371                method=self.solver,
372            )
373            self.beta_ = opt.x
374            self.minloglik_ = opt.fun
375
376        if self.solver == "L-BFGS-B-lstsq":
377            opt = minimize(
378                fun=loglik_func,
379                x0=np.linalg.lstsq(scaled_Z, Y, rcond=None)[0].flatten(
380                    order="F"
381                ),
382                jac=grad_func,
383                method="L-BFGS-B",
384            )
385            self.beta_ = opt.x
386            self.minloglik_ = opt.fun
387
388        if self.solver in "Newton-CG-lstsq":
389            opt = minimize(
390                fun=loglik_func,
391                x0=np.linalg.lstsq(scaled_Z, Y, rcond=None)[0].flatten(
392                    order="F"
393                ),
394                jac=grad_func,
395                hess=hessian_func,
396                method="Newton-CG",
397            )
398            self.beta_ = opt.x
399            self.minloglik_ = opt.fun
400
401        if self.solver in "trust-ncg-lstsq":
402            opt = minimize(
403                fun=loglik_func,
404                x0=np.linalg.lstsq(scaled_Z, Y, rcond=None)[0].flatten(
405                    order="F"
406                ),
407                jac=grad_func,
408                hess=hessian_func,
409                method="trust-ncg",
410            )
411            self.beta_ = opt.x
412            self.minloglik_ = opt.fun
413
414        self.classes_ = np.unique(y)
415
416        return self
417
418    def predict(self, X, **kwargs):
419        """Predict test data X.
420
421        Args:
422
423            X: {array-like}, shape = [n_samples, n_features]
424                Training vectors, where n_samples is the number
425                of samples and n_features is the number of features.
426
427            **kwargs: additional parameters to be passed to
428                    self.cook_test_set
429
430        Returns:
431
432            model predictions: {array-like}
433        """
434
435        return np.argmax(self.predict_proba(X, **kwargs), axis=1)
436
437    def predict_proba(self, X, **kwargs):
438        """Predict probabilities for test data X.
439
440        Args:
441
442            X: {array-like}, shape = [n_samples, n_features]
443                Training vectors, where n_samples is the number
444                of samples and n_features is the number of features.
445
446            **kwargs: additional parameters to be passed to
447                    self.cook_test_set
448
449        Returns:
450
451            probability estimates for test data: {array-like}
452
453        """
454        if len(X.shape) == 1:
455            n_features = X.shape[0]
456            new_X = mo.rbind(
457                X.reshape(1, n_features),
458                np.ones(n_features).reshape(1, n_features),
459            )
460
461            Z = self.cook_test_set(new_X, **kwargs)
462
463        else:
464            Z = self.cook_test_set(X, **kwargs)
465
466        ZB = mo.safe_sparse_dot(
467            a=Z,
468            b=self.beta_.reshape(
469                self.n_classes,
470                X.shape[1] + self.n_hidden_features + self.n_clusters,
471            ).T,
472            backend=self.backend,
473        )
474
475        exp_ZB = np.exp(ZB)
476
477        return exp_ZB / exp_ZB.sum(axis=1)[:, None]

Multinomial logit classification with 2 regularization parameters

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

direct_link: boolean
    indicates if the original predictors are included (True) in model's
    fitting or not (False)

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

lambda1: float
    regularization parameter on direct link

lambda2: float
    regularization parameter on hidden layer

solver: str
    optimization function "L-BFGS-B",  "Newton-CG",
    "trust-ncg", "L-BFGS-B-lstsq", "Newton-CG-lstsq",
    "trust-ncg-lstsq" (see scipy.optimize.minimize)
    When using "L-BFGS-B-lstsq", "Newton-CG-lstsq", or "trust-ncg-lstsq",
    the initial value for the optimization is set to the least squares solution

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

beta_: {array-like}
    regression coefficients

classes_: {array-like}
    unique classes in the target variable

minloglik_: float
    minimum value of the negative log-likelihood

Examples:

See also https://github.com/Techtonique/nnetsauce/blob/master/examples/ridge_classification.py

import nnetsauce as ns
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from time import time


breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target

# split data into training test and test set
np.random.seed(123)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# create the model with nnetsauce
fit_obj = ns.Ridge2Classifier(lambda1 = 6.90185578e+04,
                            lambda2 = 3.17392781e+02,
                            n_hidden_features=95,
                            n_clusters=2,
                            dropout = 3.62817383e-01,
                            type_clust = "gmm")

# fit the model on training set
start = time()
fit_obj.fit(X_train, y_train)
print(f"Elapsed {time() - start}")

# get the accuracy on test set
start = time()
print(fit_obj.score(X_test, y_test))
print(f"Elapsed {time() - start}")

# get area under the curve on test set (auc)
print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
def fit(self, X, y, **kwargs):
318    def fit(self, X, y, **kwargs):
319        """Fit Ridge model to training data (X, y).
320
321        for beta: regression coeffs (beta11, ..., beta1p, ..., betaK1, ..., betaKp)
322        for K classes and p covariates.
323
324        Args:
325
326            X: {array-like}, shape = [n_samples, n_features]
327                Training vectors, where n_samples is the number
328                of samples and n_features is the number of features.
329
330            y: array-like, shape = [n_samples]
331                Target values.
332
333            **kwargs: additional parameters to be passed to
334                    self.cook_training_set or self.obj.fit
335
336        Returns:
337
338            self: object
339
340        """
341
342        assert mx.is_factor(y), "y must contain only integers"
343
344        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
345
346        self.n_classes = len(np.unique(y))
347        self.classes_ = np.unique(y)  # for compatibility with sklearn
348        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
349
350        Y = mo.one_hot_encode2(output_y, self.n_classes)
351
352        # optimize for beta, minimize self.loglik (maximize loglik) -----
353        loglik_func, grad_func, hessian_func = self.loglik(X=scaled_Z, Y=Y)
354
355        if self.solver == "L-BFGS-B":
356            opt = minimize(
357                fun=loglik_func,
358                x0=np.zeros(scaled_Z.shape[1] * self.n_classes),
359                jac=grad_func,
360                method=self.solver,
361            )
362            self.beta_ = opt.x
363            self.minloglik_ = opt.fun
364
365        if self.solver in ("Newton-CG", "trust-ncg"):
366            opt = minimize(
367                fun=loglik_func,
368                x0=np.zeros(scaled_Z.shape[1] * self.n_classes),
369                jac=grad_func,
370                hess=hessian_func,
371                method=self.solver,
372            )
373            self.beta_ = opt.x
374            self.minloglik_ = opt.fun
375
376        if self.solver == "L-BFGS-B-lstsq":
377            opt = minimize(
378                fun=loglik_func,
379                x0=np.linalg.lstsq(scaled_Z, Y, rcond=None)[0].flatten(
380                    order="F"
381                ),
382                jac=grad_func,
383                method="L-BFGS-B",
384            )
385            self.beta_ = opt.x
386            self.minloglik_ = opt.fun
387
388        if self.solver in "Newton-CG-lstsq":
389            opt = minimize(
390                fun=loglik_func,
391                x0=np.linalg.lstsq(scaled_Z, Y, rcond=None)[0].flatten(
392                    order="F"
393                ),
394                jac=grad_func,
395                hess=hessian_func,
396                method="Newton-CG",
397            )
398            self.beta_ = opt.x
399            self.minloglik_ = opt.fun
400
401        if self.solver in "trust-ncg-lstsq":
402            opt = minimize(
403                fun=loglik_func,
404                x0=np.linalg.lstsq(scaled_Z, Y, rcond=None)[0].flatten(
405                    order="F"
406                ),
407                jac=grad_func,
408                hess=hessian_func,
409                method="trust-ncg",
410            )
411            self.beta_ = opt.x
412            self.minloglik_ = opt.fun
413
414        self.classes_ = np.unique(y)
415
416        return self

Fit Ridge model to training data (X, y).

for beta: regression coeffs (beta11, ..., beta1p, ..., betaK1, ..., betaKp) for K classes and p covariates.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
418    def predict(self, X, **kwargs):
419        """Predict test data X.
420
421        Args:
422
423            X: {array-like}, shape = [n_samples, n_features]
424                Training vectors, where n_samples is the number
425                of samples and n_features is the number of features.
426
427            **kwargs: additional parameters to be passed to
428                    self.cook_test_set
429
430        Returns:
431
432            model predictions: {array-like}
433        """
434
435        return np.argmax(self.predict_proba(X, **kwargs), axis=1)

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
437    def predict_proba(self, X, **kwargs):
438        """Predict probabilities for test data X.
439
440        Args:
441
442            X: {array-like}, shape = [n_samples, n_features]
443                Training vectors, where n_samples is the number
444                of samples and n_features is the number of features.
445
446            **kwargs: additional parameters to be passed to
447                    self.cook_test_set
448
449        Returns:
450
451            probability estimates for test data: {array-like}
452
453        """
454        if len(X.shape) == 1:
455            n_features = X.shape[0]
456            new_X = mo.rbind(
457                X.reshape(1, n_features),
458                np.ones(n_features).reshape(1, n_features),
459            )
460
461            Z = self.cook_test_set(new_X, **kwargs)
462
463        else:
464            Z = self.cook_test_set(X, **kwargs)
465
466        ZB = mo.safe_sparse_dot(
467            a=Z,
468            b=self.beta_.reshape(
469                self.n_classes,
470                X.shape[1] + self.n_hidden_features + self.n_clusters,
471            ).T,
472            backend=self.backend,
473        )
474
475        exp_ZB = np.exp(ZB)
476
477        return exp_ZB / exp_ZB.sum(axis=1)[:, None]

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class Ridge2MultitaskClassifier(nnetsauce.ridge2.ridge2.Ridge2, sklearn.base.ClassifierMixin):
 21class Ridge2MultitaskClassifier(Ridge2, ClassifierMixin):
 22    """Multitask Ridge classification with 2 regularization parameters
 23
 24    Parameters:
 25
 26        n_hidden_features: int
 27            number of nodes in the hidden layer
 28
 29        activation_name: str
 30            activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'
 31
 32        a: float
 33            hyperparameter for 'prelu' or 'elu' activation function
 34
 35        nodes_sim: str
 36            type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
 37            'uniform'
 38
 39        bias: boolean
 40            indicates if the hidden layer contains a bias term (True) or not
 41            (False)
 42
 43        dropout: float
 44            regularization parameter; (random) percentage of nodes dropped out
 45            of the training
 46
 47        n_clusters: int
 48            number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
 49                no clustering)
 50
 51        cluster_encode: bool
 52            defines how the variable containing clusters is treated (default is one-hot)
 53            if `False`, then labels are used, without one-hot encoding
 54
 55        type_clust: str
 56            type of clustering method: currently k-means ('kmeans') or Gaussian
 57            Mixture Model ('gmm')
 58
 59        type_scaling: a tuple of 3 strings
 60            scaling methods for inputs, hidden layer, and clustering respectively
 61            (and when relevant).
 62            Currently available: standardization ('std') or MinMax scaling ('minmax')
 63
 64        lambda1: float
 65            regularization parameter on direct link
 66
 67        lambda2: float
 68            regularization parameter on hidden layer
 69
 70        seed: int
 71            reproducibility seed for nodes_sim=='uniform'
 72
 73        backend: str
 74            "cpu" or "gpu" or "tpu"
 75
 76    Attributes:
 77
 78        beta_: {array-like}
 79            regression coefficients
 80
 81    Examples:
 82
 83    See also [https://github.com/Techtonique/nnetsauce/blob/master/examples/ridgemtask_classification.py](https://github.com/Techtonique/nnetsauce/blob/master/examples/ridgemtask_classification.py)
 84
 85    ```python
 86    import nnetsauce as ns
 87    import numpy as np
 88    from sklearn.datasets import load_breast_cancer
 89    from sklearn.model_selection import train_test_split
 90    from sklearn import metrics
 91    from time import time
 92
 93    breast_cancer = load_breast_cancer()
 94    Z = breast_cancer.data
 95    t = breast_cancer.target
 96    np.random.seed(123)
 97    X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2)
 98
 99    fit_obj = ns.Ridge2MultitaskClassifier(n_hidden_features=int(9.83730469e+01),
100                                    dropout=4.31054687e-01,
101                                    n_clusters=int(1.71484375e+00),
102                                    lambda1=1.24023438e+01, lambda2=7.30263672e+03)
103
104    start = time()
105    fit_obj.fit(X_train, y_train)
106    print(f"Elapsed {time() - start}")
107
108    print(fit_obj.score(X_test, y_test))
109    print(fit_obj.score(X_test, y_test, scoring="roc_auc"))
110
111    start = time()
112    preds = fit_obj.predict(X_test)
113    print(f"Elapsed {time() - start}")
114    print(metrics.classification_report(preds, y_test))
115    ```
116
117    """
118
119    # construct the object -----
120
121    def __init__(
122        self,
123        n_hidden_features=5,
124        activation_name="relu",
125        a=0.01,
126        nodes_sim="sobol",
127        bias=True,
128        dropout=0,
129        n_clusters=2,
130        cluster_encode=True,
131        type_clust="kmeans",
132        type_scaling=("std", "std", "std"),
133        lambda1=0.1,
134        lambda2=0.1,
135        seed=123,
136        backend="cpu",
137    ):
138        super().__init__(
139            n_hidden_features=n_hidden_features,
140            activation_name=activation_name,
141            a=a,
142            nodes_sim=nodes_sim,
143            bias=bias,
144            dropout=dropout,
145            n_clusters=n_clusters,
146            cluster_encode=cluster_encode,
147            type_clust=type_clust,
148            type_scaling=type_scaling,
149            lambda1=lambda1,
150            lambda2=lambda2,
151            seed=seed,
152            backend=backend,
153        )
154
155        self.type_fit = "classification"
156
157    def fit(self, X, y, **kwargs):
158        """Fit Ridge model to training data (X, y).
159
160        Args:
161
162            X: {array-like}, shape = [n_samples, n_features]
163                Training vectors, where n_samples is the number
164                of samples and n_features is the number of features.
165
166            y: array-like, shape = [n_samples]
167                Target values.
168
169            **kwargs: additional parameters to be passed to
170                    self.cook_training_set or self.obj.fit
171
172        Returns:
173
174            self: object
175
176        """
177
178        sys_platform = platform.system()
179
180        assert mx.is_factor(y), "y must contain only integers"
181
182        self.classes_ = np.unique(y)  # for compatibility with sklearn
183        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
184
185        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
186
187        n_X, p_X = X.shape
188        n_Z, p_Z = scaled_Z.shape
189
190        self.n_classes = len(np.unique(y))
191
192        # multitask response
193        Y = mo.one_hot_encode2(output_y, self.n_classes)
194
195        if self.n_clusters > 0:
196            if self.encode_clusters == True:
197                n_features = p_X + self.n_clusters
198            else:
199                n_features = p_X + 1
200        else:
201            n_features = p_X
202
203        X_ = scaled_Z[:, 0:n_features]
204        Phi_X_ = scaled_Z[:, n_features:p_Z]
205
206        B = mo.crossprod(x=X_, backend=self.backend) + self.lambda1 * np.diag(
207            np.repeat(1, X_.shape[1])
208        )
209        C = mo.crossprod(x=Phi_X_, y=X_, backend=self.backend)
210        D = mo.crossprod(
211            x=Phi_X_, backend=self.backend
212        ) + self.lambda2 * np.diag(np.repeat(1, Phi_X_.shape[1]))
213
214        if sys_platform in ("Linux", "Darwin"):
215            B_inv = pinv(B) if self.backend == "cpu" else jpinv(B)
216        else:
217            B_inv = pinv(B)
218
219        W = mo.safe_sparse_dot(a=C, b=B_inv, backend=self.backend)
220        S_mat = D - mo.tcrossprod(x=W, y=C, backend=self.backend)
221
222        if sys_platform in ("Linux", "Darwin"):
223            S_inv = pinv(S_mat) if self.backend == "cpu" else jpinv(S_mat)
224        else:
225            S_inv = pinv(S_mat)
226
227        Y2 = mo.safe_sparse_dot(a=S_inv, b=W, backend=self.backend)
228        inv = mo.rbind(
229            mo.cbind(
230                x=B_inv + mo.crossprod(x=W, y=Y2, backend=self.backend),
231                y=-np.transpose(Y2),
232                backend=self.backend,
233            ),
234            mo.cbind(x=-Y2, y=S_inv, backend=self.backend),
235            backend=self.backend,
236        )
237
238        self.beta_ = mo.safe_sparse_dot(
239            a=inv,
240            b=mo.crossprod(x=scaled_Z, y=Y, backend=self.backend),
241            backend=self.backend,
242        )
243        self.classes_ = np.unique(y)
244        return self
245
246    def predict(self, X, **kwargs):
247        """Predict test data X.
248
249        Args:
250
251            X: {array-like}, shape = [n_samples, n_features]
252                Training vectors, where n_samples is the number
253                of samples and n_features is the number of features.
254
255            **kwargs: additional parameters to be passed to
256                    self.cook_test_set
257
258        Returns:
259
260            model predictions: {array-like}
261
262        """
263
264        return np.argmax(self.predict_proba(X, **kwargs), axis=1)
265
266    def predict_proba(self, X, **kwargs):
267        """Predict probabilities for test data X.
268
269        Args:
270
271            X: {array-like}, shape = [n_samples, n_features]
272                Training vectors, where n_samples is the number
273                of samples and n_features is the number of features.
274
275            **kwargs: additional parameters to be passed to
276                    self.cook_test_set
277
278        Returns:
279
280            probability estimates for test data: {array-like}
281
282        """
283
284        if len(X.shape) == 1:
285            n_features = X.shape[0]
286            new_X = mo.rbind(
287                x=X.reshape(1, n_features),
288                y=np.ones(n_features).reshape(1, n_features),
289                backend=self.backend,
290            )
291
292            Z = self.cook_test_set(new_X, **kwargs)
293
294        else:
295            Z = self.cook_test_set(X, **kwargs)
296
297        ZB = mo.safe_sparse_dot(a=Z, b=self.beta_, backend=self.backend)
298
299        exp_ZB = np.exp(ZB)
300
301        return exp_ZB / exp_ZB.sum(axis=1)[:, None]

Multitask Ridge classification with 2 regularization parameters

Parameters:

n_hidden_features: int
    number of nodes in the hidden layer

activation_name: str
    activation function: 'relu', 'tanh', 'sigmoid', 'prelu' or 'elu'

a: float
    hyperparameter for 'prelu' or 'elu' activation function

nodes_sim: str
    type of simulation for the nodes: 'sobol', 'hammersley', 'halton',
    'uniform'

bias: boolean
    indicates if the hidden layer contains a bias term (True) or not
    (False)

dropout: float
    regularization parameter; (random) percentage of nodes dropped out
    of the training

n_clusters: int
    number of clusters for 'kmeans' or 'gmm' clustering (could be 0:
        no clustering)

cluster_encode: bool
    defines how the variable containing clusters is treated (default is one-hot)
    if `False`, then labels are used, without one-hot encoding

type_clust: str
    type of clustering method: currently k-means ('kmeans') or Gaussian
    Mixture Model ('gmm')

type_scaling: a tuple of 3 strings
    scaling methods for inputs, hidden layer, and clustering respectively
    (and when relevant).
    Currently available: standardization ('std') or MinMax scaling ('minmax')

lambda1: float
    regularization parameter on direct link

lambda2: float
    regularization parameter on hidden layer

seed: int
    reproducibility seed for nodes_sim=='uniform'

backend: str
    "cpu" or "gpu" or "tpu"

Attributes:

beta_: {array-like}
    regression coefficients

Examples:

See also https://github.com/Techtonique/nnetsauce/blob/master/examples/ridgemtask_classification.py

import nnetsauce as ns
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn import metrics
from time import time

breast_cancer = load_breast_cancer()
Z = breast_cancer.data
t = breast_cancer.target
np.random.seed(123)
X_train, X_test, y_train, y_test = train_test_split(Z, t, test_size=0.2)

fit_obj = ns.Ridge2MultitaskClassifier(n_hidden_features=int(9.83730469e+01),
                                dropout=4.31054687e-01,
                                n_clusters=int(1.71484375e+00),
                                lambda1=1.24023438e+01, lambda2=7.30263672e+03)

start = time()
fit_obj.fit(X_train, y_train)
print(f"Elapsed {time() - start}")

print(fit_obj.score(X_test, y_test))
print(fit_obj.score(X_test, y_test, scoring="roc_auc"))

start = time()
preds = fit_obj.predict(X_test)
print(f"Elapsed {time() - start}")
print(metrics.classification_report(preds, y_test))
def fit(self, X, y, **kwargs):
157    def fit(self, X, y, **kwargs):
158        """Fit Ridge model to training data (X, y).
159
160        Args:
161
162            X: {array-like}, shape = [n_samples, n_features]
163                Training vectors, where n_samples is the number
164                of samples and n_features is the number of features.
165
166            y: array-like, shape = [n_samples]
167                Target values.
168
169            **kwargs: additional parameters to be passed to
170                    self.cook_training_set or self.obj.fit
171
172        Returns:
173
174            self: object
175
176        """
177
178        sys_platform = platform.system()
179
180        assert mx.is_factor(y), "y must contain only integers"
181
182        self.classes_ = np.unique(y)  # for compatibility with sklearn
183        self.n_classes_ = len(self.classes_)  # for compatibility with sklearn
184
185        output_y, scaled_Z = self.cook_training_set(y=y, X=X, **kwargs)
186
187        n_X, p_X = X.shape
188        n_Z, p_Z = scaled_Z.shape
189
190        self.n_classes = len(np.unique(y))
191
192        # multitask response
193        Y = mo.one_hot_encode2(output_y, self.n_classes)
194
195        if self.n_clusters > 0:
196            if self.encode_clusters == True:
197                n_features = p_X + self.n_clusters
198            else:
199                n_features = p_X + 1
200        else:
201            n_features = p_X
202
203        X_ = scaled_Z[:, 0:n_features]
204        Phi_X_ = scaled_Z[:, n_features:p_Z]
205
206        B = mo.crossprod(x=X_, backend=self.backend) + self.lambda1 * np.diag(
207            np.repeat(1, X_.shape[1])
208        )
209        C = mo.crossprod(x=Phi_X_, y=X_, backend=self.backend)
210        D = mo.crossprod(
211            x=Phi_X_, backend=self.backend
212        ) + self.lambda2 * np.diag(np.repeat(1, Phi_X_.shape[1]))
213
214        if sys_platform in ("Linux", "Darwin"):
215            B_inv = pinv(B) if self.backend == "cpu" else jpinv(B)
216        else:
217            B_inv = pinv(B)
218
219        W = mo.safe_sparse_dot(a=C, b=B_inv, backend=self.backend)
220        S_mat = D - mo.tcrossprod(x=W, y=C, backend=self.backend)
221
222        if sys_platform in ("Linux", "Darwin"):
223            S_inv = pinv(S_mat) if self.backend == "cpu" else jpinv(S_mat)
224        else:
225            S_inv = pinv(S_mat)
226
227        Y2 = mo.safe_sparse_dot(a=S_inv, b=W, backend=self.backend)
228        inv = mo.rbind(
229            mo.cbind(
230                x=B_inv + mo.crossprod(x=W, y=Y2, backend=self.backend),
231                y=-np.transpose(Y2),
232                backend=self.backend,
233            ),
234            mo.cbind(x=-Y2, y=S_inv, backend=self.backend),
235            backend=self.backend,
236        )
237
238        self.beta_ = mo.safe_sparse_dot(
239            a=inv,
240            b=mo.crossprod(x=scaled_Z, y=Y, backend=self.backend),
241            backend=self.backend,
242        )
243        self.classes_ = np.unique(y)
244        return self

Fit Ridge model to training data (X, y).

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

y: array-like, shape = [n_samples]
    Target values.

**kwargs: additional parameters to be passed to
        self.cook_training_set or self.obj.fit

Returns:

self: object
def predict(self, X, **kwargs):
246    def predict(self, X, **kwargs):
247        """Predict test data X.
248
249        Args:
250
251            X: {array-like}, shape = [n_samples, n_features]
252                Training vectors, where n_samples is the number
253                of samples and n_features is the number of features.
254
255            **kwargs: additional parameters to be passed to
256                    self.cook_test_set
257
258        Returns:
259
260            model predictions: {array-like}
261
262        """
263
264        return np.argmax(self.predict_proba(X, **kwargs), axis=1)

Predict test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

model predictions: {array-like}
def predict_proba(self, X, **kwargs):
266    def predict_proba(self, X, **kwargs):
267        """Predict probabilities for test data X.
268
269        Args:
270
271            X: {array-like}, shape = [n_samples, n_features]
272                Training vectors, where n_samples is the number
273                of samples and n_features is the number of features.
274
275            **kwargs: additional parameters to be passed to
276                    self.cook_test_set
277
278        Returns:
279
280            probability estimates for test data: {array-like}
281
282        """
283
284        if len(X.shape) == 1:
285            n_features = X.shape[0]
286            new_X = mo.rbind(
287                x=X.reshape(1, n_features),
288                y=np.ones(n_features).reshape(1, n_features),
289                backend=self.backend,
290            )
291
292            Z = self.cook_test_set(new_X, **kwargs)
293
294        else:
295            Z = self.cook_test_set(X, **kwargs)
296
297        ZB = mo.safe_sparse_dot(a=Z, b=self.beta_, backend=self.backend)
298
299        exp_ZB = np.exp(ZB)
300
301        return exp_ZB / exp_ZB.sum(axis=1)[:, None]

Predict probabilities for test data X.

Args:

X: {array-like}, shape = [n_samples, n_features]
    Training vectors, where n_samples is the number
    of samples and n_features is the number of features.

**kwargs: additional parameters to be passed to
        self.cook_test_set

Returns:

probability estimates for test data: {array-like}
class SubSampler:
 6class SubSampler:
 7    """Subsampling class.
 8
 9    Attributes:
10
11       y: array-like, shape = [n_samples]
12           Target values.
13
14       row_sample: double
15           subsampling fraction
16
17       n_samples: int
18            subsampling by using the number of rows (supersedes row_sample)
19
20       seed: int
21           reproductibility seed
22
23       n_jobs: int
24            number of jobs to run in parallel
25
26       verbose: bool
27            print progress messages and bars
28    """
29
30    def __init__(
31        self,
32        y,
33        row_sample=0.8,
34        n_samples=None,
35        seed=123,
36        n_jobs=None,
37        verbose=False,
38    ):
39        self.y = y
40        self.n_samples = n_samples
41        if self.n_samples is None:
42            assert (
43                row_sample < 1 and row_sample >= 0
44            ), "'row_sample' must be provided, plus < 1 and >= 0"
45            self.row_sample = row_sample
46        else:
47            assert self.n_samples < len(y), "'n_samples' must be < len(y)"
48            self.row_sample = self.n_samples / len(y)
49        self.seed = seed
50        self.indices = None
51        self.n_jobs = n_jobs
52        self.verbose = verbose
53
54    def subsample(self):
55        """Returns indices of subsampled input data.
56
57        Examples:
58
59        <ul>
60            <li> <a href="https://github.com/Techtonique/nnetsauce/blob/master/nnetsauce/demo/thierrymoudiki_20240105_subsampling.ipynb">20240105_subsampling.ipynb</a> </li>
61            <li> <a href="https://github.com/Techtonique/nnetsauce/blob/master/nnetsauce/demo/thierrymoudiki_20240131_subsampling_nsamples.ipynb">20240131_subsampling_nsamples.ipynb</a> </li>
62        </ul>
63
64        """
65        self.indices = dosubsample(
66            y=self.y,
67            row_sample=self.row_sample,
68            seed=self.seed,
69            n_jobs=self.n_jobs,
70            verbose=self.verbose,
71        )
72        return self.indices

Subsampling class.

Attributes:

y: array-like, shape = [n_samples] Target values.

row_sample: double subsampling fraction

n_samples: int subsampling by using the number of rows (supersedes row_sample)

seed: int reproductibility seed

n_jobs: int number of jobs to run in parallel

verbose: bool print progress messages and bars

def subsample(self):
54    def subsample(self):
55        """Returns indices of subsampled input data.
56
57        Examples:
58
59        <ul>
60            <li> <a href="https://github.com/Techtonique/nnetsauce/blob/master/nnetsauce/demo/thierrymoudiki_20240105_subsampling.ipynb">20240105_subsampling.ipynb</a> </li>
61            <li> <a href="https://github.com/Techtonique/nnetsauce/blob/master/nnetsauce/demo/thierrymoudiki_20240131_subsampling_nsamples.ipynb">20240131_subsampling_nsamples.ipynb</a> </li>
62        </ul>
63
64        """
65        self.indices = dosubsample(
66            y=self.y,
67            row_sample=self.row_sample,
68            seed=self.seed,
69            n_jobs=self.n_jobs,
70            verbose=self.verbose,
71        )
72        return self.indices

Returns indices of subsampled input data.

Examples: