| |
| import numpy as np |
| import pandas as pd |
| import time |
| import warnings |
| import xgboost |
| import lightgbm |
| from tqdm import tqdm |
| from sklearn.pipeline import Pipeline |
| from sklearn.impute import SimpleImputer |
| from sklearn.preprocessing import StandardScaler, OneHotEncoder, OrdinalEncoder |
| from sklearn.compose import ColumnTransformer |
| from sklearn.utils import all_estimators |
| from sklearn.base import RegressorMixin |
| from sklearn.base import ClassifierMixin |
| from sklearn.metrics import ( |
| accuracy_score, |
| balanced_accuracy_score, |
| roc_auc_score, |
| f1_score, |
| r2_score, |
| mean_squared_error, |
| ) |
|
|
| try: |
| from utils import print_message |
| from seed_utils import get_global_seed |
| except ImportError: |
| from ..utils import print_message |
| from ..seed_utils import get_global_seed |
|
|
| warnings.filterwarnings("ignore") |
| pd.set_option("display.precision", 2) |
| pd.set_option("display.float_format", lambda x: "%.2f" % x) |
|
|
|
|
| removed_classifiers = [ |
| "ClassifierChain", |
| "ComplementNB", |
| "GradientBoostingClassifier", |
| "GaussianProcessClassifier", |
| "HistGradientBoostingClassifier", |
| "MLPClassifier", |
| "LogisticRegressionCV", |
| "MultiOutputClassifier", |
| "MultinomialNB", |
| "OneVsOneClassifier", |
| "OneVsRestClassifier", |
| "OutputCodeClassifier", |
| "RadiusNeighborsClassifier", |
| "VotingClassifier", |
| "LogisticRegressionCV", |
| "CalibratedClassifierCV", |
| "RidgeClassifierCV", |
| "LinearSVC", |
| "Perceptron", |
| "MLPClassifier", |
| "SGDClassifier", |
| |
| "LabelPropagation", |
| "LabelSpreading", |
| "SVC", |
| "NuSVC", |
| |
| "AdaBoostClassifier", |
| "BaggingClassifier", |
| |
| "KNeighborsClassifier", |
| |
| "DecisionTreeClassifier", |
| "ExtraTreeClassifier", |
| "ExtraTreesClassifier", |
| |
| "CategoricalNB", |
| |
| "LinearDiscriminantAnalysis", |
| "QuadraticDiscriminantAnalysis", |
| |
| "FixedThresholdClassifier", |
| "TunedThresholdClassifierCV", |
| ] |
|
|
| removed_regressors = [ |
| "TheilSenRegressor", |
| "ARDRegression", |
| "CCA", |
| "IsotonicRegression", |
| "StackingRegressor", |
| "MultiOutputRegressor", |
| "MultiTaskElasticNet", |
| "MultiTaskElasticNetCV", |
| "MultiTaskLasso", |
| "MultiTaskLassoCV", |
| "PLSCanonical", |
| "PLSRegression", |
| "RadiusNeighborsRegressor", |
| "RegressorChain", |
| "VotingRegressor", |
| "OrthogonalMatchingPursuitCV", |
| "LassoLars", |
| "LarsCV", |
| "LassoCV", |
| "RidgeCV", |
| "LassoLarsCV", |
| "ElasticNetCV", |
| "LinearSVR", |
| "LassoLarsIC", |
| |
| "AdaBoostRegressor", |
| "BaggingRegressor", |
| |
| "KNeighborsRegressor", |
| |
| "DecisionTreeRegressor", |
| "ExtraTreeRegressor", |
| "ExtraTreesRegressor", |
| ] |
|
|
| |
| CLASSIFIERS = [ |
| est |
| for est in all_estimators() |
| if (issubclass(est[1], ClassifierMixin) and (est[0] not in removed_classifiers)) |
| ] |
| CLASSIFIER_DICT = {model[0]: model[1] for model in CLASSIFIERS} |
|
|
| """ |
| CLASSIFIERS = [ |
| 'LogisticRegression', |
| 'SVC', |
| 'PassiveAggressiveClassifier', |
| 'LabelPropagation', |
| 'LabelSpreading', |
| 'RandomForestClassifier', |
| 'GradientBoostingClassifier', |
| 'QuadraticDiscriminantAnalysis', |
| 'HistGradientBoostingClassifier', |
| 'RidgeClassifier', |
| 'AdaBoostClassifier', |
| 'ExtraTreesClassifier', |
| 'KNeighborsClassifier', |
| 'BaggingClassifier', |
| 'BernoulliNB', |
| 'LinearDiscriminantAnalysis', |
| 'GaussianNB', |
| 'NuSVC', |
| 'DecisionTreeClassifier', |
| 'NearestCentroid', |
| 'ExtraTreeClassifier', |
| 'CheckingClassifier', |
| 'DummyClassifier' |
| ] |
| """ |
|
|
| REGRESSORS = [ |
| est |
| for est in all_estimators() |
| if (issubclass(est[1], RegressorMixin) and (est[0] not in removed_regressors)) |
| ] |
| REGRESSOR_DICT = {model[0]: model[1] for model in REGRESSORS} |
|
|
| ALL_MODELS = CLASSIFIERS + REGRESSORS |
| ALL_MODEL_DICT = {model[0]: model[1] for model in ALL_MODELS} |
|
|
| """ |
| REGRESSORS = [ |
| 'ExtraTreesRegressor', |
| 'Lasso', |
| 'PassiveAggressiveRegressor', |
| 'SGDRegressor', |
| 'Ridge', |
| 'BayesianRidge', |
| 'TransformedTargetRegressor', |
| 'LinearRegression', |
| 'Lars', |
| 'HuberRegressor', |
| 'RandomForestRegressor', |
| 'AdaBoostRegressor', |
| 'LGBMRegressor', |
| 'HistGradientBoostingRegressor', |
| 'PoissonRegressor', |
| 'ElasticNet', |
| 'KNeighborsRegressor', |
| 'OrthogonalMatchingPursuit', |
| 'BaggingRegressor', |
| 'GradientBoostingRegressor', |
| 'TweedieRegressor', |
| 'XGBRegressor', |
| 'GammaRegressor', |
| 'RANSACRegressor', |
| 'ExtraTreeRegressor', |
| 'NuSVR', |
| 'SVR', |
| 'DummyRegressor', |
| 'DecisionTreeRegressor', |
| 'GaussianProcessRegressor', |
| 'MLPRegressor', |
| 'KernelRidge' |
| ] |
| """ |
|
|
| REGRESSORS.append(("XGBRegressor", xgboost.XGBRegressor)) |
| REGRESSORS.append(("LGBMRegressor", lightgbm.LGBMRegressor)) |
| |
|
|
| CLASSIFIERS.append(("XGBClassifier", xgboost.XGBClassifier)) |
| CLASSIFIERS.append(("LGBMClassifier", lightgbm.LGBMClassifier)) |
| |
|
|
| |
| CLASSIFIER_DICT["XGBClassifier"] = xgboost.XGBClassifier |
| CLASSIFIER_DICT["LGBMClassifier"] = lightgbm.LGBMClassifier |
| REGRESSOR_DICT["XGBRegressor"] = xgboost.XGBRegressor |
| REGRESSOR_DICT["LGBMRegressor"] = lightgbm.LGBMRegressor |
| ALL_MODEL_DICT["XGBClassifier"] = xgboost.XGBClassifier |
| ALL_MODEL_DICT["LGBMClassifier"] = lightgbm.LGBMClassifier |
| ALL_MODEL_DICT["XGBRegressor"] = xgboost.XGBRegressor |
| ALL_MODEL_DICT["LGBMRegressor"] = lightgbm.LGBMRegressor |
|
|
| numeric_transformer = Pipeline( |
| steps=[("imputer", SimpleImputer(strategy="mean")), ("scaler", StandardScaler())] |
| ) |
|
|
| categorical_transformer_low = Pipeline( |
| steps=[ |
| ("imputer", SimpleImputer(strategy="constant", fill_value="missing")), |
| ("encoding", OneHotEncoder(handle_unknown="ignore", sparse_output=False)), |
| ] |
| ) |
|
|
| categorical_transformer_high = Pipeline( |
| steps=[ |
| ("imputer", SimpleImputer(strategy="constant", fill_value="missing")), |
| |
| ("encoding", OrdinalEncoder()), |
| ] |
| ) |
|
|
|
|
| |
| def get_card_split(df, cols, n=11): |
| """ |
| Splits categorical columns into 2 lists based on cardinality (i.e # of unique values) |
| Parameters |
| ---------- |
| df : Pandas DataFrame |
| DataFrame from which the cardinality of the columns is calculated. |
| cols : list-like |
| Categorical columns to list |
| n : int, optional (default=11) |
| The value of 'n' will be used to split columns. |
| Returns |
| ------- |
| card_low : list-like |
| Columns with cardinality < n |
| card_high : list-like |
| Columns with cardinality >= n |
| """ |
| cond = df[cols].nunique() > n |
| card_high = cols[cond] |
| card_low = cols[~cond] |
| return card_low, card_high |
|
|
|
|
| |
| class LazyClassifier: |
| """ |
| This module helps in fitting to all the classification algorithms that are available in Scikit-learn |
| Parameters |
| ---------- |
| verbose : int, optional (default=0) |
| For the liblinear and lbfgs solvers set verbose to 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. |
| prediction : bool, optional (default=False) |
| When set to True, the predictions of all the models models are returned as dataframe. |
| classifiers : list, optional (default="all") |
| When function is provided, trains the chosen classifier(s). |
| """ |
|
|
| def __init__( |
| self, |
| verbose=0, |
| ignore_warnings=True, |
| custom_metric=None, |
| predictions=False, |
| random_state=None, |
| classifiers="all", |
| ): |
| self.verbose = verbose |
| self.ignore_warnings = ignore_warnings |
| self.custom_metric = custom_metric |
| self.predictions = predictions |
| self.models = {} |
| self.random_state = random_state or get_global_seed() |
| self.classifiers = classifiers |
|
|
| def fit(self, X_train, X_test, y_train, y_test): |
| """Fit Classification 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. |
| """ |
| Accuracy = [] |
| B_Accuracy = [] |
| ROC_AUC = [] |
| F1 = [] |
| names = [] |
| TIME = [] |
| predictions = {} |
|
|
| if self.custom_metric is not None: |
| CUSTOM_METRIC = [] |
|
|
| if isinstance(X_train, np.ndarray): |
| X_train = pd.DataFrame(X_train) |
| X_test = pd.DataFrame(X_test) |
|
|
| numeric_features = X_train.select_dtypes(include=[np.number]).columns |
| categorical_features = X_train.select_dtypes(include=["object"]).columns |
|
|
| categorical_low, categorical_high = get_card_split( |
| X_train, categorical_features |
| ) |
|
|
| preprocessor = ColumnTransformer( |
| transformers=[ |
| ("numeric", numeric_transformer, numeric_features), |
| ("categorical_low", categorical_transformer_low, categorical_low), |
| ("categorical_high", categorical_transformer_high, categorical_high), |
| ] |
| ) |
| |
| |
| print_message("Preprocessing data once for all models...") |
| preprocess_start = time.time() |
| X_train_transformed = preprocessor.fit_transform(X_train) |
| X_test_transformed = preprocessor.transform(X_test) |
| print_message(f"Preprocessing completed in {time.time() - preprocess_start:.1f}s") |
|
|
| if self.classifiers == "all": |
| self.classifiers = CLASSIFIERS |
| else: |
| try: |
| temp_list = [] |
| for classifier in self.classifiers: |
| full_name = (classifier.__name__, classifier) |
| temp_list.append(full_name) |
| self.classifiers = temp_list |
| except Exception as exception: |
| print_message(exception) |
| print_message("Invalid Classifier(s)") |
|
|
| |
| failed_models = [] |
| total_start = time.time() |
|
|
| for name, model in tqdm(self.classifiers, desc="Training classifiers"): |
| print_message(f"Starting {name}...") |
| start = time.time() |
| try: |
| |
| model_kwargs = {} |
| if "random_state" in model().get_params().keys(): |
| model_kwargs["random_state"] = self.random_state |
| |
| if "n_jobs" in model().get_params().keys(): |
| model_kwargs["n_jobs"] = -1 |
| |
| if name in ("XGBClassifier", "LGBMClassifier"): |
| model_kwargs["verbose"] = 1 |
| |
| |
| clf = model(**model_kwargs) |
| clf.fit(X_train_transformed, y_train) |
| self.models[name] = clf |
| y_pred = clf.predict(X_test_transformed) |
| accuracy = accuracy_score(y_test, y_pred, normalize=True) |
| b_accuracy = balanced_accuracy_score(y_test, y_pred) |
| f1 = f1_score(y_test, y_pred, average="weighted") |
| try: |
| roc_auc = roc_auc_score(y_test, y_pred) |
| except Exception as exception: |
| roc_auc = None |
| if self.ignore_warnings is False: |
| print_message("ROC AUC couldn't be calculated for " + name) |
| print_message(exception) |
| fit_time = time.time() - start |
| names.append(name) |
| Accuracy.append(accuracy) |
| B_Accuracy.append(b_accuracy) |
| ROC_AUC.append(roc_auc) |
| F1.append(f1) |
| TIME.append(fit_time) |
| |
| print_message(f" {name} completed in {fit_time:.1f}s | Acc: {accuracy:.3f} | F1: {f1:.3f}") |
|
|
| if self.custom_metric is not None: |
| custom_metric = self.custom_metric(y_test, y_pred) |
| CUSTOM_METRIC.append(custom_metric) |
|
|
| if self.predictions: |
| predictions[name] = y_pred |
|
|
| except Exception as exception: |
| failed_models.append(name) |
| if self.ignore_warnings is False: |
| print_message(f'\n{name} model failed to execute') |
| print_message(exception) |
|
|
| if self.custom_metric is None: |
| scores = pd.DataFrame( |
| { |
| "Model": names, |
| "Accuracy": Accuracy, |
| "Balanced Accuracy": B_Accuracy, |
| "ROC AUC": ROC_AUC, |
| "F1 Score": F1, |
| "Time Taken": TIME, |
| } |
| ) |
| else: |
| scores = pd.DataFrame( |
| { |
| "Model": names, |
| "Accuracy": Accuracy, |
| "Balanced Accuracy": B_Accuracy, |
| "ROC AUC": ROC_AUC, |
| "F1 Score": F1, |
| "Custom Metric": CUSTOM_METRIC, |
| "Time Taken": TIME, |
| } |
| ) |
| scores = scores.sort_values(by="Balanced Accuracy", ascending=False).set_index( |
| "Model" |
| ) |
|
|
| |
| total_time = time.time() - total_start |
| n_success = len(names) |
| n_failed = len(failed_models) |
| best_model = scores.index[0] if len(scores) > 0 else "N/A" |
| best_score = scores["Balanced Accuracy"].iloc[0] if len(scores) > 0 else 0 |
|
|
| if self.verbose > 0: |
| |
| summary = f"\nLazyClassifier Results ({n_success} succeeded, {n_failed} failed, {total_time:.1f}s)\n" |
| summary += scores.to_string() |
| if failed_models: |
| summary += f"\n\nFailed: {', '.join(failed_models)}" |
| print_message(summary) |
| else: |
| |
| print_message(f"Completed {n_success + n_failed} classifiers in {total_time:.1f}s | {n_success} succeeded, {n_failed} failed | Best: {best_model} ({best_score:.2f})") |
|
|
| if self.predictions: |
| predictions_df = pd.DataFrame.from_dict(predictions) |
| return scores, predictions_df |
| return scores |
|
|
| def provide_models(self, X_train, X_test, y_train, y_test): |
| """ |
| 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. |
| """ |
| if len(self.models.keys()) == 0: |
| self.fit(X_train, X_test, y_train, y_test) |
|
|
| return self.models |
|
|
|
|
| def adjusted_rsquared(r2, n, p): |
| return 1 - (1 - r2) * ((n - 1) / (n - p - 1)) |
|
|
|
|
| |
| class LazyRegressor: |
| """ |
| This module helps in fitting regression models that are available in Scikit-learn |
| Parameters |
| ---------- |
| verbose : int, optional (default=0) |
| For the liblinear and lbfgs solvers set verbose to 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. |
| prediction : bool, optional (default=False) |
| When set to True, the predictions of all the models models are returned as dataframe. |
| regressors : list, optional (default="all") |
| When function is provided, trains the chosen regressor(s). |
| """ |
|
|
| def __init__( |
| self, |
| verbose=0, |
| ignore_warnings=True, |
| custom_metric=None, |
| predictions=False, |
| random_state=None, |
| regressors="all", |
| ): |
| self.verbose = verbose |
| self.ignore_warnings = ignore_warnings |
| self.custom_metric = custom_metric |
| self.predictions = predictions |
| self.models = {} |
| self.random_state = random_state or get_global_seed() |
| self.regressors = regressors |
|
|
| def fit(self, X_train, X_test, y_train, y_test): |
| """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. |
| """ |
| R2 = [] |
| ADJR2 = [] |
| RMSE = [] |
| |
| names = [] |
| TIME = [] |
| predictions = {} |
|
|
| if self.custom_metric: |
| CUSTOM_METRIC = [] |
|
|
| if isinstance(X_train, np.ndarray): |
| X_train = pd.DataFrame(X_train) |
| X_test = pd.DataFrame(X_test) |
|
|
| numeric_features = X_train.select_dtypes(include=[np.number]).columns |
| categorical_features = X_train.select_dtypes(include=["object"]).columns |
|
|
| categorical_low, categorical_high = get_card_split( |
| X_train, categorical_features |
| ) |
|
|
| preprocessor = ColumnTransformer( |
| transformers=[ |
| ("numeric", numeric_transformer, numeric_features), |
| ("categorical_low", categorical_transformer_low, categorical_low), |
| ("categorical_high", categorical_transformer_high, categorical_high), |
| ] |
| ) |
| |
| |
| print_message("Preprocessing data once for all models...") |
| preprocess_start = time.time() |
| X_train_transformed = preprocessor.fit_transform(X_train) |
| X_test_transformed = preprocessor.transform(X_test) |
| print_message(f"Preprocessing completed in {time.time() - preprocess_start:.1f}s") |
|
|
| if self.regressors == "all": |
| self.regressors = REGRESSORS |
| else: |
| try: |
| temp_list = [] |
| for regressor in self.regressors: |
| full_name = (regressor.__name__, regressor) |
| temp_list.append(full_name) |
| self.regressors = temp_list |
| except Exception as exception: |
| print_message(exception) |
| print_message("Invalid Regressor(s)") |
|
|
| |
| failed_models = [] |
| total_start = time.time() |
|
|
| for name, model in tqdm(self.regressors, desc="Training regressors"): |
| print_message(f"Starting {name}...") |
| start = time.time() |
| try: |
| |
| model_kwargs = {} |
| if "random_state" in model().get_params().keys(): |
| model_kwargs["random_state"] = self.random_state |
| |
| if "n_jobs" in model().get_params().keys(): |
| model_kwargs["n_jobs"] = -1 |
| |
| if name in ("XGBRegressor", "LGBMRegressor"): |
| model_kwargs["verbose"] = 1 |
| |
| |
| reg = model(**model_kwargs) |
| reg.fit(X_train_transformed, y_train) |
| self.models[name] = reg |
| y_pred = reg.predict(X_test_transformed) |
|
|
| r_squared = r2_score(y_test, y_pred) |
| adj_rsquared = adjusted_rsquared( |
| r_squared, X_test.shape[0], X_test.shape[1] |
| ) |
| rmse = np.sqrt(mean_squared_error(y_test, y_pred)) |
|
|
| fit_time = time.time() - start |
| names.append(name) |
| R2.append(r_squared) |
| ADJR2.append(adj_rsquared) |
| RMSE.append(rmse) |
| TIME.append(fit_time) |
| |
| print_message(f" {name} completed in {fit_time:.1f}s | R²: {r_squared:.3f} | RMSE: {rmse:.3f}") |
|
|
| if self.custom_metric: |
| custom_metric = self.custom_metric(y_test, y_pred) |
| CUSTOM_METRIC.append(custom_metric) |
|
|
| if self.predictions: |
| predictions[name] = y_pred |
|
|
| except Exception as exception: |
| failed_models.append(name) |
| if self.ignore_warnings is False: |
| print_message(f'\n{name} model failed to execute') |
| print_message(exception) |
|
|
| scores = { |
| "Model": names, |
| "Adjusted R-Squared": ADJR2, |
| "R-Squared": R2, |
| "RMSE": RMSE, |
| "Time Taken": TIME, |
| } |
|
|
| if self.custom_metric: |
| scores[self.custom_metric.__name__] = CUSTOM_METRIC |
|
|
| scores = pd.DataFrame(scores) |
| scores = scores.sort_values(by="Adjusted R-Squared", ascending=False).set_index( |
| "Model" |
| ) |
|
|
| |
| total_time = time.time() - total_start |
| n_success = len(names) |
| n_failed = len(failed_models) |
| best_model = scores.index[0] if len(scores) > 0 else "N/A" |
| best_score = scores["Adjusted R-Squared"].iloc[0] if len(scores) > 0 else 0 |
|
|
| if self.verbose > 0: |
| |
| summary = f"\nLazyRegressor Results ({n_success} succeeded, {n_failed} failed, {total_time:.1f}s)\n" |
| summary += scores.to_string() |
| if failed_models: |
| summary += f"\n\nFailed: {', '.join(failed_models)}" |
| print_message(summary) |
| else: |
| |
| print_message(f"Completed {n_success + n_failed} regressors in {total_time:.1f}s | {n_success} succeeded, {n_failed} failed | Best: {best_model} ({best_score:.2f})") |
|
|
| if self.predictions: |
| predictions_df = pd.DataFrame.from_dict(predictions) |
| return scores, predictions_df |
| return scores |
|
|
| def provide_models(self, X_train, X_test, y_train, y_test): |
| """ |
| 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. |
| """ |
| if len(self.models.keys()) == 0: |
| self.fit(X_train, X_test, y_train, y_test) |
|
|
| return self.models |
|
|