Source code for metaperceptron.core.metaheuristic_mlp

#!/usr/bin/env python
# Created by "Thieu" at 17:43, 13/09/2023 ----------%
#       Email: nguyenthieu2102@gmail.com            %
#       Github: https://github.com/thieu1995        %
# --------------------------------------------------%

import numpy as np
import torch
from sklearn.metrics import accuracy_score, r2_score
from sklearn.base import ClassifierMixin, RegressorMixin
from permetrics import ClassificationMetric, RegressionMetric
from metaperceptron.core.base_mlp import BaseMhaMlp


[docs]class MhaMlpClassifier(BaseMhaMlp, ClassifierMixin): """ A Metaheuristic-based MLP Classifier that extends the BaseMhaMlp class and implements the ClassifierMixin interface from Scikit-Learn for classification tasks. Attributes ---------- classes_ : np.ndarray Unique classes found in the target variable. metric_class : type The metric class used for evaluating classification performance. Parameters ---------- hidden_layers : list of int, tuple of int, or np.ndarray of int The structure of the hidden layers (default is (100,)). act_names : str Activation function name to use in hidden layers (default is "ReLU"). dropout_rates : float, optional Dropout rate for regularization (default is 0.2). act_output : any, optional Activation function for the output layer (default is None). optim : str The optimization algorithm to use (default is "BaseGA"). optim_params : dict Parameters for the optimizer (default is None). obj_name : str, optional The objective name for the optimization (default is "F1S"). seed : int, optional Random seed for reproducibility (default is 42). verbose : bool, optional Whether to print detailed logs during fitting (default is True). lb : int, float, tuple, list, np.ndarray, optional Lower bounds for weights and biases in network. ub : int, float, tuple, list, np.ndarray, optional Upper bounds for weights and biases in network. mode : str, optional Mode for optimization (default is 'single'). n_workers : int, optional Number of workers for parallel processing (default is None). termination : any, optional Termination criteria for optimization (default is None). """ def __init__(self, hidden_layers=(100,), act_names="ReLU", dropout_rates=0.2, act_output=None, optim="BaseGA", optim_params=None, obj_name="F1S", seed=42, verbose=True, lb=None, ub=None, mode='single', n_workers=None, termination=None): """ Initializes the MhaMlpClassifier with specified parameters. """ super().__init__(hidden_layers, act_names, dropout_rates, act_output, optim, optim_params, obj_name, seed, verbose, lb, ub, mode, n_workers, termination) self.classes_ = None # Initialize classes to None self.metric_class = ClassificationMetric # Set the metric class for evaluation
[docs] def fit(self, X, y): """ Fits the model to the training data. Parameters ---------- X : array-like, shape (n_samples, n_features) Training data. y : array-like, shape (n_samples,) Target values. Returns ------- self : MhaMlpClassifier Returns the instance of the fitted model. """ ## Check the parameters self.size_input = X.shape[1] # Number of features y = np.squeeze(np.array(y)) # Convert y to a numpy array and squeeze dimensions if y.ndim != 1: y = np.argmax(y, axis=1) # Convert to 1D if it’s not already self.classes_ = np.unique(y) # Get unique classes from y if len(self.classes_) == 2: self.task = "binary_classification" # Set task for binary classification self.size_output = 1 # Output size for binary classification else: self.task = "classification" # Set task for multi-class classification self.size_output = len(self.classes_) # Output size for multi-class ## Process data X_tensor = torch.tensor(X, dtype=torch.float32) # Convert input data to tensor ## Build model self.build_model() # Build the model architecture ## Fit the data self._fit(X_tensor, y) # Fit the model return self # Return the fitted model
[docs] def predict(self, X): """ Predicts the class labels for the provided input data. Parameters ---------- X : array-like, shape (n_samples, n_features) Input data for prediction. Returns ------- np.ndarray Predicted class labels for each sample. """ X_tensor = torch.tensor(X, dtype=torch.float32) # Convert input data to tensor self.network.eval() # Set model to evaluation mode with torch.no_grad(): output = self.network(X_tensor) # Get model predictions if self.task =="classification": # Multi-class classification _, predicted = torch.max(output, 1) else: # Binary classification predicted = (output > 0.5).int().squeeze() return predicted.numpy() # Return as a numpy array
[docs] def score(self, X, y): """ Computes the accuracy score of the model based on predictions. Parameters ---------- X : array-like, shape (n_samples, n_features) Input data for scoring. y : array-like, shape (n_samples,) True labels for comparison. Returns ------- float Accuracy score of the model. """ y_pred = self.predict(X) # Get predictions return accuracy_score(y, y_pred) # Calculate and return accuracy score
[docs] def predict_proba(self, X): """ Computes the probability estimates for each class (for classification tasks only). Parameters ---------- X : array-like, shape (n_samples, n_features) Input data for which to predict probabilities. Returns ------- np.ndarray Probability predictions for each class. Raises ------ ValueError If the task is not a classification task. """ X_tensor = torch.tensor(X, dtype=torch.float32) # Convert input data to tensor if self.task not in ["classification", "binary_classification"]: raise ValueError( "predict_proba is only available for classification tasks.") # Raise error if task is invalid self.network.eval() # Ensure model is in evaluation mode with torch.no_grad(): probs = self.network.forward(X_tensor) # Get the output from forward pass return probs.numpy() # Return probabilities as a numpy array
[docs] def evaluate(self, y_true, y_pred, list_metrics=("AS", "RS")): """ Return the list of performance metrics on the given test data and labels. Parameters ---------- y_true : array-like of shape (n_samples,) or (n_samples, n_outputs) True values for `X`. y_pred : array-like of shape (n_samples,) or (n_samples, n_outputs) Predicted values for `X`. list_metrics : list, default=("AS", "RS") List of metrics to compute using Permetrics library: https://github.com/thieu1995/permetrics Returns ------- results : dict A dictionary containing the results of the requested metrics. """ return self._evaluate_cls(y_true, y_pred, list_metrics) # Call evaluation method
[docs]class MhaMlpRegressor(BaseMhaMlp, RegressorMixin): """ A Metaheuristic-based MLP Regressor that extends the BaseMhaMlp class and implements the RegressorMixin interface from Scikit-Learn for regression tasks. Attributes ---------- metric_class : type The metric class used for evaluating regression performance. Parameters ---------- hidden_layers : list of int, tuple of int, or np.ndarray of int The structure of the hidden layers (default is (100,)). act_names : str Activation function name to use in hidden layers (default is "ELU"). dropout_rates : float, optional Dropout rate for regularization (default is 0.2). act_output : any, optional Activation function for the output layer (default is None). optim : str The optimization algorithm to use (default is "BaseGA"). optim_params : dict Parameters for the optimizer (default is None). obj_name : str, optional The objective name for the optimization (default is "MSE"). seed : int, optional Random seed for reproducibility (default is 42). verbose : bool, optional Whether to print detailed logs during fitting (default is True). lb : int, float, tuple, list, np.ndarray, optional Lower bounds for weights and biases in network. ub : int, float, tuple, list, np.ndarray, optional Upper bounds for weights and biases in network. mode : str, optional Mode for optimization (default is 'single'). n_workers : int, optional Number of workers for parallel processing (default is None). termination : any, optional Termination criteria for optimization (default is None). """ def __init__(self, hidden_layers=(100,), act_names="ELU", dropout_rates=0.2, act_output=None, optim="BaseGA", optim_params=None, obj_name="MSE", seed=42, verbose=True, lb=None, ub=None, mode='single', n_workers=None, termination=None): """ Initializes the MhaMlpRegressor with specified parameters. """ super().__init__(hidden_layers, act_names, dropout_rates, act_output, optim, optim_params, obj_name, seed, verbose, lb, ub, mode, n_workers, termination) self.metric_class = RegressionMetric # Set the metric class for evaluation
[docs] def fit(self, X, y): """ Fits the model to the training data. Parameters ---------- X : array-like, shape (n_samples, n_features) Training data. y : array-like, shape (n_samples,) or (n_samples, n_outputs) Target values. Returns ------- self : MhaMlpRegressor Returns the instance of the fitted model. """ ## Check the parameters self.size_input = X.shape[1] # Number of input features y = np.squeeze(np.array(y)) # Convert y to a numpy array and squeeze dimensions self.size_output = 1 # Default output size for single-output regression self.task = "regression" # Default task is regression if y.ndim == 2: self.task = "multi_regression" # Set task for multi-output regression self.size_output = y.shape[1] # Update output size for multi-output ## Process data X_tensor = torch.tensor(X, dtype=torch.float32) # Convert input data to tensor ## Build model self.build_model() # Build the model architecture ## Fit the data self._fit(X_tensor, y) return self # Return the fitted model
[docs] def predict(self, X): """ Predicts the output values for the provided input data. Parameters ---------- X : array-like, shape (n_samples, n_features) Input data for prediction. Returns ------- np.ndarray Predicted output values for each sample. """ X_tensor = torch.tensor(X, dtype=torch.float32) # Convert input data to tensor self.network.eval() # Set model to evaluation mode with torch.no_grad(): predicted = self.network(X_tensor) # Get model predictions return predicted.numpy() # Return predictions as a numpy array
[docs] def score(self, X, y): """ Computes the R2 score of the model based on predictions. Parameters ---------- X : array-like, shape (n_samples, n_features) Input data for scoring. y : array-like, shape (n_samples,) True labels for comparison. Returns ------- float R2 score of the model. """ y_pred = self.predict(X) # Get predictions return r2_score(y, y_pred) # Calculate and return R^2 score
[docs] def evaluate(self, y_true, y_pred, list_metrics=("AS", "RS")): """ Return the list of performance metrics on the given test data and labels. Parameters ---------- y_true : array-like of shape (n_samples,) or (n_samples, n_outputs) True values for `X`. y_pred : array-like of shape (n_samples,) or (n_samples, n_outputs) Predicted values for `X`. list_metrics : list, default=("AS", "RS") List of metrics to compute using Permetrics library: https://github.com/thieu1995/permetrics Returns ------- results : dict A dictionary containing the results of the requested metrics. """ return self._evaluate_reg(y_true, y_pred, list_metrics) # Call evaluation method