"""Automated Supervised Learning with BuildML library."""
import warnings
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import ydata_profiling as pp
import sweetviz as sv
import imblearn.over_sampling as ios
import imblearn.under_sampling as ius
import sklearn.impute as si
import sklearn.linear_model as slm
import sklearn.preprocessing as sp
import sklearn.model_selection as sms
import sklearn.metrics as sm
import sklearn.neighbors as sn
import sklearn.feature_selection as sfs
import datatable as dt
__author__ = "TechLeo"
__email__ = "techleo.ng@outlook.com"
__copyright__ = "Copyright (c) 2023 TechLeo"
__license__ = "MIT"
[docs]
class SupervisedLearning:
"""
Automated Supervised Learning module designed for end-to-end data handling,
preprocessing, model development, and evaluation in the context of supervised
machine learning.
Parameters
----------
dataset : pd.DataFrame
The input dataset for supervised learning.
show_warnings : bool, optional
If True, display warnings. Default is False.
Examples
--------
>>> import numpy as np
>>> import pandas as pd
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.ensemble import RandomForestClassifier, DecisionTreeClassifier
>>> from sklearn.snm import SVC
>>> from buildml import SupervisedLearning
>>>
>>>
>>> dataset = pd.read_csv("Your_file_path") # Load your dataset(e.g Pandas DataFrame)
>>> data = SupervisedLearning(dataset)
>>>
>>> # Exploratory Data Analysis
>>> eda = data.eda()
>>>
>>> # Build and Evaluate Classifier
>>> classifiers = ["LogisticRegression(random_state = 0)",
>>> "RandomForestClassifier(random_state = 0)",
>>> "DecisionTreeClassifier(random_state = 0)",
>>> "SVC()"]
>>> build_model = data.build_multiple_classifiers(classifiers)
Notes
-----
This class encapsulates various functionalities for data handling and model development.
It leverages popular libraries such as pandas, numpy, matplotlib, seaborn, ydata_profiling,
sweetviz, imbalanced-learn, scikit-learn, warnings, feature-engine, and datatable.
The workflow involves steps like loading and handling data, cleaning and manipulation,
formatting and transformation, exploratory data analysis,
feature engineering, data preprocessing,
model building and evaluation, data aggregation and summarization, and data type handling.
References
----------
- pandas: https://pandas.pydata.org/
- numpy: https://numpy.org/
- matplotlib: https://matplotlib.org/
- seaborn: https://seaborn.pydata.org/
- ydata_profiling: https://github.com/dexplo/ydata_profiling
- sweetviz: https://github.com/fbdesignpro/sweetviz
- imbalanced-learn: https://github.com/scikit-learn-contrib/imbalanced-learn
- scikit-learn: https://scikit-learn.org/
- warnings: https://docs.python.org/3/library/warnings.html
- feature-engine: https://github.com/solegalli/feature_engine
- datatable: https://datatable.readthedocs.io/en/latest/
"""
def __init__(self, dataset, show_warnings: bool = False):
if isinstance(show_warnings, bool):
if show_warnings == False:
self.warnings = show_warnings
warnings.filterwarnings("ignore")
else:
self.warnings = warnings
else:
raise TypeError("Warnings must be boolean of True or False.")
self.__dataset = dataset
self.__data = dataset
self.__x = None
self.__y = None
self.__x_train = None
self.__y_train = None
self.__x_test = None
self.__y_test = None
self.__x_train1 = None
self.__x_test1 = None
self.__y_train1 = None
self.__y_test1 = None
self.regressor = None
self.model_regressor = None
self.model_classifier = None
self.classifier = None
self.__y_pred = None
self.__y_pred1 = None
self.__multiple_regressor_models = None
self.__multiple_classifier_models = None
self.__y_train_encoded = None
self.__y_encoded = None
self.__poly_features = None
self.__poly_x = None
self.__x1 = None
self.__strategy = None
self.__columns = None
self.__scaler = None
self.__scaled = False
self.__fixed_missing = False
self.__eda = False
self.__model_training = False
self.__dropped_column = False
self.__get_dataset = False
self.__data_transformation = False
self.__model_prediction = False
self.__model_evaluation = False
self.__model_testing = False
self.__remove_outlier = False
self.__polynomial_regression = False
self.__eda_visual = False
self.__split_data = False
self.__dependent_independent = False
self.classification_problem = False
self.regression_problem = False
[docs]
def drop_columns(self, columns: list or str):
"""
Drop specified columns from the dataset.
Parameters
----------
columns : str or list of str
A single column name (string) or a list of column names to be dropped.
Returns
-------
pd.DataFrame
A new DataFrame with the specified columns dropped.
Notes
-----
This method utilizes the `pandas` library for DataFrame manipulation.
See Also
--------
- pandas.DataFrame.drop : Drop specified labels from rows or columns.
Examples
--------
>>> # Drop a single column
>>> df = SupervisedLearning(dataset)
>>> df.drop_columns('column_name')
>>> # Drop multiple columns
>>> df = SupervisedLearning(dataset)
>>> df.drop_columns(['column1', 'column2'])
"""
self.__data = self.__data.drop(columns, axis = 1)
return self.__data
[docs]
def get_training_test_data(self):
"""
Get the training and test data splits.
Returns
-------
Tuple
A tuple containing X_train, X_test, y_train, and y_test.
Notes
-----
This method uses the `sklearn.model_selection` library for splitting the data into training and test sets.
See Also
--------
- sklearn.model_selection.train_test_split : Split arrays or matrices into random train and test subsets.
Examples
--------
>>> # Get training and test data splits
>>> df = SupervisedLearning(dataset)
>>> X_train, X_test, y_train, y_test = df.get_training_test_data()
"""
return (self.__x_train, self.__x_test, self.__y_train, self.__y_test)
[docs]
def get_dataset(self):
"""
Retrieve the original dataset and the processed data.
Returns
-------
Tuple
A tuple containing the original dataset and the processed data.
Notes
-----
This method provides access to both the original and processed datasets.
See Also
--------
pandas.DataFrame : Data structure for handling tabular data.
Examples
--------
>>> # Get the original and processed datasets
>>> df = SupervisedLearning(dataset)
>>> original_data, processed_data = df.get_dataset()
"""
return (self.__data, self.__dataset)
[docs]
def fix_missing_values(self, strategy: str = None):
"""
Fix missing values in the dataset.
Parameters
----------
strategy : str, optional
The strategy to use for imputation. If not specified, it defaults to "mean".
Options: "mean", "median", "mode".
Returns
-------
pd.DataFrame
The dataset with missing values imputed.
Notes
-----
This method uses the `sklearn.impute` library for handling missing values.
See Also
--------
sklearn.impute.SimpleImputer : Imputation transformer for completing missing values.
Examples
--------
>>> # Fix missing values using the default strategy ("mean")
>>> df = SupervisedLearning(dataset)
>>> df.fix_missing_values()
>>> # Fix missing values using a specific strategy (e.g., "median")
>>> df.fix_missing_values(strategy="median")
"""
self.__strategy = strategy
if self.__strategy == None:
imputer = si.SimpleImputer(strategy = "mean")
self.__data = pd.DataFrame(imputer.fit_transform(self.__data), columns = imputer.feature_names_in_)
self.__fixed_missing = True
elif self.__strategy.lower().strip() == "mean":
imputer = si.SimpleImputer(strategy = "mean")
self.__data = pd.DataFrame(imputer.fit_transform(self.__data), columns = imputer.feature_names_in_)
self.__fixed_missing = True
elif self.__strategy.lower().strip() == "median":
imputer = si.SimpleImputer(strategy = "median")
self.__data = pd.DataFrame(imputer.fit_transform(self.__data), columns = imputer.feature_names_in_)
self.__fixed_missing = True
elif self.__strategy.lower().strip() == "mode":
imputer = si.SimpleImputer(strategy = "most_frequent")
self.__data = pd.DataFrame(imputer.fit_transform(self.__data), columns = imputer.feature_names_in_)
self.__fixed_missing = True
return self.__data
[docs]
def categorical_to_numerical(self, columns: list = None):
"""
Convert categorical columns to numerical using one-hot encoding.
Parameters
----------
columns : list, optional
A list of column names to apply one-hot encoding. If not provided, one-hot encoding is applied to all categorical columns.
Returns
-------
pd.DataFrame
Transformed DataFrame with categorical columns converted to numerical using one-hot encoding.
Notes
-----
This method uses the `pandas` library for one-hot encoding.
See Also
--------
pandas.get_dummies : Convert categorical variable(s) into dummy/indicator variables.
Examples
--------
>>> # Convert all categorical columns to numerical using one-hot encoding
>>> df = SupervisedLearning(dataset)
>>> df.categorical_to_numerical()
>>> # Convert specific columns to numerical using one-hot encoding
>>> df.categorical_to_numerical(columns=['Category1', 'Category2'])
"""
self.__columns = columns
if self.__columns == None:
self.__data = pd.get_dummies(self.__data, drop_first = True, dtype = int)
self.__data_transformation = True
else:
self.__data = pd.get_dummies(self.__data, columns = self.__columns, drop_first = True, dtype = int)
self.__data_transformation = True
return self.__data
[docs]
def remove_outlier(self, drop_na: bool):
"""
Remove outliers from the dataset.
This method uses the `sklearn.preprocessing` library for standard scaling and outlier removal.
Parameters
----------
drop_na : bool
If False, outliers are replaced with NaN values. If True, rows with NaN values are dropped.
Returns
-------
pd.DataFrame
The dataset with outliers removed.
Notes
-----
The method applies standard scaling using `sklearn.preprocessing.StandardScaler` and removes outliers
based on the range of -3 to 3 standard deviations.
See Also
--------
sklearn.preprocessing.StandardScaler : Standardize features by removing the mean and scaling to unit variance.
Examples
--------
>>> # Remove outliers, replace with NaN
>>> df = SupervisedLearning(dataset)
>>> df.remove_outlier(drop_na=False)
>>> # Remove outliers and drop rows with NaN values
>>> df.remove_outlier(drop_na=True)
"""
if drop_na == False:
scaler = sp.StandardScaler()
self.__data = scaler.fit_transform(self.__data)
self.__data = pd.DataFrame(self.__data, columns = scaler.feature_names_in_)
self.__data = self.__data[(self.__data >= -3) & (self.__data <= 3)]
self.__data = pd.DataFrame(scaler.inverse_transform(self.__data), columns = scaler.feature_names_in_)
self.__remove_outlier = True
elif drop_na == True:
scaler = sp.StandardScaler()
self.__data = scaler.fit_transform(self.__data)
self.__data = pd.DataFrame(self.__data, columns = scaler.feature_names_in_)
self.__data = self.__data[(self.__data >= -3) & (self.__data <= 3)].dropna()
self.__data = pd.DataFrame(scaler.inverse_transform(self.__data), columns = scaler.feature_names_in_)
self.__remove_outlier = True
return self.__data
[docs]
def scale_independent_variables(self):
"""
Standardize independent variables using sklearn.preprocessing.StandardScaler.
Returns
-------
pd.DataFrame
A DataFrame with scaled independent variables.
Notes
-----
This method uses the `sklearn.preprocessing` library for standardization.
Examples
--------
>>> # Create an instance of SupervisedLearning
>>> df = SupervisedLearning(dataset)
>>> # Scale independent variables
>>> scaled_data = df.scale_independent_variables()
See Also
--------
sklearn.preprocessing.StandardScaler : Standardize features by removing the mean and scaling to unit variance.
"""
self.__scaler = sp.StandardScaler()
self.__x = self.__scaler.fit_transform(self.__x)
self.__x = pd.DataFrame(self.__x, columns = self.__scaler.feature_names_in_)
self.__scaled = True
return self.__x
[docs]
def eda(self):
"""
Perform Exploratory Data Analysis (EDA) on the dataset.
Returns
-------
Dict
A dictionary containing various EDA results, including data head, data tail, descriptive statistics, mode, distinct count, null count, total null count, and correlation matrix.
Notes
-----
This method utilizes functionalities from pandas for data analysis.
Examples
--------
>>> # Perform Exploratory Data Analysis
>>> df = SupervisedLearning(dataset)
>>> eda_results = df.eda()
See Also
--------
- pandas.DataFrame.info : Get a concise summary of a DataFrame.
- pandas.DataFrame.head : Return the first n rows.
- pandas.DataFrame.tail : Return the last n rows.
- pandas.DataFrame.describe : Generate descriptive statistics.
- pandas.DataFrame.mode : Get the mode(s) of each element.
- pandas.DataFrame.nunique : Count distinct observations.
- pandas.DataFrame.isnull : Detect missing values.
- pandas.DataFrame.corr : Compute pairwise correlation of columns.
"""
self.__data.info()
print("\n\n")
data_head = self.__data.head()
data_tail = self.__data.tail()
data_descriptive_statistic = self.__data.describe()
data_more_descriptive_statistics = self.__data.describe(include = "all")
data_mode = self.__data.mode()
data_unique = SupervisedLearning.unique_elements_in_columns(self)
data_distinct_count = self.__data.nunique()
data_null_count = self.__data.isnull().sum()
data_total_null_count = self.__data.isnull().sum().sum()
data_correlation_matrix = self.__data.corr()
self.__eda = True
return {"Data": self.__data, "Data_Head": data_head, "Data_Tail": data_tail, "Data_Descriptive_Statistic": data_descriptive_statistic, "Data_More_Descriptive_Statistic": data_more_descriptive_statistics, "Data_Mode": data_mode, "Data_Distinct_Count": data_distinct_count, "Unique_Elements_in_Data": data_unique, "Data_Null_Count": data_null_count, "Data_Total_Null_Count": data_total_null_count, "Data_Correlation_Matrix": data_correlation_matrix}
[docs]
def eda_visual(self, histogram_bins: int = 10, figsize_heatmap: tuple = (15, 10), figsize_histogram: tuple = (15, 10), figsize_barchart: tuple = (15, 10), before_data_cleaning: bool = True):
"""
Generate visualizations for exploratory data analysis (EDA).
Parameters
----------
histogram_bins: int
The number of bins for each instogram.
figsize_heatmap: tuple
The length and breadth for the frame of the heatmap.
figsize_histogram: tuple
The length and breadth for the frame of the histogram.
figsize_barchart: tuple
The length and breadth for the frame of the barchart.
before_data_cleaning : bool, default True
If True, visualizes data before cleaning. If False, visualizes cleaned data.
Returns
-------
None
The method generates and displays various visualizations based on the data distribution and correlation.
Notes
-----
This method utilizes the following libraries for visualization:
- `matplotlib.pyplot` for creating histograms and heatmaps.
- `seaborn` for creating count plots and box plots.
Examples
--------
>>> # Generate EDA visualizations before data cleaning
>>> df = SupervisedLearning(dataset)
>>> df.eda_visual(y='target_variable', before_data_cleaning=True)
>>> # Generate EDA visualizations after data cleaning
>>> df.eda_visual(y='target_variable', before_data_cleaning=False)
"""
if before_data_cleaning == False:
data_histogram = self.__data.hist(figsize = figsize_histogram, bins = histogram_bins)
plt.figure(figsize = figsize_heatmap)
data_heatmap = sns.heatmap(self.__data.corr(), cmap = "coolwarm", annot = True, fmt=".2f")
plt.title('Correlation Matrix')
plt.show()
elif before_data_cleaning == True:
# Visualize the distribution of categorical features
categorical_features = self.__data.select_dtypes(include = "object").columns
for feature in categorical_features:
plt.figure(figsize=figsize_barchart)
sns.countplot(x=feature, data = self.__data)
plt.title(f'Distribution of {feature}')
plt.show()
data_histogram = self.__data.hist(figsize = figsize_histogram, bins = histogram_bins)
plt.figure(figsize = figsize_heatmap)
data_heatmap = sns.heatmap(self.__data.corr(), cmap = "coolwarm", annot = True, fmt=".2f")
plt.title('Correlation Matrix')
plt.show()
self.__eda_visual = True
return {"Heatmap": data_heatmap, "Histogram": data_histogram}
[docs]
def select_dependent_and_independent(self, predict: str):
"""
Select the dependent and independent variables for the supervised learning model.
Parameters
----------
predict : str
The name of the column to be used as the dependent variable.
Returns
-------
Dict
A dictionary containing the dependent variable and independent variables.
Notes
-----
This method uses the `pandas` library for data manipulation.
Examples
--------
>>> # Select dependent and independent variables
>>> df = SupervisedLearning(dataset)
>>> variables = df.select_dependent_and_independent("target_column")
See Also
--------
- pandas.DataFrame.drop : Drop specified labels from rows or columns.
- pandas.Series : One-dimensional ndarray with axis labels.
"""
self.__x = self.__data.drop(predict, axis = 1)
self.__y = self.__data[f"{predict}"]
self.__dependent_independent = True
return {"Dependent Variable": self.__y, "Independent Variables": self.__x}
[docs]
def split_data(self, test_size: float = 0.2):
"""
Split the dataset into training and test sets.
Parameters
----------
test_size: float, optional, default=0.2
Specifies the size of the data to split as test data.
Returns
-------
Dict
A dictionary containing the training and test sets for independent (X) and dependent (y) variables.
Notes
-----
This method uses the `sklearn.model_selection.train_test_split` function for data splitting.
Examples
--------
>>> # Split the data into training and test sets
>>> df = SupervisedLearning(dataset)
>>> data_splits = df.split_data()
>>>
>>> X_train = data_splits["Training X"]
>>> X_test = data_splits["Test X"]
>>> y_train = data_splits["Training Y"]
>>> y_test = data_splits["Test Y"]
See Also
--------
- sklearn.model_selection.train_test_split : Split arrays or matrices into random train and test subsets.
"""
self.__x_train, self.__x_test, self.__y_train, self.__y_test = sms.train_test_split(self.__x, self.__y, test_size = test_size, random_state = 0)
self.__split_data = True
if self.__polynomial_regression == True:
self.__x_train1, self.__x_test1, self.__y_train1, self.__y_test1 = sms.train_test_split(self.__x1, self.__y, test_size = test_size, random_state = 0)
return {"Training X": self.__x_train, "Test X": self.__x_test, "Training Y": self.__y_train, "Test Y": self.__y_test}
[docs]
def train_model_regressor(self, regressor):
"""
Train a regressor model.
Parameters
----------
regressor : Any
A regressor model object compatible with scikit-learn's regressor interface.
Returns
-------
Any
The trained regressor model.
Notes
-----
- This method uses the `sklearn.model_selection` and `sklearn.metrics` libraries for training and evaluation.
- All required steps before model training should have been completed before running this function.
Examples
--------
>>> from sklearn.linear_model import LinearRegression
>>>
>>> # Train a regressor model
>>> df = SupervisedLearning(dataset)
>>> regressor = LinearRegression()
>>> trained_regressor = df.train_model_regressor(regressor)
See Also
--------
- sklearn.model_selection.train_test_split : Split arrays or matrices into random train and test subsets.
- sklearn.metrics.r2_score : R^2 (coefficient of determination) regression score function.
"""
if self.__split_data == True:
self.regression_problem = True
self.regressor = regressor
self.model_regressor = self.regressor.fit(self.__x_train, self.__y_train)
score = self.model_regressor.score(self.__x_train, self.__y_train)
print(f"{self.regressor.__class__.__name__}'s amount of variation in Y predicted by your features X after training: (Rsquared) ----> {score}")
self.__model_training = True
else:
self.regression_problem = True
self.regressor = regressor
self.model_regressor = self.regressor.fit(self.__x, self.__y)
score = self.model_regressor.score(self.__x, self.__y)
print(f"{self.regressor.__class__.__name__}'s amount of variation in Y predicted by your features X after training: (Rsquared) ----> {score}")
self.__model_training = True
return self.model_regressor
[docs]
def train_model_classifier(self, classifier):
"""
Train a classifier on the provided data.
Parameters
----------
classifier : Any
The classifier object to be trained.
Returns
-------
Any
The trained classifier.
Notes
-----
This method uses the `sklearn.model_selection` and `sklearn.metrics` libraries for training and evaluating the classifier.
Examples
--------
>>> from sklearn.ensemble import RandomForestClassifier
>>>
>>> # Train a classifier
>>> df = SupervisedLearning(dataset)
>>> classifier = RandomForestClassifier(random_state = 0)
>>> trained_classifier = df.train_model_classifier(classifier)
See Also
--------
- sklearn.model_selection.train_test_split : Split arrays or matrices into random train and test subsets.
- sklearn.metrics.accuracy_score : Accuracy classification score.
"""
if self.__split_data == True:
self.classification_problem = True
self.classifier = classifier
self.model_classifier = self.classifier.fit(self.__x_train, self.__y_train)
score = self.model_classifier.score(self.__x_train, self.__y_train)
print(f"{self.classifier.__class__.__name__} accuracy in prediction after training: (Accuracy) ---> {score}")
self.__model_training = True
else:
self.classification_problem = True
self.classifier = classifier
self.model_classifier = self.classifier.fit(self.__x, self.__y)
score = self.model_classifier.score(self.__x, self.__y)
print(f"{self.classifier.__class__.__name__} accuracy in prediction after training: (Accuracy) ---> {score}")
self.__model_training = True
return self.model_classifier
[docs]
def regressor_predict(self):
"""
Predict the target variable for regression models.
Returns
-------
Dict[str, np.ndarray]
A dictionary containing actual training and test targets along with predicted values,
or None if the model is set for classification.
Raises
------
AssertionError
If the training phase of the model is set to classification, as regression models
cannot predict a classification model.
Notes
-----
This method uses the `sklearn` library for regression model prediction.
Examples
--------
>>> from sklearn.linear_model import LinearRegression
>>>
>>> # Train a regressor model
>>> df = SupervisedLearning(dataset)
>>> regressor = LinearRegression()
>>> trained_regressor = df.train_model_regressor(regressor)
>>>
>>> # Predict for regression model
>>> predictions = df.regressor_predict()
>>>
>>> print(predictions)
{'Actual Training Y': array([...]), 'Actual Test Y': array([...]),
'Predicted Training Y': array([...]), 'Predicted Test Y': array([...])}
See Also
--------
- sklearn.model_selection.train_test_split : Split arrays or matrices into random train and test subsets.
"""
if self.__split_data == True:
if self.regression_problem == True:
self.__y_pred = self.model_regressor.predict(self.__x_train)
self.__y_pred1 = self.model_regressor.predict(self.__x_test)
self.__model_prediction = True
return {"Actual Training Y": self.__y_train, "Actual Test Y": self.__y_test, "Predicted Training Y": self.__y_pred, "Predicted Test Y": self.__y_pred1}
else:
if self.regression_problem == True:
self.__y_pred = self.model_regressor.predict(self.__x)
self.__model_prediction = True
return {"Actual Y": self.__y, "Predicted Y": self.__y_pred}
[docs]
def classifier_predict(self):
"""
Predict the target variable using the trained classifier.
Returns
-------
Dict[str, np.ndarray]
A dictionary containing the actual and predicted values for training and test sets.
Keys include 'Actual Training Y', 'Actual Test Y', 'Predicted Training Y', and 'Predicted Test Y'.
Raises
------
AssertionError
If the model is set for regression, not classification.
Notes
-----
This method uses the `sklearn` library for classification model prediction.
Examples
--------
>>> from sklearn.ensemble import RandomForestClassifier
>>>
>>> # Train a regressor model
>>> df = SupervisedLearning(dataset)
>>> classifier = RandomForestClassifier(random_state = 0)
>>> trained_classifier = df.train_model_classifier(classifier)
>>>
>>> # Predict for regression model
>>> predictions = df.classifier_predict()
>>>
>>> print(predictions)
{'Actual Training Y': array([...]), 'Actual Test Y': array([...]),
'Predicted Training Y': array([...]), 'Predicted Test Y': array([...])}
See Also
--------
- sklearn.model_selection.train_test_split : Split arrays or matrices into random train and test subsets.
"""
if self.__split_data == True:
if self.classification_problem == True:
self.__y_pred = self.model_classifier.predict(self.__x_train)
self.__y_pred1 = self.model_classifier.predict(self.__x_test)
self.__model_prediction = True
return {"Actual Training Y": self.__y_train, "Actual Test Y": self.__y_test, "Predicted Training Y": self.__y_pred, "Predicted Test Y": self.__y_pred1}
else:
raise AssertionError("The training phase of the model has been set to regression. Can not predict a regression model with a classification model.")
else:
if self.classification_problem == True:
self.__y_pred = self.model_classifier.predict(self.__x)
self.__model_prediction = True
return {"Actual Y": self.__y, "Predicted Y": self.__y_pred}
else:
raise AssertionError("The training phase of the model has been set to regression. Can not predict a regression model with a classification model.")
[docs]
def regressor_model_testing(self, variables_values: list, scaling: bool = False):
"""
Test the trained regressor model with given input variables.
Parameters
----------
variables_values : list
A list containing values for each independent variable.
scaling : bool, default False
Whether to scale the input variables. If True, the method expects
scaled input using the same scaler used during training.
Returns
-------
np.ndarray
The predicted values from the regressor model.
Raises
------
AssertionError
If the problem type is not regression.
Notes
-----
- This method tests a pre-trained regressor model.
- If scaling is set to True, the input variables are expected to be scaled using the same scaler used during training.
Examples
--------
>>> # Assuming df is an instance of SupervisedLearning class with a trained regressor model
>>> df.regressor_model_testing([1.5, 0.7, 2.0], scaling=True)
array([42.0])
See Also
--------
- sklearn.preprocessing.StandardScaler : Standardize features by removing the mean and scaling to unit variance.
"""
if self.regression_problem == True:
if scaling == False:
prediction = self.model_regressor.predict([variables_values])
self.__model_testing = True
return prediction
elif scaling == True:
variables_values = self.__scaler.transform([variables_values])
prediction = self.model_regressor.predict(variables_values)
self.__model_testing = True
return prediction
else:
raise AssertionError("You can't test a classification problem with this function.")
[docs]
def regressor_evaluation(self, kfold: int = None, cross_validation: bool = False):
"""
Evaluate the performance of the regression model.
Parameters
----------
kfold : int, optional
Number of folds for cross-validation. If provided, cross-validation will be performed.
cross_validation : bool, default False
If True, perform cross-validation; otherwise, perform a simple train-test split evaluation.
Returns
-------
dict
Dictionary containing evaluation metrics.
Raises
------
TypeError
If invalid combination of parameters is provided.
Notes
-----
This method uses the `sklearn.metrics` and `sklearn.model_selection` libraries for regression evaluation.
Examples
--------
>>> # Evaluate regression model performance using simple train-test split
>>> from sklearn.linear_model import LinearRegression
>>>
>>> # Train a regressor model
>>> df = SupervisedLearning(dataset)
>>> regressor = LinearRegression()
>>> trained_regressor = df.train_model_regressor(regressor)
>>>
>>> # Predict for regression model
>>> predictions = df.regressor_predict()
>>> evaluation_results = df.regressor_evaluation()
>>> # Evaluate regression model performance using 10-fold cross-validation
>>> from sklearn.linear_model import LinearRegression
>>>
>>> # Train a regressor model
>>> df = SupervisedLearning(dataset)
>>> regressor = LinearRegression()
>>> trained_regressor = df.train_model_regressor(regressor)
>>>
>>> # Predict for regression model
>>> predictions = df.regressor_predict()
>>> evaluation_results = df.regressor_evaluation(kfold=10, cross_validation=True)
See Also
--------
- sklearn.metrics.r2_score : R-squared (coefficient of determination) regression score function.
- sklearn.metrics.mean_squared_error : Mean squared error regression loss.
- sklearn.model_selection.cross_val_score : Evaluate a score by cross-validation.
"""
if self.__split_data == True:
if self.regression_problem == True:
if kfold == None and cross_validation == False:
training_rsquared = sm.r2_score(self.__y_train, self.__y_pred)
test_rsquared = sm.r2_score(self.__y_test, self.__y_pred1)
training_rmse = np.sqrt(sm.mean_squared_error(self.__y_train, self.__y_pred))
test_rmse = np.sqrt(sm.mean_squared_error(self.__y_test, self.__y_pred1))
self.__model_evaluation = True
return {"Training Evaluation": {"Training R2": training_rsquared, "Training RMSE": training_rmse}, "Test Evaluation": {"Test R2": test_rsquared, "Test RMSE": test_rmse}}
elif kfold != None and cross_validation == False:
raise TypeError
elif kfold == None and cross_validation == True:
training_rsquared = sm.r2_score(self.__y_train, self.__y_pred)
test_rsquared = sm.r2_score(self.__y_test, self.__y_pred1)
training_rmse = np.sqrt(sm.mean_squared_error(self.__y_train, self.__y_pred))
test_rmse = np.sqrt(sm.mean_squared_error(self.__y_test, self.__y_pred1))
cross_val = sms.cross_val_score(self.model_regressor, self.__x_train, self.__y_train, cv = 10)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {"Training Evaluation": {"Training R2": training_rsquared, "Training RMSE": training_rmse}, "Test Evaluation": {"Test R2": test_rsquared, "Test RMSE": test_rmse}, "Cross Validation": {"Cross Validation Mean": score_mean, "Cross Validation Standard Deviation": score_std_dev}}
elif kfold != None and cross_validation == True:
training_rsquared = sm.r2_score(self.__y_train, self.__y_pred)
test_rsquared = sm.r2_score(self.__y_test, self.__y_pred1)
training_rmse = np.sqrt(sm.mean_squared_error(self.__y_train, self.__y_pred))
test_rmse = np.sqrt(sm.mean_squared_error(self.__y_test, self.__y_pred1))
cross_val = sms.cross_val_score(self.model_regressor, self.__x_train, self.__y_train, cv = kfold)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {"Training Evaluation": {"Training R2": training_rsquared, "Training RMSE": training_rmse}, "Test Evaluation": {"Test R2": test_rsquared, "Test RMSE": test_rmse}, "Cross Validation": {"Cross Validation Mean": score_mean, "Cross Validation Standard Deviation": score_std_dev}}
else:
raise AssertionError("You can not use a regression evaluation function for a classification problem.")
else:
if self.regression_problem == True:
if kfold == None and cross_validation == False:
rsquared = sm.r2_score(self.__y, self.__y_pred)
rmse = np.sqrt(sm.mean_squared_error(self.__y, self.__y_pred))
self.__model_evaluation = True
return {"R2": rsquared, "RMSE": rmse}
elif kfold != None and cross_validation == False:
raise TypeError
elif kfold == None and cross_validation == True:
rsquared = sm.r2_score(self.__y, self.__y_pred)
rmse = np.sqrt(sm.mean_squared_error(self.__y, self.__y_pred))
cross_val = sms.cross_val_score(self.model_regressor, self.__x, self.__y, cv = 10)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {"Training Evaluation": {"Training R2": training_rsquared, "Training RMSE": training_rmse}, "Test Evaluation": {"Test R2": test_rsquared, "Test RMSE": test_rmse}, "Cross Validation": {"Cross Validation Mean": score_mean, "Cross Validation Standard Deviation": score_std_dev}}
elif kfold != None and cross_validation == True:
rsquared = sm.r2_score(self.__y, self.__y_pred)
rmse = np.sqrt(sm.mean_squared_error(self.__y, self.__y_pred))
cross_val = sms.cross_val_score(self.model_regressor, self.__x, self.__y, cv = kfold)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {"R2": rsquared, "RMSE": rmse, "Cross Validation Mean": score_mean, "Cross Validation Standard Deviation": score_std_dev}
else:
raise AssertionError("You can not use a regression evaluation function for a classification problem.")
[docs]
def build_multiple_regressors(self, regressors: list or tuple, kfold: int = None, cross_validation: bool = False, graph: bool = False, length: int = 20, width: int = 10, linestyle: str = 'dashed', marker: str = 'o', markersize: int = 12, fontweight: int = 80, fontstretch: int = 50):
"""
Build, evaluate, and optionally graph multiple regression models.
This method facilitates the construction and assessment of multiple regression models using a variety of algorithms.
It supports both single train-test split and k-fold cross-validation approaches. The generated models are evaluated
based on key regression metrics, providing insights into their performance on both training and test datasets.
Parameters
----------
regressors : list or tuple
List of regression models to build and evaluate.
kfold : int, optional
Number of folds for cross-validation. Default is None.
cross_validation : bool, default False
If True, perform cross-validation; otherwise, use a simple train-test split.
graph : bool, default False
If True, plot evaluation metrics for each regression model.
length : int, optional, default=None
Length of the graph (if graph=True).
width : int, optional, default=None
Width of the graph (if graph=True).
Returns
-------
dict
A dictionary containing regression metrics and additional information.
Notes
-----
This method uses the following libraries:
- `sklearn.model_selection` for train-test splitting and cross-validation.
- `matplotlib.pyplot` for plotting if graph=True.
Examples
--------
>>> # Build and evaluate multiple regression models
>>> df = SupervisedLearning(dataset)
>>> models = [LinearRegression(),
>>> RandomForestRegressor(),
>>> GradientBoostingRegressor()]
>>> results = df.build_multiple_regressors(regressors=models,
>>> kfold=5,
>>> cross_validation=True,
>>> graph=True)
See Also
--------
- SupervisedLearning.train_model_regressor : Train a single regression model.
- SupervisedLearning.regressor_predict : Make predictions using a trained regression model.
- SupervisedLearning.regressor_evaluation : Evaluate the performance of a regression model.
"""
if self.__split_data == True:
if (isinstance(regressors, list) or isinstance(regressors, tuple)) and cross_validation == False:
self.__multiple_regressor_models = {}
store = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"]
]
store.append(info)
dataset_regressors = pd.DataFrame(store, columns = ["Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
if graph == True:
# Training R2
plt.figure(figsize = (length, width))
plt.title("Training R2", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Training R2"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training R2"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training R2", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training RMSE
plt.figure(figsize = (length, width))
plt.title("Training RMSE", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Training RMSE"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training RMSE"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training RMSE", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test R2
plt.figure(figsize = (length, width))
plt.title("Training R2", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Test R2"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training R2"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training R2", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test RMSE
plt.figure(figsize = (length, width))
plt.title("Training RMSE", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Test RMSE"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training RMSE"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training RMSE", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
elif (isinstance(regressors, list) or isinstance(regressors, tuple)) and cross_validation == True:
self.__multiple_regressor_models = {}
store = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store.append(info)
dataset_regressors = pd.DataFrame(store, columns = ["Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if graph == True:
# Training R2
plt.figure(figsize = (length, width))
plt.title("Training R2", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Training R2"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training R2"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training R2", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training RMSE
plt.figure(figsize = (length, width))
plt.title("Training RMSE", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Training RMSE"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training RMSE"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training RMSE", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test R2
plt.figure(figsize = (length, width))
plt.title("Training R2", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Test R2"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training R2"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training R2", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test RMSE
plt.figure(figsize = (length, width))
plt.title("Training RMSE", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Test RMSE"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Training RMSE"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training RMSE", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Mean
plt.figure(figsize = (length, width))
plt.title("Cross Validation Mean", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Cross Validation Mean"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Cross Validation Mean"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Mean", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Standard Deviation
plt.figure(figsize = (length, width))
plt.title("Cross Validation Standard Deviation", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Cross Validation Standard Deviation"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Cross Validation Standard Deviation"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Standard Deviation", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
return {"Regressor Metrics": dataset_regressors, "More Info": self.__multiple_regressor_models}
else:
if (isinstance(regressors, list) or isinstance(regressors, tuple)) and cross_validation == False:
self.__multiple_regressor_models = {}
store = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["RMSE"],
]
store.append(info)
dataset_regressors = pd.DataFrame(store, columns = ["Algorithm", "R2", "RMSE"])
if graph == True:
# R2
plt.figure(figsize = (length, width))
plt.title("R2", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["R2"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["R2"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("R2", labelpad = 20)
plt.show()
# RMSE
plt.figure(figsize = (length, width))
plt.title("RMSE", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["RMSE"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["RMSE"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("RMSE", labelpad = 20)
plt.show()
elif (isinstance(regressors, list) or isinstance(regressors, tuple)) and cross_validation == True:
self.__multiple_regressor_models = {}
store = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store.append(info)
dataset_regressors = pd.DataFrame(store, columns = ["Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if graph == True:
# R2
plt.figure(figsize = (length, width))
plt.title("R2", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["R2"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["R2"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("R2", labelpad = 20)
plt.show()
# RMSE
plt.figure(figsize = (length, width))
plt.title("RMSE", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["RMSE"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["RMSE"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("RMSE", labelpad = 20)
plt.show()
# Cross Validation Mean
plt.figure(figsize = (length, width))
plt.title("Cross Validation Mean", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Cross Validation Mean"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Cross Validation Mean"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Mean", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Standard Deviation
plt.figure(figsize = (length, width))
plt.title("Cross Validation Standard Deviation", pad = 10)
plt.plot(dataset_regressors["Algorithm"], dataset_regressors["Cross Validation Standard Deviation"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_regressors.Algorithm, round(dataset_regressors["Cross Validation Standard Deviation"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Standard Deviation", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
return {"Regressor Metrics": dataset_regressors, "More Info": self.__multiple_regressor_models}
[docs]
def build_multiple_classifiers(self, classifiers: list or tuple, kfold: int = None, cross_validation: bool = False, graph: bool = False, length: int = 20, width: int = 10, linestyle: str = 'dashed', marker: str = 'o', markersize: int = 12, fontweight: int = 80, fontstretch: int = 50):
"""
Build and evaluate multiple classifiers.
Parameters
----------
classifiers : list or tuple
A list or tuple of classifier objects to be trained and evaluated.
kfold : int, optional, default=None
Number of folds for cross-validation. If None, cross-validation is not performed.
cross_validation : bool, optional, default=False
Perform cross-validation if True.
graph : bool, optional, default=False
Whether to display performance metrics as graphs.
length : int, optional, default=None
Length of the graph (if graph=True).
width : int, optional, default=None
Width of the graph (if graph=True).
Returns
-------
dict
A dictionary containing classifier metrics and additional information.
Notes
-----
This method builds and evaluates multiple classifiers on the provided dataset. It supports both traditional
training/testing evaluation and cross-validation.
If `graph` is True, the method also displays graphs showing performance metrics for training and testing datasets.
References
----------
- `scikit-learn: Machine Learning in Python <https://scikit-learn.org/stable/>`_
- `matplotlib: Python plotting <https://matplotlib.org/>`_
- `numpy: The fundamental package for scientific computing with Python <https://numpy.org/>`_
- `pandas: Powerful data structures for data analysis <https://pandas.pydata.org/>`_
Example:
--------
>>> classifiers = [LogisticRegression(random_state = 0),
>>> RandomForestClassifier(random_state = 0),
>>> SVC(random_state = 0)]
>>> results = build_multiple_classifiers(classifiers,
>>> kfold=5,
>>> cross_validation=True,
>>> graph=True,
>>> length=8,
>>> width=12)
Note: Ensure that the classifiers provided are compatible with scikit-learn's classification API.
"""
if self.__split_data == True:
if isinstance(classifiers, (list, tuple)) and cross_validation == False:
self.__multiple_classifier_models = {}
store = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cross_validation)}
info = [
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
]
store.append(info)
dataset_classifiers = pd.DataFrame(store, columns = ["Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
if graph == True:
# Training Accuracy
plt.figure(figsize = (length, width))
plt.title("Training Accuracy", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training Accuracy"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training Accuracy"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training Accuracy", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Precision
plt.figure(figsize = (length, width))
plt.title("Training Precision", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training Precision"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training Precision"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training Precision", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Recall
plt.figure(figsize = (length, width))
plt.title("Training Recall", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training Recall"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training Recall"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training Recall", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training F1 Score
plt.figure(figsize = (length, width))
plt.title("Training F1 Score", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training F1 Score"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training F1 Score"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training F1 Score", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test Accuracy
plt.figure(figsize = (length, width))
plt.title("Test Accuracy", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Accuracy"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Accuracy"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test Accuracy", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test Precision
plt.figure(figsize = (length, width))
plt.title("Test Precision", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Precision"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Precision"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test Precision", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test Recall
plt.figure(figsize = (length, width))
plt.title("Test Recall", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Recall"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Recall"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test Recall", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test F1 Score
plt.figure(figsize = (length, width))
plt.title("Test F1 Score", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test F1 Score"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test F1 Score"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test F1 Score", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
elif (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cross_validation == True:
self.__multiple_classifier_models = {}
store = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cross_validation)}
name = self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__
info = [
name,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store.append(info)
dataset_classifiers = pd.DataFrame(store, columns = ["Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test Model F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if graph == True:
# Training Accuracy
plt.figure(figsize = (length, width))
plt.title("Training Accuracy", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training Accuracy"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training Accuracy"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training Accuracy", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Precision
plt.figure(figsize = (length, width))
plt.title("Training Precision", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training Precision"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training Precision"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training Precision", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Recall
plt.figure(figsize = (length, width))
plt.title("Training Recall", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training Recall"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training Recall"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training Recall", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training F1 Score
plt.figure(figsize = (length, width))
plt.title("Training F1 Score", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Training F1 Score"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Training F1 Score"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Training F1 Score", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test Accuracy
plt.figure(figsize = (length, width))
plt.title("Test Accuracy", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Accuracy"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Accuracy"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test Accuracy", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test Precision
plt.figure(figsize = (length, width))
plt.title("Test Precision", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Precision"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Precision"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test Precision", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test Recall
plt.figure(figsize = (length, width))
plt.title("Test Recall", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Recall"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Recall"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test Recall", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Test F1 Score
plt.figure(figsize = (length, width))
plt.title("Test F1 Score", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Test Model F1 Score"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Test Model F1 Score"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Test F1 Score", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Mean
plt.figure(figsize = (length, width))
plt.title("Cross Validation Mean", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Cross Validation Mean"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Cross Validation Mean"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Mean", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Standard Deviation
plt.figure(figsize = (length, width))
plt.title("Cross Validation Standard Deviation", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Cross Validation Standard Deviation"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Cross Validation Standard Deviation"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Standard Deviation", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
return {"Classifier Metrics": dataset_classifiers, "More Info": self.__multiple_classifier_models}
else:
if (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cross_validation == False:
self.__multiple_classifier_models = {}
store = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cross_validation)}
info = [
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
]
store.append(info)
dataset_classifiers = pd.DataFrame(store, columns = ["Algorithm", "Accuracy", "Precision", "Recall", "F1 Score",])
if graph == True:
# Training Accuracy
plt.figure(figsize = (length, width))
plt.title("Accuracy", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Accuracy"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Accuracy"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Accuracy", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Precision
plt.figure(figsize = (length, width))
plt.title("Precision", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Precision"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Precision"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Precision", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Recall
plt.figure(figsize = (length, width))
plt.title("Recall", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Recall"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Recall"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Recall", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training F1 Score
plt.figure(figsize = (length, width))
plt.title("F1 Score", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["F1 Score"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["F1 Score"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("F1 Score", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
elif (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cross_validation == True:
self.__multiple_classifier_models = {}
store = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cross_validation)}
name = self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__
info = [
name,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store.append(info)
dataset_classifiers = pd.DataFrame(store, columns = ["Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if graph == True:
# Training Accuracy
plt.figure(figsize = (length, width))
plt.title("Accuracy", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Accuracy"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Accuracy"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Accuracy", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Precision
plt.figure(figsize = (length, width))
plt.title("Precision", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Precision"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Precision"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Precision", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training Recall
plt.figure(figsize = (length, width))
plt.title("Recall", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Recall"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Recall"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Recall", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Training F1 Score
plt.figure(figsize = (length, width))
plt.title("F1 Score", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["F1 Score"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["F1 Score"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("F1 Score", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Mean
plt.figure(figsize = (length, width))
plt.title("Cross Validation Mean", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Cross Validation Mean"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Cross Validation Mean"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Mean", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
# Cross Validation Standard Deviation
plt.figure(figsize = (length, width))
plt.title("Cross Validation Standard Deviation", pad = 10)
plt.plot(dataset_classifiers["Algorithm"], dataset_classifiers["Cross Validation Standard Deviation"], 'go--', linestyle = linestyle, marker = marker, markersize = markersize)
for x1, y1 in zip(dataset_classifiers.Algorithm, round(dataset_classifiers["Cross Validation Standard Deviation"], 4)):
plt.text(x = x1, y = y1 + 0.0002, s = str(y1), horizontalalignment = "center", verticalalignment = "bottom", size = "large", fontweight = fontweight, fontstretch = fontstretch)
plt.xlabel("Algorithm", labelpad = 20)
plt.ylabel("Cross Validation Standard Deviation", labelpad = 20)
# plt.yticks(np.arange(0.0, 1.0, 0.1))
plt.show()
return {"Classifier Metrics": dataset_classifiers, "More Info": self.__multiple_classifier_models}
[docs]
def build_single_regressor_from_features(self, strategy: str, estimator, regressor, max_num_features: int = None, min_num_features: int = None, kfold: int = None, cv: bool = False):
"""
Build and evaluate a single regression model using feature selection.
Parameters
----------
strategy : str
Feature selection strategy. Should be one of ["selectkbest", "selectpercentile", "rfe", "selectfrommodel"].
estimator :
Estimator used for feature selection, applicable for "rfe" and "selectfrommodel" strategies. Is set to a regressor that implements 'fit'. Could be one of ["f_regression", "f_oneway", "chi2"] if strategy is set to: ["selectkbest", "selectpercentile"].
regressor : object
Regression model object to be trained.
max_num_features : int, optional
Maximum number of features to consider, by default None.
min_num_features : int, optional
Minimum number of features to consider, by default None.
kfold : int, optional
Number of folds for cross-validation, by default None. Needs cv to be set to True to work.
cv : bool, optional
Whether to perform cross-validation, by default False.
Returns
-------
dict
A dictionary containing feature metrics and additional information about the models.
Notes
-----
- This method builds a regression model using feature selection techniques and evaluates its performance.
- The feature selection strategies include "selectkbest", "selectpercentile", "rfe", and "selectfrommodel".
- The estimator parameter is required for "rfe" and "selectfrommodel" strategies.
- This method assumes that the dataset and labels are already set in the class instance.
See Also
--------
- `scikit-learn.feature_selection` for feature selection techniques.
- `scikit-learn.linear_model` for regression models.
- `scikit-learn.model_selection` for cross-validation techniques.
- `scikit-learn.metrics` for regression performance metrics.
- Other libraries used in this method: `numpy`, `pandas`, `matplotlib`, `seaborn`, `ydata_profiling`, `sweetviz`,
`imblearn`, `sklearn`, `warnings`, `datatable`.
References
-----------
- scikit-learn documentation for feature selection: https://scikit-learn.org/stable/modules/feature_selection.html
- scikit-learn documentation for regression models: https://scikit-learn.org/stable/supervised_learning.html#regression
Example
--------
>>> from sklearn.feature_selection import f_regression
>>> from buildml import SupervisedLearning
>>> from sklearn.linear_model import LinearRegression
>>>
>>> learn = SupervisedLearning(dataset)
>>> results = learn.build_single_regressor_from_features(strategy='selectkbest',
>>> estimator=f_regression,
>>> regressor=LinearRegression())
>>> print(results)
"""
if self.__split_data == True:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if not (isinstance(regressor, list) or isinstance(regressor, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"]
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"]
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif not (isinstance(regressor, list) or isinstance(regressor, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
else:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if not (isinstance(regressor, list) or isinstance(regressor, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "R2", "RMSE"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["RMSE"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["RMSE"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif not (isinstance(regressor, list) or isinstance(regressor, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = regressor), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["RMSE"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{regressor.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_regressor_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
[docs]
def build_single_classifier_from_features(self, strategy: str, estimator, classifier, max_num_features: int = None, min_num_features: int = None, kfold: int = None, cv: bool = False):
"""
Build and evaluate a single classification model using feature selection.
Parameters
----------
strategy : str
Feature selection strategy. Should be one of ["selectkbest", "selectpercentile", "rfe", "selectfrommodel"].
estimator :
Estimator used for feature selection, applicable for "rfe" and "selectfrommodel" strategies. Is set to a classifier that implements 'fit'. Could be one of ["f_classif", "chi2", "mutual_info_classif"] if strategy is set to: ["selectkbest", "selectpercentile"].
classifier : object
Classification model object to be trained.
max_num_features : int, optional
Maximum number of features to consider, by default None.
min_num_features : int, optional
Minimum number of features to consider, by default None.
kfold : int, optional
Number of folds for cross-validation, by default None. Needs cv to be set to True to work.
cv : bool, optional
Whether to perform cross-validation, by default False.
Returns
-------
dict
A dictionary containing feature metrics and additional information about the models.
Notes
-----
- This method builds a classification model using feature selection techniques and evaluates its performance.
- The feature selection strategies include "selectkbest", "selectpercentile", "rfe", and "selectfrommodel".
- The estimator parameter is required for "rfe" and "selectfrommodel" strategies.
- This method assumes that the dataset and labels are already set in the class instance.
See Also
--------
- `scikit-learn.feature_selection` for feature selection techniques.
- `scikit-learn.linear_model` for classification models.
- `scikit-learn.model_selection` for cross-validation techniques.
- `scikit-learn.metrics` for classification performance metrics.
- Other libraries used in this method: `numpy`, `pandas`, `matplotlib`, `seaborn`.
References
-----------
- scikit-learn documentation for feature selection: https://scikit-learn.org/stable/modules/feature_selection.html
- scikit-learn documentation for classification models: https://scikit-learn.org/stable/supervised_learning.html#classification
Example
--------
>>> from sklearn.feature_selection import f_classif
>>> from buildml import SupervisedLearning
>>> from sklearn.ensemble import RandomForestClassifier
>>>
>>> learn = SupervisedLearning(dataset)
>>> results = learn.build_single_classifier_from_features(strategy='selectkbest',
>>> estimator=f_classif,
>>> classifier=RandomForestClassifier(random_state = 0))
>>> print(results)
"""
if self.__split_data == True:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if not (isinstance(classifier, list) or isinstance(classifier, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif not (isinstance(classifier, list) or isinstance(classifier, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range((length_col - 1), 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
else:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if not (isinstance(classifier, list) or isinstance(classifier, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif not (isinstance(classifier, list) or isinstance(classifier, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range((length_col - 1), 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = classifier), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{classifier.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"] = self.__multiple_classifier_models
store[f"{num}"]["Feature Info"] = feature_info
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
[docs]
def build_multiple_regressors_from_features(self, strategy: str, estimator, regressors: list or tuple, max_num_features: int = None, min_num_features: int = None, kfold: int = None, cv: bool = False):
"""
Build and evaluate multiple regression models with varying numbers of features.
Parameters:
-----------
strategy : str
The feature selection strategy. Supported values are 'selectkbest', 'selectpercentile',
'rfe', and 'selectfrommodel'.
estimator :
Estimator used for feature selection, applicable for "rfe" and "selectfrommodel" strategies. Is set to a regressor that implements 'fit'. Could be one of ["f_regression", "chi2"] if strategy is set to: ["selectkbest", "selectpercentile"].
regressors : list or tuple
List of regression models to build and evaluate.
max_num_features : int, optional
Maximum number of features to consider during the feature selection process.
min_num_features : int, optional
Minimum number of features to consider during the feature selection process.
kfold : int, optional
Number of folds for cross-validation. If provided, cross-validation metrics will be calculated.
cv : bool, default False
If True, perform cross-validation; otherwise, use a single train-test split.
Returns:
--------
dict
A dictionary containing feature metrics and additional information for each model.
Example:
--------
>>> from buildml import SupervisedLearning
>>> from sklearn.feature_selection import f_regression
>>> from sklearn.ensemble import RandomForestRegressor, DecisionTreeRegressor
>>> from sklearn.linear_model import LinearRegression
>>>
>>>
>>> data = SupervisedLearning(dataset)
>>> results = data.build_multiple_regressors_from_features(
>>> strategy='selectkbest',
>>> estimator=f_regression,
>>> regressors=[LinearRegression(),
>>> RandomForestRegressor(random_state = 0),
>>> DecisionTreeRegressor(random_state = 0)],
>>> max_num_features=10,
>>> kfold=5,
>>> cv=True
>>> )
See Also:
---------
- `sklearn.feature_selection.SelectKBest`
- `sklearn.feature_selection.SelectPercentile`
- `sklearn.feature_selection.RFE`
- `sklearn.feature_selection.SelectFromModel`
- `sklearn.linear_model`
- `sklearn.ensemble.RandomForestRegressor`
- `sklearn.model_selection.cross_val_score`
- `sklearn.metrics.mean_squared_error`
- `sklearn.metrics.r2_score`
"""
if self.__split_data == True:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if isinstance(regressors, (list, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"]
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"]
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif (isinstance(regressors, list) or isinstance(regressors, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Training RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Test RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
else:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if (isinstance(regressors, list) or isinstance(regressors, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "R2", "RMSE"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["RMSE"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = False)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["RMSE"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif (isinstance(regressors, list) or isinstance(regressors, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Regression Model with {num} Feature(s): \n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_regressor_models = {}
store_data = []
for algorithms in regressors:
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_regressor(self, regressor = algorithms), "Prediction": SupervisedLearning.regressor_predict(self), "Evaluation": SupervisedLearning.regressor_evaluation(self, kfold = kfold, cross_validation = True)}
info = [
num,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["R2"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["RMSE"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_regressor_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_regressors = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "R2", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_regressors
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_regressor_models
dataset2 = dataset_regressors
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
[docs]
def build_multiple_classifiers_from_features(self, strategy: str, estimator, classifiers: list or tuple, max_num_features: int = None, min_num_features: int = None, kfold: int = None, cv: bool = False):
"""
Build multiple classifiers using different feature selection strategies and machine learning algorithms.
This method performs feature selection, trains multiple classifiers, and evaluates their performance.
Parameters:
-----------
strategy : str
Feature selection strategy. Should be one of 'selectkbest', 'selectpercentile', 'rfe', or 'selectfrommodel'.
estimator :
Estimator used for feature selection, applicable for "rfe" and "selectfrommodel" strategies. Is set to a classifier that implements 'fit'. Could be one of ["f_classif", "chi2", "mutual_info_classif"] if strategy is set to: ["selectkbest", "selectpercentile"].
classifiers : list or tuple
List of classifier instances to be trained and evaluated.
max_num_features : int, optional
Maximum number of features to consider. If None, all features are considered.
min_num_features : int, optional
Minimum number of features to consider. If None, the process starts with max_num_features and decreases the count until 1.
kfold : int, optional
Number of folds for cross-validation. If None, regular train-test split is used.
cv : bool, optional
If True, perform cross-validation. If False, use a train-test split.
Returns:
--------
dict: A dictionary containing feature metrics and additional information about the trained models.
See Also:
---------
- `scikit-learn.feature_selection` for feature selection strategies: https://scikit-learn.org/stable/modules/feature_selection.html
- `scikit-learn.ensemble` for ensemble classifiers: https://scikit-learn.org/stable/modules/ensemble.html
- `scikit-learn.neighbors` for k-nearest neighbors classifiers: https://scikit-learn.org/stable/modules/neighbors.html
- `pandas` for data manipulation: https://pandas.pydata.org/docs/
- `numpy` for numerical operations: https://numpy.org/doc/stable/
- `sklearn` for various machine learning utilities: https://scikit-learn.org/stable/documentation.html
Example:
--------
>>> from buildml import SupervisedLearning
>>> from sklearn.feature_selection import f_classif
>>> from sklearn.ensemble import RandomForestClassifier, DecisionTreeClassifier
>>>
>>>
>>> data = SupervisedLearning(dataset)
>>> classifiers = [RandomForestClassifier(random_state = 0),
>>> DecisionTreeClassifier(random_state = 0)]
>>> result = data.build_multiple_classifiers_from_features(strategy='selectkbest',
>>> estimator=f_classif,
>>> classifiers=classifiers,
>>> max_num_features=10,
>>> kfold=5)
"""
if self.__split_data == True:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score",])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range((length_col - 1), 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Training Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Test Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Training Accuracy", "Training Precision", "Training Recall", "Training F1 Score", "Test Accuracy", "Test Precision", "Test Recall", "Test F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
else:
types1 = ["selectkbest", "selectpercentile"]
types2 = ["rfe", "selectfrommodel"]
if (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cv == False:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range(length_col, 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
elif (isinstance(classifiers, list) or isinstance(classifiers, tuple)) and cv == True:
data_columns = [col for col in self.__x.columns]
length_col = len(data_columns)
store = {}
dataset_features = pd.DataFrame(columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
if (max_num_features != None) and isinstance(max_num_features, int):
length_col = max_num_features
if (min_num_features == None):
for num in range((length_col - 1), 0, -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
elif (min_num_features != None) and isinstance(min_num_features, int):
if (min_num_features <= length_col):
for num in range(length_col, (min_num_features - 1), -1):
print(f"\n\n\nBuilding Classification Model with {num} Feature(s):\n")
feature_info = {}
features = SupervisedLearning.select_features(self, strategy = strategy, estimator = estimator, number_of_features = num)
strategy = strategy.lower()
if strategy in types2:
self.__x = features
elif strategy in types1:
self.__x = features["Dataset ---> Features Selected"]
# self.__x_train, self.__x_test, self.__y_train, self.__y_test = SupervisedLearning.split_data(self).values()
self.__multiple_classifier_models = {}
store_data = []
for algorithms in classifiers:
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"] = {"Built Model": SupervisedLearning.train_model_classifier(self, classifier = algorithms), "Prediction": SupervisedLearning.classifier_predict(self), "Evaluation": SupervisedLearning.classifier_evaluation(self, kfold = kfold, cross_validation = cv)}
info = [
num,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Built Model"].__class__.__name__,
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Accuracy"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Precision"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model Recall"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Model F1 Score"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Mean"],
self.__multiple_classifier_models[f"{algorithms.__class__.__name__}"]["Evaluation"]["Cross Validation Standard Deviation"],
]
store_data.append(info)
dataset_classifiers = pd.DataFrame(store_data, columns = ["No. of features selected", "Algorithm", "Accuracy", "Precision", "Recall", "F1 Score", "Cross Validation Mean", "Cross Validation Standard Deviation"])
feature_info[f"{num} Feature(s) Selected"] = features
feature_info[f"Model Trained with {num} Feature(s)"] = dataset_classifiers
store[f"{num}"] = {}
store[f"{num}"]["Feature Info"] = feature_info
store[f"{num}"]["More Info"] = self.__multiple_classifier_models
dataset2 = dataset_classifiers
dataset_features = pd.concat([dataset_features, dataset2], axis = 0)
else:
raise TypeError("The parameter 'min_num_features' cannot be more than the number of features in our dataset.")
dataset_features = dataset_features.reset_index(drop = True)
return {"Feature Metrics": dataset_features, "More Info": store}
[docs]
def classifier_evaluation(self, kfold: int = None, cross_validation: bool = False):
"""
Evaluate the performance of a classification model.
Parameters
----------
kfold : int, optional
Number of folds for cross-validation. If not provided, default is None.
cross_validation : bool, default False
Flag to indicate whether to perform cross-validation.
Returns
-------
dict
A dictionary containing evaluation metrics for both training and test sets.
Raises
------
TypeError
- If `kfold` is provided without enabling cross-validation.
AssertionError
- If called for a regression problem.
Notes
-----
- This method evaluates the performance of a classification model using metrics such as confusion matrix, classification report, accuracy, precision, recall, and F1 score.
- If `kfold` is not provided, it evaluates the model on the training and test sets.
- If `cross_validation` is set to True, cross-validation scores are also included in the result.
Examples
--------
>>> # Create a supervised learning instance and train a classification model
>>> model = SupervisedLearning(dataset)
>>> model.train_model_classifier()
>>>
>>> # Evaluate the model
>>> evaluation_results = model.classifier_evaluation(kfold=5, cross_validation=True)
>>> print(evaluation_results)
See Also
--------
- sklearn.metrics.confusion_matrix : Compute confusion matrix.
- sklearn.metrics.classification_report : Build a text report showing the main classification metrics.
- sklearn.metrics.accuracy_score : Accuracy classification score.
- sklearn.metrics.precision_score : Compute the precision.
- sklearn.metrics.recall_score : Compute the recall.
- sklearn.metrics.f1_score : Compute the F1 score.
- sklearn.model_selection.cross_val_score : Evaluate a score by cross-validation.
References
----------
- Scikit-learn: https://scikit-learn.org/stable/modules/model_evaluation.html
- NumPy: https://numpy.org/doc/stable/
- Matplotlib: https://matplotlib.org/stable/contents.html
"""
if self.__split_data == True:
if self.classification_problem == True:
if kfold == None and cross_validation == False:
training_analysis = sm.confusion_matrix(self.__y_train, self.__y_pred)
training_class_report = sm.classification_report(self.__y_train, self.__y_pred)
training_accuracy = sm.accuracy_score(self.__y_train, self.__y_pred)
training_precision = sm.precision_score(self.__y_train, self.__y_pred, average='weighted')
training_recall = sm.recall_score(self.__y_train, self.__y_pred, average='weighted')
training_f1score = sm.f1_score(self.__y_train, self.__y_pred, average='weighted')
test_analysis = sm.confusion_matrix(self.__y_test, self.__y_pred1)
test_class_report = sm.classification_report(self.__y_test, self.__y_pred1)
test_accuracy = sm.accuracy_score(self.__y_test, self.__y_pred1)
test_precision = sm.precision_score(self.__y_test, self.__y_pred1, average='weighted')
test_recall = sm.recall_score(self.__y_test, self.__y_pred1, average='weighted')
test_f1score = sm.f1_score(self.__y_test, self.__y_pred1, average='weighted')
self.__model_evaluation = True
return {
"Training Evaluation": {
"Confusion Matrix": training_analysis,
"Classification Report": training_class_report,
"Model Accuracy": training_accuracy,
"Model Precision": training_precision,
"Model Recall": training_recall,
"Model F1 Score": training_f1score,
},
"Test Evaluation": {
"Confusion Matrix": test_analysis,
"Classification Report": test_class_report,
"Model Accuracy": test_accuracy,
"Model Precision": test_precision,
"Model Recall": test_recall,
"Model F1 Score": test_f1score,
},
}
elif kfold != None and cross_validation == False:
raise TypeError("Cross Validation must be set to True if kfold is specified.")
elif kfold == None and cross_validation == True:
training_analysis = sm.confusion_matrix(self.__y_train, self.__y_pred)
training_class_report = sm.classification_report(self.__y_train, self.__y_pred)
training_accuracy = sm.accuracy_score(self.__y_train, self.__y_pred)
training_precision = sm.precision_score(self.__y_train, self.__y_pred, average='weighted')
training_recall = sm.recall_score(self.__y_train, self.__y_pred, average='weighted')
training_f1score = sm.f1_score(self.__y_train, self.__y_pred, average='weighted')
test_analysis = sm.confusion_matrix(self.__y_test, self.__y_pred1)
test_class_report = sm.classification_report(self.__y_test, self.__y_pred1)
test_accuracy = sm.accuracy_score(self.__y_test, self.__y_pred1)
test_precision = sm.precision_score(self.__y_test, self.__y_pred1, average='weighted')
test_recall = sm.recall_score(self.__y_test, self.__y_pred1, average='weighted')
test_f1score = sm.f1_score(self.__y_test, self.__y_pred1, average='weighted')
cross_val = sms.cross_val_score(self.model_classifier, self.__x_train, self.__y_train, cv = 10)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {
"Training Evaluation": {
"Confusion Matrix": training_analysis,
"Classification Report": training_class_report,
"Model Accuracy": training_accuracy,
"Model Precision": training_precision,
"Model Recall": training_recall,
"Model F1 Score": training_f1score,
},
"Test Evaluation": {
"Confusion Matrix": test_analysis,
"Classification Report": test_class_report,
"Model Accuracy": test_accuracy,
"Model Precision": test_precision,
"Model Recall": test_recall,
"Model F1 Score": test_f1score,
},
"Cross Validation": {
"Cross Validation Mean": score_mean,
"Cross Validation Standard Deviation": score_std_dev
}
}
elif kfold != None and cross_validation == True:
training_analysis = sm.confusion_matrix(self.__y_train, self.__y_pred)
training_class_report = sm.classification_report(self.__y_train, self.__y_pred)
training_accuracy = sm.accuracy_score(self.__y_train, self.__y_pred)
training_precision = sm.precision_score(self.__y_train, self.__y_pred, average='weighted')
training_recall = sm.recall_score(self.__y_train, self.__y_pred, average='weighted')
training_f1score = sm.f1_score(self.__y_train, self.__y_pred, average='weighted')
test_analysis = sm.confusion_matrix(self.__y_test, self.__y_pred1)
test_class_report = sm.classification_report(self.__y_test, self.__y_pred1)
test_accuracy = sm.accuracy_score(self.__y_test, self.__y_pred1)
test_precision = sm.precision_score(self.__y_test, self.__y_pred1, average='weighted')
test_recall = sm.recall_score(self.__y_test, self.__y_pred1, average='weighted')
test_f1score = sm.f1_score(self.__y_test, self.__y_pred1, average='weighted')
cross_val = sms.cross_val_score(self.model_classifier, self.__x_train, self.__y_train, cv = kfold)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {
"Training Evaluation": {
"Confusion Matrix": training_analysis,
"Classification Report": training_class_report,
"Model Accuracy": training_accuracy,
"Model Precision": training_precision,
"Model Recall": training_recall,
"Model F1 Score": training_f1score,
},
"Test Evaluation": {
"Confusion Matrix": test_analysis,
"Classification Report": test_class_report,
"Model Accuracy": test_accuracy,
"Model Precision": test_precision,
"Model Recall": test_recall,
"Model F1 Score": test_f1score,
},
"Cross Validation": {
"Cross Validation Mean": score_mean,
"Cross Validation Standard Deviation": score_std_dev
}
}
else:
raise AssertionError("You can not use a classification evaluation function for a regression problem.")
else:
if self.classification_problem == True:
if kfold == None and cross_validation == False:
training_analysis = sm.confusion_matrix(self.__y, self.__y_pred)
training_class_report = sm.classification_report(self.__y, self.__y_pred)
training_accuracy = sm.accuracy_score(self.__y, self.__y_pred)
training_precision = sm.precision_score(self.__y, self.__y_pred, average='weighted')
training_recall = sm.recall_score(self.__y, self.__y_pred, average='weighted')
training_f1score = sm.f1_score(self.__y, self.__y_pred, average='weighted')
self.__model_evaluation = True
return {
"Confusion Matrix": training_analysis,
"Classification Report": training_class_report,
"Model Accuracy": training_accuracy,
"Model Precision": training_precision,
"Model Recall": training_recall,
"Model F1 Score": training_f1score,
}
elif kfold != None and cross_validation == False:
raise TypeError("Cross Validation must be set to True if kfold is specified.")
elif kfold == None and cross_validation == True:
training_analysis = sm.confusion_matrix(self.__y, self.__y_pred)
training_class_report = sm.classification_report(self.__y, self.__y_pred)
training_accuracy = sm.accuracy_score(self.__y, self.__y_pred)
training_precision = sm.precision_score(self.__y, self.__y_pred, average='weighted')
training_recall = sm.recall_score(self.__y, self.__y_pred, average='weighted')
training_f1score = sm.f1_score(self.__y, self.__y_pred, average='weighted')
cross_val = sms.cross_val_score(self.model_classifier, self.__x_train, self.__y, cv = 10)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {
"Confusion Matrix": training_analysis,
"Classification Report": training_class_report,
"Model Accuracy": training_accuracy,
"Model Precision": training_precision,
"Model Recall": training_recall,
"Model F1 Score": training_f1score,
"Cross Validation Mean": score_mean,
"Cross Validation Standard Deviation": score_std_dev
}
elif kfold != None and cross_validation == True:
training_analysis = sm.confusion_matrix(self.__y, self.__y_pred)
training_class_report = sm.classification_report(self.__y, self.__y_pred)
training_accuracy = sm.accuracy_score(self.__y, self.__y_pred)
training_precision = sm.precision_score(self.__y, self.__y_pred, average='weighted')
training_recall = sm.recall_score(self.__y, self.__y_pred, average='weighted')
training_f1score = sm.f1_score(self.__y, self.__y_pred, average='weighted')
cross_val = sms.cross_val_score(self.model_classifier, self.__x_train, self.__y, cv = kfold)
score_mean = round((cross_val.mean() * 100), 2)
score_std_dev = round((cross_val.std() * 100), 2)
self.__model_evaluation = True
return {
"Confusion Matrix": training_analysis,
"Classification Report": training_class_report,
"Model Accuracy": training_accuracy,
"Model Precision": training_precision,
"Model Recall": training_recall,
"Model F1 Score": training_f1score,
"Cross Validation Mean": score_mean,
"Cross Validation Standard Deviation": score_std_dev
}
else:
raise AssertionError("You can not use a classification evaluation function for a regression problem.")
[docs]
def classifier_model_testing(self, variables_values: list, scaling: bool = False):
"""
Test a classification model with given input variables.
Parameters
----------
variables_values : list
A list containing values for input variables used to make predictions.
scaling : bool, default False
Flag to indicate whether to scale input variables. If True, the method
assumes that the model was trained on scaled data.
Returns
-------
array
Predicted labels for the given input variables.
Raises
------
AssertionError
If called for a regression problem.
Notes
-----
- This method is used to test a classification model by providing values for the input variables and obtaining predicted labels.
- If scaling is required, it is important to set the `scaling` parameter to True.
Examples
--------
>>> # Create a supervised learning instance and train a classification model
>>> model = SupervisedLearning(dataset)
>>> model.train_model_classifier()
>>>
>>> # Provide input variables for testing
>>> input_data = [value1, value2, value3]
>>>
>>> # Test the model
>>> predicted_labels = model.classifier_model_testing(input_data, scaling=True)
>>> print(predicted_labels)
See Also
--------
- sklearn.preprocessing.StandardScaler : Standardize features by removing the mean and scaling to unit variance.
- sklearn.neighbors.KNeighborsClassifier : K-nearest neighbors classifier.
- sklearn.ensemble.RandomForestClassifier : A meta-estimator that fits a number of decision tree classifiers on various sub-samples of the dataset.
References
----------
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
"""
if self.classification_problem == True:
if scaling == False:
prediction = self.model_classifier.predict([variables_values])
self.__model_testing = True
return prediction
elif scaling == True:
variables_values = self.__scaler.transform([variables_values])
prediction = self.model_classifier.predict(variables_values)
self.__model_testing = True
return prediction
else:
raise AssertionError("You can't test a classification problem with this function.")
[docs]
def classifier_graph(self, classifier, cmap_train = "viridis", cmap_test = "viridis", size_train_marker: float = 10, size_test_marker: float = 10, resolution=100):
"""
Visualize the decision boundaries of a classification model.
Parameters
----------
classifier : scikit-learn classifier object
The trained classification model.
cmap_train : str, default "viridis"
Colormap for the training set.
cmap_test : str, default "viridis"
Colormap for the test set.
size_train_marker : float, default 10
Marker size for training set points.
size_test_marker : float, default 10
Marker size for test set points.
resolution : int, default 100
Resolution of the decision boundary plot.
Raises
------
AssertionError
If called for a regression problem.
TypeError
If the number of features is not 2.
Notes
-----
- This method visualizes the decision boundaries of a classification model by plotting the regions where the model predicts different classes.
- It supports both training and test sets, with different markers and colormaps for each.
Examples
--------
>>> # Create a supervised learning instance and train a classification model
>>> model = SupervisedLearning(dataset)
>>> model.train_model_classifier()
>>>
>>> # Visualize the decision boundaries
>>> model.classifier_graph(classifier=model.model_classifier)
See Also
--------
- sklearn.preprocessing.LabelEncoder : Encode target labels.
- sklearn.linear_model.LogisticRegression : Logistic Regression classifier.
- sklearn.svm.SVC : Support Vector Classification.
- sklearn.tree.DecisionTreeClassifier : Decision Tree classifier.
- sklearn.ensemble.RandomForestClassifier : Random Forest classifier.
- sklearn.neighbors.KNeighborsClassifier : K-Nearest Neighbors classifier.
- matplotlib.pyplot.scatter : Plot scatter plots.
References
----------
- Scikit-learn: https://scikit-learn.org/stable/supervised_learning.html
- Matplotlib: https://matplotlib.org/stable/gallery/lines_bars_and_markers/fill.html
"""
if self.__split_data == True:
if self.classification_problem == True:
columns = [col for col in self.__x_train.columns]
if len(columns) == 2:
feature1 = self.__x_train.iloc[:, 0].name
feature2 = self.__x_train.iloc[:, 1].name
le = sp.LabelEncoder()
self.__y_train_encoded = le.fit_transform(self.__y_train)
if isinstance(self.__x_train, pd.DataFrame):
x1_vals_train, x2_vals_train = np.meshgrid(np.linspace((self.__x_train.iloc[:, 0].min() - (self.__x_train.iloc[:, 0].min() / 8)), (self.__x_train.iloc[:, 0].max() + (self.__x_train.iloc[:, 0].max() / 8)), resolution),
np.linspace((self.__x_train.iloc[:, 1].min() - (self.__x_train.iloc[:, 1].min() / 8)), (self.__x_train.iloc[:, 1].max() + (self.__x_train.iloc[:, 1].max() / 8)), resolution))
elif isinstance(self.__x_train, np.ndarray):
x1_vals_train, x2_vals_train = np.meshgrid(np.linspace((self.__x_train.iloc[:, 0].min() - (self.__x_train.iloc[:, 0].min() / 8)), (self.__x_train.iloc[:, 0].max() + (self.__x_train.iloc[:, 0].max() / 8)), resolution),
np.linspace((self.__x_train.iloc[:, 1].min() - (self.__x_train.iloc[:, 1].min() / 8)), (self.__x_train.iloc[:, 1].max() + (self.__x_train.iloc[:, 1].max() / 8)), resolution))
else:
raise TypeError("Unsupported input type for self.__x_train. Use either Pandas DataFrame or NumPy array.")
grid_points_train = np.c_[x1_vals_train.ravel(), x2_vals_train.ravel()]
predictions_train = classifier.predict(grid_points_train)
predictions_train = le.inverse_transform(predictions_train)
plt.figure(figsize = (15, 10))
plt.contourf(x1_vals_train, x2_vals_train, le.transform(predictions_train).reshape(x1_vals_train.shape), alpha=0.3, cmap = cmap_train)
if isinstance(self.__x_train, pd.DataFrame):
plt.scatter(self.__x_train.iloc[:, 0], self.__x_train.iloc[:, 1], c=self.__y_train_encoded, cmap=cmap_train, edgecolors='k', s=size_train_marker, marker='o')
elif isinstance(self.__x_train, np.ndarray):
plt.scatter(self.__x_train[:, 0], self.__x_train[:, 1], c=self.__y_train_encoded, cmap=cmap_train, edgecolors='k', s=size_train_marker, marker='o')
plt.title(f"{classifier.__class__.__name__} Training Classification Graph")
plt.xlabel(feature1)
plt.ylabel(feature2)
plt.tight_layout()
plt.show()
if self.__x_test is not None and self.__y_test is not None:
plt.figure(figsize = (15, 10))
x1_vals_test, x2_vals_test = np.meshgrid(np.linspace((self.__x_test.iloc[:, 0].min() - (self.__x_test.iloc[:, 0].min() / 8)), (self.__x_test.iloc[:, 0].max() + (self.__x_test.iloc[:, 0].max() / 8)), resolution),
np.linspace((self.__x_test.iloc[:, 1].min() - (self.__x_test.iloc[:, 1].min() / 8)), (self.__x_test.iloc[:, 1].max() + (self.__x_test.iloc[:, 1].max() / 8)), resolution))
grid_points_test = np.c_[x1_vals_test.ravel(), x2_vals_test.ravel()]
predictions_test = classifier.predict(grid_points_test)
predictions_test = le.inverse_transform(predictions_test)
plt.contourf(x1_vals_test, x2_vals_test, le.transform(predictions_test).reshape(x1_vals_test.shape), alpha=0.3, cmap=cmap_test)
if isinstance(self.__x_test, pd.DataFrame):
plt.scatter(self.__x_test.iloc[:, 0], self.__x_test.iloc[:, 1], c=le.transform(self.__y_test), cmap=cmap_test, edgecolors='k', s=size_test_marker, marker='o')
elif isinstance(self.__x_test, np.ndarray):
plt.scatter(self.__x_test[:, 0], self.__x_test[:, 1], c=le.transform(self.__y_test), cmap=cmap_test, edgecolors='k', s=size_test_marker, marker='o')
plt.title(f"{classifier.__class__.__name__} Test Classification Graph")
plt.xlabel(feature1)
plt.ylabel(feature2)
plt.tight_layout()
plt.show()
else:
raise TypeError(f"Visualization needs a maximum of 2 features for the independent variables. {len(self.__x_train.columns)} given.")
else:
raise AssertionError("You can not use a classification graph for a regression problem.")
else:
if self.classification_problem == True:
columns = [col for col in self.__x.columns]
if len(columns) == 2:
feature1 = self.__x.iloc[:, 0].name
feature2 = self.__x.iloc[:, 1].name
le = sp.LabelEncoder()
self.__y_encoded = le.fit_transform(self.__y)
if isinstance(self.__x, pd.DataFrame):
x1_vals_train, x2_vals_train = np.meshgrid(np.linspace((self.__x.iloc[:, 0].min() - (self.__x.iloc[:, 0].min() / 8)), (self.__x.iloc[:, 0].max() + (self.__x.iloc[:, 0].max() / 8)), resolution),
np.linspace((self.__x.iloc[:, 1].min() - (self.__x.iloc[:, 1].min() / 8)), (self.__x.iloc[:, 1].max() + (self.__x.iloc[:, 1].max() / 8)), resolution))
elif isinstance(self.__x, np.ndarray):
x1_vals_train, x2_vals_train = np.meshgrid(np.linspace((self.__x.iloc[:, 0].min() - (self.__x.iloc[:, 0].min() / 8)), (self.__x.iloc[:, 0].max() + (self.__x.iloc[:, 0].max() / 8)), resolution),
np.linspace((self.__x.iloc[:, 1].min() - (self.__x.iloc[:, 1].min() / 8)), (self.__x.iloc[:, 1].max() + (self.__x.iloc[:, 1].max() / 8)), resolution))
else:
raise TypeError("Unsupported input type for self.__x. Use either Pandas DataFrame or NumPy array.")
grid_points_train = np.c_[x1_vals_train.ravel(), x2_vals_train.ravel()]
predictions_train = classifier.predict(grid_points_train)
predictions_train = le.inverse_transform(predictions_train)
plt.figure(figsize = (15, 10))
plt.contourf(x1_vals_train, x2_vals_train, le.transform(predictions_train).reshape(x1_vals_train.shape), alpha=0.3, cmap = cmap_train)
if isinstance(self.__x, pd.DataFrame):
plt.scatter(self.__x.iloc[:, 0], self.__x.iloc[:, 1], c=self.__y_encoded, cmap=cmap_train, edgecolors='k', s=size_train_marker, marker='o')
elif isinstance(self.__x, np.ndarray):
plt.scatter(self.__x[:, 0], self.__x[:, 1], c=self.__y_encoded, cmap=cmap_train, edgecolors='k', s=size_train_marker, marker='o')
plt.title(f"{classifier.__class__.__name__} Training Classification Graph")
plt.xlabel(feature1)
plt.ylabel(feature2)
plt.tight_layout()
plt.show()
else:
raise TypeError(f"Visualization needs a maximum of 2 features for the independent variables. {len(self.__x.columns)} given.")
else:
raise AssertionError("You can not use a classification graph for a regression problem.")
[docs]
def numerical_to_categorical(self, column):
"""
Convert numerical columns to categorical in the dataset.
Parameters
----------
column : str, list, or tuple
The name of the column or a list/tuple of column names to be converted.
Returns
-------
DataFrame
A new DataFrame with specified numerical columns converted to categorical.
Notes
-----
- This method converts numerical columns in the dataset to categorical type.
- It is useful when dealing with features that represent categories or labels but are encoded as numerical values.
Examples
--------
>>> # Create a supervised learning instance and load a dataset
>>> data = SupervisedLearning(dataset)
>>>
>>> # Convert a single numerical column to categorical
>>> data.numerical_to_categorical("numeric_column")
>>>
>>> # Convert multiple numerical columns to categorical
>>> data.numerical_to_categorical(["numeric_col1", "numeric_col2"])
See Also
--------
- pandas.DataFrame.astype : Cast a pandas object to a specified dtype.
- NumPy: https://numpy.org/doc/stable/
References
----------
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.astype.html
- NumPy: https://numpy.org/doc/stable/user/basics.types.html
"""
if isinstance(column, list):
for items in column:
self.__data[items] = self.__data[items].astype("object")
elif isinstance(column, str):
self.__data[column] = self.__data[column].astype("object")
elif isinstance(column, tuple):
for items in column:
self.__data[items] = self.__data[items].astype("object")
return self.__data
[docs]
def categorical_to_datetime(self, column):
"""
Convert specified categorical columns to datetime format.
Parameters
----------
column : str, list, or tuple
The column or columns to be converted to datetime format.
Returns
-------
DataFrame
The DataFrame with specified columns converted to datetime.
Notes
-----
This method allows for the conversion of categorical columns containing date or time information to the datetime format.
Examples
--------
>>> # Create a supervised learning instance and convert a single column
>>> model = SupervisedLearning(dataset)
>>> model.categorical_to_datetime('date_column')
>>> # Convert multiple columns
>>> model.categorical_to_datetime(['start_date', 'end_date'])
>>> # Convert a combination of columns using a tuple
>>> model.categorical_to_datetime(('start_date', 'end_date'))
See Also
--------
- pandas.to_datetime : Convert argument to datetime.
References
----------
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html
- NumPy: https://numpy.org/doc/stable/
"""
if isinstance(column, list):
for items in column:
self.__data[items] = pd.to_datetime(self.__data[items])
elif isinstance(column, str):
self.__data[column] = pd.to_datetime(self.__data[column])
elif isinstance(column, tuple):
for items in column:
self.__data[items] = pd.to_datetime(self.__data[items])
return self.__data
[docs]
def column_binning(self, column, number_of_bins: int = 10, labels: list or tuple = None):
"""
Apply binning to specified columns in the dataset.
Parameters
----------
column : str or list or tuple
The column(s) to apply binning to.
number_of_bins : int, default 10
The number of bins to use.
labels: list or tuple, default = None
Name the categorical columns created by giving them labels.
Returns
-------
DataFrame
The dataset with specified column(s) binned.
Notes
-----
- This method uses the `pd.cut` function to apply binning to the specified column(s).
- Binning is a process of converting numerical data into categorical data.
Examples
--------
>>> # Create a supervised learning instance and perform column binning
>>> model = SupervisedLearning(dataset)
>>> model.column_binning(column="Age", number_of_bins=5)
>>> model.column_binning(column=["Salary", "Experience"], number_of_bins=10)
See Also
--------
- pandas.cut : Bin values into discrete intervals.
- pandas.DataFrame : Data structure for handling the dataset.
References
----------
- Pandas Documentation: https://pandas.pydata.org/pandas-docs/stable/index.html
"""
if isinstance(column, list):
for items in column:
self.__data[items] = pd.cut(self.__data[items], bins = number_of_bins, labels = labels)
elif isinstance(column, str):
self.__data[column] = pd.cut(self.__data[column], bins = number_of_bins, labels = labels)
elif isinstance(column, tuple):
for items in column:
self.__data[items] = pd.cut(self.__data[items], bins = number_of_bins, labels = labels)
return self.__data
[docs]
def fix_unbalanced_dataset(self, sampler: str, k_neighbors: int = None, random_state: int = None):
"""
Apply techniques to address class imbalance in the dataset.
Parameters
----------
sampler : str
The resampling technique. Options: "SMOTE", "RandomOverSampler", "RandomUnderSampler".
k_neighbors : int, optional
The number of nearest neighbors to use in the SMOTE algorithm.
random_state : int, optional
Seed for reproducibility.
Returns
-------
dict
A dictionary containing the resampled training data.
Raises
------
TypeError
- If `k_neighbors` is specified for a sampler other than "SMOTE".
Notes
-----
- This method addresses class imbalance in the dataset using various resampling techniques.
- Supported samplers include SMOTE, RandomOverSampler, and RandomUnderSampler.
Examples
--------
>>> # Create a supervised learning instance and fix unbalanced dataset
>>> model = SupervisedLearning(dataset)
>>> model.fix_unbalanced_dataset(sampler="SMOTE", k_neighbors=5)
See Also
--------
- imblearn.over_sampling.SMOTE : Synthetic Minority Over-sampling Technique.
- imblearn.over_sampling.RandomOverSampler : Random over-sampling.
- imblearn.under_sampling.RandomUnderSampler : Random under-sampling.
- sklearn.impute.SimpleImputer : Simple imputation for handling missing values.
References
----------
- Imbalanced-learn Documentation: https://imbalanced-learn.org/stable/
- Scikit-learn Documentation: https://scikit-learn.org/stable/documentation.html
"""
if self.__split_data == True:
if random_state == None:
if sampler == "SMOTE" and k_neighbors != None:
technique = ios.SMOTE(random_state = 0, k_neighbors = k_neighbors)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
elif sampler == "SMOTE" and k_neighbors == None:
technique = ios.SMOTE(random_state = 0)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
elif sampler == "RandomOverSampler" and k_neighbors == None:
technique = ios.RandomOverSampler(random_state = 0)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
elif sampler == "RandomUnderSampler" and k_neighbors == None:
technique = ius.RandomUnderSampler(random_state = 0)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
else:
raise TypeError("k_neighbors works with only the SMOTE algorithm.")
return {"Training X": self.__x_train, "Training Y": self.__y_train}
elif random_state != None:
if sampler == "SMOTE" and k_neighbors != None:
technique = ios.SMOTE(random_state = random_state, k_neighbors = k_neighbors)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
elif sampler == "SMOTE" and k_neighbors == None:
technique = ios.SMOTE(random_state = random_state)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
elif sampler == "RandomOverSampler" and k_neighbors == None:
technique = ios.RandomOverSampler(random_state = random_state)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
elif sampler == "RandomUnderSampler" and k_neighbors == None:
technique = ius.RandomUnderSampler(random_state = random_state)
self.__x_train, self.__y_train = technique.fit_resample(self.__x_train, self.__y_train)
else:
raise TypeError("k_neighbors works with only the SMOTE algorithm.")
return {"Training X": self.__x_train, "Training Y": self.__y_train}
else:
if random_state == None:
if sampler == "SMOTE" and k_neighbors != None:
technique = ios.SMOTE(random_state = 0, k_neighbors = k_neighbors)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
elif sampler == "SMOTE" and k_neighbors == None:
technique = ios.SMOTE(random_state = 0)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
elif sampler == "RandomOverSampler" and k_neighbors == None:
technique = ios.RandomOverSampler(random_state = 0)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
elif sampler == "RandomUnderSampler" and k_neighbors == None:
technique = ius.RandomUnderSampler(random_state = 0)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
else:
raise TypeError("k_neighbors works with only the SMOTE algorithm.")
return {"X": self.__x, "Y": self.__y}
elif random_state != None:
if sampler == "SMOTE" and k_neighbors != None:
technique = ios.SMOTE(random_state = random_state, k_neighbors = k_neighbors)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
elif sampler == "SMOTE" and k_neighbors == None:
technique = ios.SMOTE(random_state = random_state)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
elif sampler == "RandomOverSampler" and k_neighbors == None:
technique = ios.RandomOverSampler(random_state = random_state)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
elif sampler == "RandomUnderSampler" and k_neighbors == None:
technique = ius.RandomUnderSampler(random_state = random_state)
self.__x, self.__y = technique.fit_resample(self.__x, self.__y)
else:
raise TypeError("k_neighbors works with only the SMOTE algorithm.")
return {"X": self.__x, "Y": self.__y}
[docs]
def replace_values(self, replace: int or float or str or list or tuple or dict, new_value: int or float or str or list or tuple):
"""
Replace specified values in the dataset.
Parameters
----------
replace : int or float or str or list or tuple or dict
The value or set of values to be replaced.
new_value : int or float or str or list or tuple
The new value or set of values to replace the existing ones.
Returns
-------
pd.DataFrame
A dataframe containing the modified dataset with replaced values.
Raises
------
TypeError
- If `replace` is a string, integer, or float, and `new_value` is not a string, integer, or float.
- If `replace` is a list or tuple, and `new_value` is not a string, integer, float, list, or tuple.
- If `replace` is a dictionary, and `new_value` is not specified.
Notes
-----
This method replaces specified values in the dataset. The replacement can be done for a single value, a list of values, or using a dictionary for multiple replacements.
Examples
--------
>>> # Create a supervised learning instance and replace values
>>> data = SupervisedLearning(dataset)
>>>
>>> # Replace a single value
>>> replaced_values = data.replace_values(0, -1)
>>>
>>> # Replace multiple values using a dictionary
>>> replaced_values = data.replace_values({'Male': 1, 'Female': 0})
See Also
--------
- pandas.DataFrame.replace : Replace values in a DataFrame.
- NumPy: https://numpy.org/doc/stable/
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html#imputation
- Matplotlib: https://matplotlib.org/stable/contents.html
References
----------
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html
- NumPy: https://numpy.org/doc/stable/
"""
if isinstance(replace, str) or isinstance(new_value, int) or isinstance(new_value, float):
if isinstance(new_value, str) or isinstance(new_value, int) or isinstance(new_value, float):
self.__data.replace(to_replace = replace, value = new_value, inplace = True)
else:
raise TypeError("If replace is a string, integer, or float, then new value must be either a string, integer, or float.")
elif isinstance(replace, list) or isinstance(replace, tuple):
if isinstance(new_value, str) or isinstance(new_value, int) or isinstance(new_value, float):
self.__data.replace(to_replace = replace, value = new_value, inplace = True)
elif isinstance(new_value, list) or isinstance(new_value, tuple):
for word, new in zip(replace, new_value):
self.__data.replace(to_replace = word, value = new, inplace = True)
else:
raise TypeError("If replace is a list or tuple, then value can be any of int, str, float, list, or tuple.")
elif isinstance(replace, dict):
self.__data.replace(to_replace = replace, value = new_value, inplace = True)
else:
raise TypeError("Check your input arguments for the parameters: replace and new_value")
return self.__data
[docs]
def sort_values(self, column: str or list, ascending: bool = True, reset_index: bool = False):
"""
Sort the dataset based on specified columns.
Parameters
----------
column : str or list
The column(s) to sort the dataset.
ascending : bool, optional
Whether to sort in ascending order. Default is True.
reset_index : bool, optional
Whether to reset the index after sorting. Default is False.
Returns
-------
pd.DataFrame
The dataset sorted according to the specified column or columns.
Examples
--------
>>> # Create a supervised learning instance and sort the dataset
>>> data = SupervisedLearning(dataset)
>>> sorted_data = data.sort_values("column_name",
>>> ascending=False,
>>> reset_index=True)
>>> print(sorted_data)
See Also
--------
- pandas.DataFrame.sort_values
- NumPy: https://numpy.org/doc/stable/
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html#imputation
"""
if isinstance(column, str) or isinstance(column, list):
self.__data.sort_values(by = column, ascending = ascending, ignore_index = reset_index, inplace = True)
return self.__data
[docs]
def set_index(self, column: str or list):
"""
Set the index of the dataset.
Parameters
----------
column : str or list
The column(s) to set as the index.
Returns
-------
pd.DataFrame
The dataset with the index set to the specified column or columns.
Examples
--------
>>> # Create a supervised learning instance and set the index
>>> data = SupervisedLearning(dataset)
>>> index_set_data = data.set_index("column_name")
>>> print(index_set_data)
See Also
--------
- pandas.DataFrame.set_index
- NumPy: https://numpy.org/doc/stable/
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html#imputation
"""
if isinstance(column, str) or isinstance(column, list):
self.__data = self.__data.set_index(column)
return self.__data
[docs]
def sort_index(self, column: str or list, ascending: bool = True, reset_index: bool = False):
"""
Sort the dataset based on the index.
Parameters
----------
column : str or list
The index column(s) to sort the dataset.
ascending : bool, optional
Whether to sort in ascending order. Default is True.
reset_index : bool, optional
Whether to reset the index after sorting. Default is False.
Returns
-------
pd.DataFrame
A dataframe containing the sorted dataset.
Examples
--------
>>> # Create a supervised learning instance and sort the dataset based on index
>>> data = SupervisedLearning(dataset)
>>> sorted_index_data = data.sort_index("index_column",
>>> ascending=False,
>>> reset_index=True)
>>> print(sorted_index_data)
See Also
--------
- pandas.DataFrame.sort_index
- NumPy: https://numpy.org/doc/stable/
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html#imputation
"""
if isinstance(column, str) or isinstance(column, list):
self.__data.sort_index(by = column, ascending = ascending, ignore_index = reset_index, inplace = True)
return self.__data
[docs]
def rename_columns(self, old_column: str or list, new_column: str or list):
"""
Rename columns in the dataset.
Parameters
----------
old_column : str or list
The old column name(s) to be renamed.
new_column : str or list
The new column name(s).
Returns
-------
pd.DataFrame
A dataframe containing the modified dataset with the column name(s) changed.
Examples
--------
>>> # Create a supervised learning instance and rename columns
>>> data = SupervisedLearning(dataset)
>>> renamed_data = data.rename_columns("old_column_name", "new_column_name")
>>> print(renamed_data)
See Also
--------
- pandas.DataFrame.rename_columns
- NumPy: https://numpy.org/doc/stable/
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html#imputation
"""
if isinstance(old_column, str) and isinstance(new_column, str):
self.__data.rename({old_column: new_column}, axis = 1, inplace = True)
elif isinstance(old_column, list) and isinstance(new_column, list):
self.__data.rename({key:value for key, value in zip(old_column, new_column)}, axis = 1, inplace = True)
return self.__data
[docs]
def reset_index(self, drop_index_after_reset: bool = False):
"""
Reset the index of the dataset.
Parameters
----------
drop_index_after_reset : bool, optional
Whether to drop the old index after resetting. Default is False.
Returns
-------
pd.DataFrame
A dataframe containing the modified dataset with the index reset.
Examples
--------
>>> # Create a supervised learning instance and reset the index
>>> data = SupervisedLearning(dataset)
>>> reset_index_data = data.reset_index(drop_index_after_reset=True)
>>> print(reset_index_data)
See Also
--------
- pandas.DataFrame.reset_index
- NumPy: https://numpy.org/doc/stable/
- Scikit-learn: https://scikit-learn.org/stable/modules/preprocessing.html#imputation
"""
self.__data.reset_index(drop = drop_index_after_reset, inplace = True)
return self.__data
[docs]
def filter_data(self, column: str or list or tuple, operation: str or list or tuple = None, value: int or float or str or list or tuple = None):
"""
Filter data based on specified conditions.
Parameters
----------
- column: str or list or tuple
The column or columns to filter.
- operation: str or list or tuple, optional
The operation or list of operations to perform. Supported operations:
'greater than', 'less than', 'equal to', 'greater than or equal to',
'less than or equal to', 'not equal to', '>', '<', '==', '>=', '<=', '!='.
Default is None.
- value: int or float or str or list or tuple, optional
The value or list of values to compare against. Default is None.
Returns
-------
pandas.DataFrame
The filtered DataFrame.
Raises
------
- TypeError: If input parameters are invalid or inconsistent.
Example
-------
>>> # Create a supervised learning instance and sort the dataset
>>> data = SupervisedLearning(dataset)
>>>
>>> # Filter data where 'column' is greater than 5
>>> filter_data = data.filter_data(column='column',
>>> operation='>',
>>> value=5)
>>>
>>> # Filter data where 'column1' is less than or equal to 10 and 'column2' is not equal to 'value'
>>> filter_data = data.filter_data(column=['column1', 'column2'],
>>> operation=['<=', '!='],
>>> value=[10, 'value'])
References
----------
- Pandas library: https://pandas.pydata.org
"""
possible_operations = ['greater than', 'less than', 'equal to', 'greater than or equal to', 'less than or equal to', 'not equal to', '>', '<', '==', '>=', '<=', '!=']
if column != None:
if isinstance(column, str):
if isinstance(value, int) or isinstance(value, float):
if isinstance(operation, str):
if operation.lower() not in possible_operations:
raise TypeError(f"This operation is not supported. Please use the following: {possible_operations}")
elif (operation.lower() == 'greater than' or operation == '>'):
condition = self.__data[column] > value
self.__data = self.__data[condition]
elif (operation.lower() == 'less than' or operation == '<'):
condition = self.__data[column] < value
self.__data = self.__data[condition]
elif (operation.lower() == 'equal to' or operation == '=='):
condition = self.__data[column] == value
self.__data = self.__data[condition]
elif (operation.lower() == 'greater than or equal to' or operation == '>='):
condition = self.__data[column] >= value
self.__data = self.__data[condition]
elif (operation.lower() == 'less than or equal to' or operation == '<='):
condition = self.__data[column] <= value
self.__data = self.__data[condition]
elif (operation.lower() == 'not equal to' or operation == '!='):
condition = self.__data[column] != value
self.__data = self.__data[condition]
elif isinstance(operation, list) or isinstance(operation, int) or isinstance(operation, float) or isinstance(operation, tuple):
raise TypeError("When column is set to string and value is set to either float, int, or string. Operation can not be a list or tuple. Must be set to string")
elif isinstance(value, str):
if (operation.lower() == 'equal to' or operation == '=='):
condition = self.__data[column] == value
self.__data = self.__data[condition]
elif (operation.lower() == 'not equal to' or operation == '!='):
condition = self.__data[column] != value
self.__data = self.__data[condition]
else:
raise TypeError("When value is a string, comparison of greater than or less than cannot be made.")
elif isinstance(value, list) or isinstance(value, tuple):
if isinstance(operation, str):
raise TypeError("Length of values should be same as length of available operations to perform")
elif isinstance(operation, list) or isinstance(operation, tuple):
for item, symbol in zip(value, operation):
if isinstance(item, str):
if (symbol.lower() == 'equal to' or symbol == '=='):
condition = self.__data[column] == item
self.__data = self.__data[condition]
elif (symbol.lower() == 'not equal to' or symbol == '!='):
condition = self.__data[column] != item
self.__data = self.__data[condition]
else:
raise TypeError("When value is a string, comparison of greater than or less than cannot be made.")
elif isinstance(item, int) or isinstance(item, float):
if (symbol.lower() == 'greater than' or symbol == '>'):
condition = self.__data[column] > item
self.__data = self.__data[condition]
elif (symbol.lower() == 'less than' or symbol == '<'):
condition = self.__data[column] < item
self.__data = self.__data[condition]
elif (symbol.lower() == 'equal to' or symbol == '=='):
condition = self.__data[column] == item
self.__data = self.__data[condition]
elif (symbol.lower() == 'greater than or equal to' or symbol == '>='):
condition = self.__data[column] >= item
self.__data = self.__data[condition]
elif (symbol.lower() == 'less than or equal to' or symbol == '<='):
condition = self.__data[column] <= item
self.__data = self.__data[condition]
elif (symbol.lower() == 'not equal to' or symbol == '!='):
condition = self.__data[column] != item
self.__data = self.__data[condition]
elif isinstance(column, list) or isinstance(column, tuple):
if isinstance(value, int) or isinstance(value, float) or isinstance(value, str):
raise TypeError("If column is a list or tuple, then value must assume form of a list or tuple with same length.")
elif (isinstance(value, list) or isinstance(value, tuple)) and (len(value) == len(column)):
if isinstance(operation, str):
for col, item in zip(column, value):
if isinstance(item, str):
if (operation.lower() == 'equal to' or operation == '=='):
condition = self.__data[col] == item
self.__data = self.__data[condition]
elif (operation.lower() == 'not equal to' or operation == '!='):
condition = self.__data[col] != item
self.__data = self.__data[condition]
else:
raise TypeError("When value is a string, comparison of greater than or less than cannot be made. Consider switching operation to a list or tuple for more control.")
elif isinstance(item, int) or isinstance(item, float):
if (operation.lower() == 'greater than' or operation == '>'):
condition = self.__data[col] > item
self.__data = self.__data[condition]
elif (operation.lower() == 'less than' or operation == '<'):
condition = self.__data[col] < item
self.__data = self.__data[condition]
elif (operation.lower() == 'equal to' or operation == '=='):
condition = self.__data[col] == item
self.__data = self.__data[condition]
elif (operation.lower() == 'greater than or equal to' or operation == '>='):
condition = self.__data[col] >= item
self.__data = self.__data[condition]
elif (operation.lower() == 'less than or equal to' or operation == '<='):
condition = self.__data[col] <= item
self.__data = self.__data[condition]
elif (operation.lower() == 'not equal to' or operation == '!='):
condition = self.__data[col] != item
self.__data = self.__data[condition]
elif isinstance(operation, list) or isinstance(operation, tuple):
if len(operation) == len(value) == len(column):
for col, item, symbol in zip(column, value, operation):
if isinstance(item, str):
if (symbol.lower() == 'equal to' or symbol == '=='):
condition = self.__data[col] == item
self.__data = self.__data[condition]
elif (symbol.lower() == 'not equal to' or symbol == '!='):
condition = self.__data[col] != item
self.__data = self.__data[condition]
else:
raise TypeError("When value is a string, comparison of greater than or less than cannot be made.")
elif isinstance(item, int) or isinstance(item, float):
if (symbol.lower() == 'greater than' or symbol == '>'):
condition = self.__data[col] > item
self.__data = self.__data[condition]
elif (symbol.lower() == 'less than' or symbol == '<'):
condition = self.__data[col] < item
self.__data = self.__data[condition]
elif (symbol.lower() == 'equal to' or symbol == '=='):
condition = self.__data[col] == item
self.__data = self.__data[condition]
elif (symbol.lower() == 'greater than or equal to' or symbol == '>='):
condition = self.__data[col] >= item
self.__data = self.__data[condition]
elif (symbol.lower() == 'less than or equal to' or symbol == '<='):
condition = self.__data[col] <= item
self.__data = self.__data[condition]
elif (symbol.lower() == 'not equal to' or symbol == '!='):
condition = self.__data[col] != item
self.__data = self.__data[condition]
else:
raise TypeError("When arguments in column, value, and operation are a list or tuple, they must all have same size.")
elif (isinstance(value, list) or isinstance(value, tuple)) and (len(value) != len(column)):
raise TypeError("The parameters column and value must have the same length when both set to either list or tuple.")
else:
raise TypeError("Column must be either a string, list, tuple, or dictionary.")
elif column == None:
if isinstance(operation, str):
if isinstance(value, int) or isinstance(value, float):
if operation.lower() not in possible_operations:
raise TypeError(f"This operation is not supported. Please use the following: {possible_operations}")
elif (operation.lower() == 'greater than' or operation == '>'):
condition = self.__data > value
self.__data = self.__data[condition]
elif (operation.lower() == 'less than' or operation == '<'):
condition = self.__data < value
self.__data = self.__data[condition]
elif (operation.lower() == 'equal to' or operation == '=='):
condition = self.__data == value
self.__data = self.__data[condition]
elif (operation.lower() == 'greater than or equal to' or operation == '>='):
condition = self.__data >= value
self.__data = self.__data[condition]
elif (operation.lower() == 'less than or equal to' or operation == '<='):
condition = self.__data <= value
self.__data = self.__data[condition]
elif (operation.lower() == 'not equal to' or operation == '!='):
condition = self.__data != value
self.__data = self.__data[condition]
elif isinstance(value, str):
if (operation.lower() == 'equal to' or operation == '=='):
condition = self.__data == value
self.__data = self.__data[condition]
elif (operation.lower() == 'not equal to' or operation == '!='):
condition = self.__data != value
self.__data = self.__data[condition]
else:
raise TypeError("When column is set to NONE and value is a string, comparison of greater than or less than cannot be made.")
elif isinstance(value, list) or isinstance(value, tuple):
raise TypeError("Length of values should be same as length of available operations to perform")
elif isinstance(operation, list) or isinstance(operation, tuple):
if isinstance(value, int) or isinstance(value, float):
raise TypeError("If operation is list or tuple, then value must be list or tuple of same size.")
elif isinstance(value, str):
raise TypeError("If operation is list or tuple, then value must be list or tuple of same size.")
elif (isinstance(value, list) or isinstance(value, tuple)) and (len(value) == len(operation)):
for item, symbol in zip(value, operation):
if isinstance(item, str):
if (symbol.lower() == 'equal to' or symbol == '=='):
condition = self.__data == item
self.__data = self.__data[condition]
elif (symbol.lower() == 'not equal to' or symbol == '!='):
condition = self.__data != item
self.__data = self.__data[condition]
else:
raise TypeError("When value is a string, comparison of greater than or less than cannot be made.")
elif isinstance(item, int) or isinstance(item, float):
if (symbol.lower() == 'greater than' or symbol == '>'):
condition = self.__data > item
self.__data = self.__data[condition]
elif (symbol.lower() == 'less than' or symbol == '<'):
condition = self.__data < item
self.__data = self.__data[condition]
elif (symbol.lower() == 'equal to' or symbol == '=='):
condition = self.__data == item
self.__data = self.__data[condition]
elif (symbol.lower() == 'greater than or equal to' or symbol == '>='):
condition = self.__data >= item
self.__data = self.__data[condition]
elif (symbol.lower() == 'less than or equal to' or symbol == '<='):
condition = self.__data <= item
self.__data = self.__data[condition]
elif (symbol.lower() == 'not equal to' or symbol == '!='):
condition = self.__data != item
self.__data = self.__data[condition]
elif (isinstance(value, list) or isinstance(value, tuple)) and (len(value) != len(operation)):
raise TypeError("If operation is list or tuple, then value must be list or tuple of same size.")
return self.__data
[docs]
def remove_duplicates(self, which_columns: str or list or tuple = None):
"""
Remove duplicate rows from the dataset based on specified columns.
Parameters
----------
which_columns : str or list or tuple, optional
Column(s) to consider when identifying duplicate rows. If specified,
the method will drop rows that have the same values in the specified column(s).
Returns
-------
DataFrame
A new DataFrame with duplicate rows removed.
Raises
------
TypeError
If `which_columns` is not a valid string, list, or tuple.
Notes
-----
- This method removes duplicate rows from the dataset based on the specified column(s).
- If no columns are specified, it considers all columns when identifying duplicates.
Examples
--------
>>> # Create a supervised learning instance and load a dataset
>>> model = SupervisedLearning(dataset)
>>> # Remove duplicate rows based on a specific column
>>> model.remove_duplicates(which_columns='column_name')
See Also
--------
- pandas.DataFrame.drop_duplicates : Drop duplicate rows.
- pandas.DataFrame : Pandas DataFrame class for handling tabular data.
- ydata_profiling : Data profiling library for understanding and analyzing datasets.
- sweetviz : Visualize and compare datasets for exploratory data analysis.
References
----------
- Pandas Documentation: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop_duplicates.html
"""
if isinstance(which_columns, str) or isinstance(which_columns, list) or isinstance(which_columns, tuple):
self.__data.drop_duplicates(inplace = True, subset = which_columns)
else:
raise TypeError("Removing duplicates from your dataset must be done by indicating the column as either a string, list, or tuple.")
return self.__data
[docs]
def select_features(self, strategy: str, estimator, number_of_features: int):
"""
Select features using different techniques.
Parameters
----------
strategy : str
The feature selection strategy. Options include "rfe", "selectkbest",
"selectfrommodel", and "selectpercentile".
estimator :
The estimator or score function used for feature selection.
number_of_features : int
The number of features to select.
Returns
-------
DataFrame or dict
DataFrame with selected features or a dictionary with selected features
and selection metrics.
Raises
------
TypeError
If the strategy or estimator is not recognized.
Notes
-----
- This method allows feature selection using different techniques such as Recursive Feature Elimination (RFE), SelectKBest, SelectFromModel, and SelectPercentile.
Examples
--------
>>> # Create a supervised learning instance and load a dataset
>>> model = SupervisedLearning(dataset)
>>>
>>> # Select features using Recursive Feature Elimination (RFE)
>>> selected_features = model.select_features(strategy='rfe',
>>> estimator=RandomForestRegressor(),
>>> number_of_features=5)
>>>
>>> print(selected_features)
See Also
--------
- sklearn.feature_selection.RFE : Recursive Feature Elimination.
- sklearn.feature_selection.SelectKBest : Select features based on k highest scores.
- sklearn.feature_selection.SelectFromModel : Feature selection using an external estimator.
- sklearn.feature_selection.SelectPercentile : Select features based on a percentile of the highest scores.
References
----------
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectFromModel.html
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectPercentile.html
"""
types = ["rfe", "selectkbest", "selectfrommodel", "selectpercentile"]
rfe_possible_estimator = "A regression or classification algorithm that can implement 'fit'."
kbest_possible_score_functions = ["f_regression", "f_classif", "f_oneway", "chi2"]
frommodel_possible_estimator = "A regression or classification algorithm that can implement 'fit'."
percentile_possible_score_functions = ["f_regression", "f_classif", "f_oneway", "chi2", "mutual_info_classif"]
strategy = strategy.lower()
if strategy in types:
if strategy == "rfe" and estimator != None:
technique = sfs.RFE(estimator = estimator, n_features_to_select = number_of_features)
self.__x = technique.fit_transform(self.__x, self.__y)
self.__x = pd.DataFrame(self.__x, columns = technique.get_feature_names_out())
return self.__x
elif strategy == "selectkbest" and estimator != None:
technique = sfs.SelectKBest(score_func = estimator, k = number_of_features)
self.__x = technique.fit_transform(self.__x, self.__y)
self.__x = pd.DataFrame(self.__x, columns = technique.get_feature_names_out())
best_features = pd.DataFrame({"Features": technique.feature_names_in_, "Scores": technique.scores_, "P_Values": technique.pvalues_})
return {"Dataset ---> Features Selected": self.__x, "Selection Metrics": best_features}
elif strategy == "selectfrommodel" and estimator != None:
technique = sfs.SelectFromModel(estimator = estimator, max_features = number_of_features)
self.__x = technique.fit_transform(self.__x, self.__y)
self.__x = pd.DataFrame(self.__x, columns = technique.get_feature_names_out())
return self.__x
elif strategy == "selectpercentile" and estimator != None:
technique = sfs.SelectPercentile(score_func = estimator, percentile = number_of_features)
self.__x = technique.fit_transform(self.__x, self.__y)
self.__x = pd.DataFrame(self.__x, columns = technique.get_feature_names_out())
best_features = pd.DataFrame({"Features": technique.feature_names_in_, "Scores": technique.scores_, "P_Values": technique.pvalues_})
return {"Dataset ---> Features Selected": self.__x, "Selection Metrics": best_features}
elif estimator == None:
raise TypeError("You must specify an estimator or score function to use feature selection processes")
else:
raise TypeError(f"Select a feature selection technique from the following: {types}. \n\nRFE Estimator = {rfe_possible_estimator} e.g XGBoost, RandomForest, SVM etc\nSelectKBest Score Function = {kbest_possible_score_functions}\nSelectFromModel Estimator = {frommodel_possible_estimator} e.g XGBoost, RandomForest, SVM etc.\nSelectPercentile Score Function = {percentile_possible_score_functions}")
[docs]
def group_data(self, columns: list or tuple, column_to_groupby: str or list or tuple, aggregate_function: str, reset_index: bool = False, inplace: bool = False):
"""
Group data by specified columns and apply an aggregate function.
Parameters
----------
columns : list or tuple
Columns to be grouped and aggregated.
column_to_groupby : str or list or tuple
Column or columns to be used for grouping.
aggregate_function : str
The aggregate function to apply (e.g., 'mean', 'count', 'min', 'max', 'std', 'var', 'median').
reset_index : bool, default False
Whether to reset the index after grouping.
inplace : bool, default False
Replace the original dataset with this groupby operation.
Returns
-------
DataFrame
Grouped and aggregated data.
Raises
------
TypeError
If the column types or aggregate function are not recognized.
Examples
--------
>>> # Create a supervised learning instance and load a dataset
>>> model = SupervisedLearning(dataset)
>>>
>>> # Group data by 'Category' and calculate the mean for 'Value'
>>> grouped_data = model.group_data(columns=['Value'],
>>> column_to_groupby='Category',
>>> aggregate_function='mean')
>>>
>>> print(grouped_data)
See Also
--------
- pandas.DataFrame.groupby : Group DataFrame using a mapper or by a Series of columns.
- pandas.DataFrame.agg : Aggregate using one or more operations over the specified axis.
References
----------
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.agg.html
"""
agg = ["mean", "count", "min", "max", "std", "var", "median"]
if reset_index == False:
if isinstance(columns, list) or isinstance(columns, tuple):
if isinstance(column_to_groupby, str) or isinstance(column_to_groupby, list) or isinstance(column_to_groupby, tuple):
aggregate_function = aggregate_function.lower().strip()
if aggregate_function in agg and isinstance(aggregate_function, str):
if aggregate_function == "mean":
grouped_columns = self.__data[columns].groupby(column_to_groupby).mean()
elif aggregate_function == "count":
grouped_columns = self.__data[columns].groupby(column_to_groupby).count()
elif aggregate_function == "min":
grouped_columns = self.__data[columns].groupby(column_to_groupby).min()
elif aggregate_function == "max":
grouped_columns = self.__data[columns].groupby(column_to_groupby).max()
elif aggregate_function == "std":
grouped_columns = self.__data[columns].groupby(column_to_groupby).std()
elif aggregate_function == "var":
grouped_columns = self.__data[columns].groupby(column_to_groupby).var()
elif aggregate_function == "median":
grouped_columns = self.__data[columns].groupby(column_to_groupby).median()
else:
raise TypeError(f"Specify the right aggregate function from the following: {agg}")
else:
raise TypeError("You need to select more than one column as a list or tuple to perform a groupby operation.")
elif reset_index == True:
if isinstance(columns, list) or isinstance(columns, tuple):
if isinstance(column_to_groupby, str) or isinstance(column_to_groupby, list) or isinstance(column_to_groupby, tuple):
aggregate_function = aggregate_function.lower().strip()
if aggregate_function in agg and isinstance(aggregate_function, str):
if aggregate_function == "mean":
grouped_columns = self.__data[columns].groupby(column_to_groupby).mean()
grouped_columns = grouped_columns.reset_index()
elif aggregate_function == "count":
grouped_columns = self.__data[columns].groupby(column_to_groupby).count()
grouped_columns = grouped_columns.reset_index()
elif aggregate_function == "min":
grouped_columns = self.__data[columns].groupby(column_to_groupby).min()
grouped_columns = grouped_columns.reset_index()
elif aggregate_function == "max":
grouped_columns = self.__data[columns].groupby(column_to_groupby).max()
grouped_columns = grouped_columns.reset_index()
elif aggregate_function == "std":
grouped_columns = self.__data[columns].groupby(column_to_groupby).std()
grouped_columns = grouped_columns.reset_index()
elif aggregate_function == "var":
grouped_columns = self.__data[columns].groupby(column_to_groupby).var()
grouped_columns = grouped_columns.reset_index()
elif aggregate_function == "median":
grouped_columns = self.__data[columns].groupby(column_to_groupby).median()
grouped_columns = grouped_columns.reset_index()
else:
raise TypeError(f"Specify the right aggregate function from the following: {agg}")
else:
raise TypeError("You need to select more than one column as a list or tuple to perform a groupby operation.")
else:
raise TypeError("The arguments for 'reset_index' must be boolean of TRUE or FALSE.")
if inplace == True:
self.__data = grouped_columns
return self.__data
return grouped_columns
[docs]
def count_column_categories(self, column: str or list or tuple, reset_index: bool = False, inplace: bool = False, test_data: bool = False):
"""
Count the occurrences of categories in a categorical column.
Parameters
----------
column : str or list or tuple
Categorical column or columns to count categories.
reset_index : bool, default False
Whether to reset the index after counting.
inplace : bool, default False
Replace the original dataset with this groupby operation.
test_data : bool, default False
Include the categories count for the test data.
Returns
-------
DataFrame
Count of occurrences of each category in the specified column.
Raises
------
TypeError
If the column type is not recognized.
Examples
--------
>>> # Create a supervised learning instance and load a dataset
>>> model = SupervisedLearning(dataset)
>>>
>>> # Count the occurrences of each category in the 'Category' column
>>> category_counts = model.count_column_categories(column='Category')
>>>
>>> print(category_counts)
See Also
--------
- pandas.Series.value_counts : Return a Series containing counts of unique values.
- pandas.DataFrame.reset_index : Reset the index of a DataFrame.
References
----------
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.value_counts.html
- Pandas: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reset_index.html
"""
if self.__split_data == False:
if reset_index == False:
if isinstance(column, str) or isinstance(column, list) or isinstance(column, tuple):
categories_count = self.__data[column].value_counts()
else:
raise TypeError("Column inserted must be a string, list, or tuple.")
elif reset_index == True:
if isinstance(column, str) or isinstance(column, list) or isinstance(column, tuple):
categories_count = self.__data[column].value_counts()
categories_count = categories_count.reset_index()
else:
raise TypeError("Column inserted must be a string, list, or tuple.")
else:
raise TypeError("The arguments for 'reset_index' must be boolean TRUE or FALSE.")
if inplace == True:
self.__data = categories_count
return self.__data
return categories_count
else:
x_train_col = [col for col in self.__x_train.columns]
y_train_col = [self.__y_train.name]
if test_data == False:
if isinstance(column, str):
if column in x_train_col:
categories_count = self.__x_train[column].value_counts()
elif column in y_train_col:
categories_count = self.__y_train.value_counts()
elif isinstance(column, list) or isinstance(column, tuple):
a = set(x_train_col)
b = set(column)
if b.issubset(a):
categories_count = self.__x_train[column].value_counts()
else:
raise TypeError("One or more of the columns specified cannot be found among your independent variables columns (x_train). Also, check that your dependent variable column (y_train) is not among the columns. To get the value counts of the y_train, it must be specified seperately as a string.")
if reset_index == True:
categories_count = categories_count.reset_index()
if inplace == True:
self.__data = categories_count
return self.__data
return categories_count
elif test_data == True:
if isinstance(column, str):
if column in x_train_col:
categories_count_train = self.__x_train[column].value_counts()
categories_count_test = self.__x_test[column].value_counts()
elif column in y_train_col:
categories_count_train = self.__y_train.value_counts()
categories_count_test = self.__y_test.value_counts()
elif isinstance(column, list) or isinstance(column, tuple):
a = set(x_train_col)
b = set(column)
if b.issubset(a):
categories_count_train = self.__x_train[column].value_counts()
categories_count_test = self.__x_test[column].value_counts()
else:
raise TypeError("One or more of the columns specified cannot be found among your independent variables columns (x_train). Also, check that your dependent variable column (y_train) is not among the columns. To get the value counts of the y_train, it must be specified seperately as a string.")
if reset_index == True:
categories_count_train = categories_count_train.reset_index()
categories_count_test = categories_count_test.reset_index()
return {"Training Data": categories_count_train, "Test Data": categories_count_test}
[docs]
def sweetviz_profile_report(self, filename: str = "Pandas Profile Report.html", auto_open: bool = False):
"""
Generate a Sweetviz profile report for the dataset.
Parameters
----------
filename : str, default "Pandas Profile Report.html"
The name of the HTML file to save the Sweetviz report.
auto_open : bool, default False
If True, open the generated HTML report in a web browser.
Returns
-------
None
See Also
--------
- sweetviz.analyze : Generate and analyze a Sweetviz data comparison report.
References
----------
- Sweetviz Documentation: https://github.com/fbdesignpro/sweetviz
"""
report1 = sv.analyze(self.__data)
report1.show_html(filepath = filename, open_browser = auto_open)
[docs]
def pandas_profiling(self, output_file: str = "Pandas Profile Report.html", dark_mode: bool = False, title: str = "Report"):
"""
Generate a Pandas profiling report for the dataset.
Parameters
----------
output_file : str, default "Pandas Profile Report.html"
The name of the HTML file to save the Pandas profiling report.
dark_mode : bool, default False
If True, use a dark mode theme for the generated report.
title : str, default "Report"
The title of the Pandas profiling report.
Returns
-------
None
See Also
--------
- pandas_profiling.ProfileReport : Generate a profile report from a DataFrame.
References
----------
- Pandas Profiling Documentation: https://github.com/pandas-profiling/pandas-profiling
"""
report = pp.ProfileReport(df = self.__data, dark_mode = dark_mode, explorative = True, title = title)
report.to_widgets()
report.to_file(output_file = output_file)
[docs]
def select_datatype(self, datatype_to_select: str = None, datatype_to_exclude: str = None, inplace: bool = False):
"""
Select columns of specific data types from the dataset.
Parameters
----------
datatype_to_select : str, optional
Data type(s) to include. All data types are included by default.
datatype_to_exclude : str, optional
Data type(s) to exclude. None are excluded by default.
inplace : bool, default False
Replace the original dataset with this groupby operation.
Returns
-------
DataFrame
Subset of the dataset containing columns of the specified data types.
See Also
--------
- pandas.DataFrame.select_dtypes : Select columns based on data type.
References
----------
- Pandas Documentation: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.select_dtypes.html
"""
selected_data = self.__data.select_dtypes(include = datatype_to_select, exclude = datatype_to_exclude)
if inplace == True:
self.__data = selected_data
return self.__data
return selected_data
[docs]
def load_large_dataset(self, dataset):
"""
Load a large dataset using the Datatable library.
Parameters
----------
dataset : str
The path or URL of the dataset.
Returns
-------
DataFrame
Pandas DataFrame containing the loaded data.
See Also
--------
- datatable.fread : Read a DataTable from a file.
References
----------
- Datatable Documentation: https://github.com/h2oai/datatable
"""
self.__data = dt.fread(dataset).to_pandas()
return self.__data
[docs]
def reduce_data_memory_useage(self, verbose: bool = True):
"""
Reduce memory usage of the dataset by converting data types.
Parameters
----------
verbose : bool, default True
If True, print information about the memory reduction.
Returns
-------
DataFrame
Pandas DataFrame with reduced memory usage.
See Also
--------
- pandas.DataFrame.memory_usage : Return the memory usage of each column.
References
----------
- NumPy Documentation: https://numpy.org/doc/stable/user/basics.types.html
"""
numerics = ["int8", "int16", "int32", "int64", "float16", "float32", "float64"]
start_mem = self.__data.memory_usage().sum() / 1024 ** 2
for col in self.__data.columns:
col_type = self.__data[col].dtypes
if col_type in numerics:
c_min = self.__data[col].min()
c_max = self.__data[col].max()
if str(col_type)[:3] == "int":
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
self.__data[col] = self.__data[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
self.__data[col] = self.__data[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
self.__data[col] = self.__data[col].astype(np.int32)
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
self.__data[col] = self.__data[col].astype(np.int64)
else:
if (
c_min > np.finfo(np.float16).min
and c_max < np.finfo(np.float16).max
):
self.__data[col] = self.__data[col].astype(np.float16)
elif (
c_min > np.finfo(np.float32).min
and c_max < np.finfo(np.float32).max
):
self.__data[col] = self.__data[col].astype(np.float32)
else:
self.__data[col] = self.__data[col].astype(np.float64)
end_mem = self.__data.memory_usage().sum() / 1024 ** 2
if verbose:
print(
"Mem. usage decreased to {:.2f} Mb ({:.1f}% reduction)".format(
end_mem, 100 * (start_mem - end_mem) / start_mem
)
)
return self.__data
[docs]
def get_bestK_KNNclassifier(self, weight = "uniform", algorithm = "auto", metric = "minkowski", max_k_range: int = 31, figsize: tuple = (15, 10)):
"""
Find the best value of k for K-Nearest Neighbors (KNN) classifier.
Parameters
----------
weight : str, default 'uniform'
Weight function used in prediction. Possible values: 'uniform' or 'distance'.
algorithm : str, default 'auto'
Algorithm used to compute the nearest neighbors. Possible values: 'auto', 'ball_tree', 'kd_tree', 'brute'.
metric : str, default 'minkowski'
Distance metric for the tree. Refer to the documentation of sklearn.neighbors.DistanceMetric for more options.
max_k_range : int, default 31
Maximum range of k values to consider.
figsize: tuple
A tuple containing the frame length and breadth for the graph to be plotted.
Returns
-------
Int
An integer indicating the best k value for the KNN Classifier.
Raises
------
TypeError
If invalid values are provided for 'algorithm' or 'weight'.
Notes
-----
This method evaluates the KNN classifier with different values of k and plots a graph to help identify the best k.
The best k-value is determined based on the highest accuracy score.
Examples
--------
>>> data = SupervisedLearning(dataset)
>>> data.get_bestK_KNNclassifier(weight='distance',
>>> algorithm='kd_tree')
See Also
--------
- sklearn.neighbors.KNeighborsClassifier : K-nearest neighbors classifier.
References
----------
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html
"""
if self.__split_data == True:
algorithms = ['auto', 'ball_tree', 'kd_tree', 'brute']
weights = ['uniform', 'distance']
a = algorithm.lower()
b = weight.lower()
if (a in algorithms) or (b in weights):
k = [num for num in range(1, max_k_range)]
scores_knn = []
scores_store = {}
for num in k:
classifier = sn.KNeighborsClassifier(n_neighbors = num, weights = weight, algorithm = algorithm, metric = metric)
model = classifier.fit(self.__x_train, self.__y_train)
# Model Evaluation
scores_knn.append(model.score(self.__x_train, self.__y_train))
scores_store[num] = (model.score(self.__x_train, self.__y_train))
# Plotting a graph
plt.figure(figsize = figsize)
plt.plot(k, scores_knn)
plt.title('KNN graph for values of K and their scores')
plt.xlabel('Ranges of K values')
plt.ylabel('Scores')
plt.show()
# Getting the best score
b = (0, 0)
for key, value in scores_store.items():
if value > b[1]:
b = (key, value)
print(f'\n\nKNN CLASSIFIER ------> Finding the besk K value:\nThe best k-value is {b[0]} with a score of {b[1]}.')
else:
raise TypeError(f"Check that the parameter 'algorithm' is one of the following: {algorithms}. Also, check that the parameter 'weight' is one of the following: {weights}")
return b[0]
else:
algorithms = ['auto', 'ball_tree', 'kd_tree', 'brute']
weights = ['uniform', 'distance']
a = algorithm.lower()
b = weight.lower()
if (a in algorithms) or (b in weights):
k = [num for num in range(1, max_k_range)]
scores_knn = []
scores_store = {}
for num in k:
classifier = sn.KNeighborsClassifier(n_neighbors = num, weights = weight, algorithm = algorithm, metric = metric)
model = classifier.fit(self.__x, self.__y)
# Model Evaluation
scores_knn.append(model.score(self.__x, self.__y))
scores_store[num] = (model.score(self.__x, self.__y))
# Plotting a graph
plt.figure(figsize = figsize)
plt.plot(k, scores_knn)
plt.title('KNN graph for values of K and their scores')
plt.xlabel('Ranges of K values')
plt.ylabel('Scores')
plt.show()
# Getting the best score
b = (0, 0)
for key, value in scores_store.items():
if value > b[1]:
b = (key, value)
print(f'\n\nKNN CLASSIFIER ------> Finding the besk K value:\nThe best k-value is {b[0]} with a score of {b[1]}.')
else:
raise TypeError(f"Check that the parameter 'algorithm' is one of the following: {algorithms}. Also, check that the parameter 'weight' is one of the following: {weights}")
return b[0]
[docs]
def get_bestK_KNNregressor(self, weight = "uniform", algorithm = "auto", metric = "minkowski", max_k_range: int = 31, figsize: tuple = (15, 10)):
"""
Find the best value of k for K-Nearest Neighbors (KNN) regressor.
Parameters
----------
weight : str, default 'uniform'
Weight function used in prediction. Possible values: 'uniform' or 'distance'.
algorithm : str, default 'auto'
Algorithm used to compute the nearest neighbors. Possible values: 'auto', 'ball_tree', 'kd_tree', 'brute'.
metric : str, default 'minkowski'
Distance metric for the tree. Refer to the documentation of sklearn.neighbors.DistanceMetric for more options.
max_k_range : int, default 31
Maximum range of k values to consider.
figsize: tuple
A tuple containing the frame length and breadth for the graph to be plotted.
Returns
-------
Int
An integer indicating the best k value for the KNN Regressor.
Raises
------
TypeError
If invalid values are provided for 'algorithm' or 'weight'.
Notes
-----
This method evaluates the KNN regressor with different values of k and plots a graph to help identify the best k.
The best k-value is determined based on the highest R-squared score.
Examples
--------
>>> data = SupervisedLearning(dataset)
>>> data.get_bestK_KNNregressor(weight='distance', algorithm='kd_tree')
See Also
--------
- sklearn.neighbors.KNeighborsRegressor : K-nearest neighbors regressor.
References
----------
- Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsRegressor.html
"""
if self.__split_data == True:
algorithms = ['auto', 'ball_tree', 'kd_tree', 'brute']
weights = ['uniform', 'distance']
a = algorithm.lower()
b = weight.lower()
if (a in algorithms) or (b in weights):
k = [num for num in range(1, max_k_range)]
scores_knn = []
scores_store = {}
for num in k:
regressor = sn.KNeighborsRegressor(n_neighbors = num, weights = weight, algorithm = algorithm, metric = metric)
model = regressor.fit(self.__x_train, self.__y_train)
# Model Evaluation
scores_knn.append(model.score(self.__x_train, self.__y_train))
scores_store[num] = (model.score(self.__x_train, self.__y_train))
# Plotting a graph
plt.figure(figsize = figsize)
plt.plot(k, scores_knn)
plt.title('KNN graph for values of K and their scores')
plt.xlabel('Ranges of K values')
plt.ylabel('Scores')
plt.show()
# Getting the best score
b = (0, 0)
for key, value in scores_store.items():
if value > b[1]:
b = (key, value)
print(f'\n\nKNN Regressor ------> Finding the besk K value:\nThe best k-value is {b[0]} with a score of {b[1]}.')
else:
raise TypeError(f"Check that the parameter 'algorithm' is one of the following: {algorithms}. Also, check that the parameter 'weight' is one of the following: {weights}")
return b[0]
else:
algorithms = ['auto', 'ball_tree', 'kd_tree', 'brute']
weights = ['uniform', 'distance']
a = algorithm.lower()
b = weight.lower()
if (a in algorithms) or (b in weights):
k = [num for num in range(1, max_k_range)]
scores_knn = []
scores_store = {}
for num in k:
regressor = sn.KNeighborsRegressor(n_neighbors = num, weights = weight, algorithm = algorithm, metric = metric)
model = regressor.fit(self.__x, self.__y)
# Model Evaluation
scores_knn.append(model.score(self.__x, self.__y))
scores_store[num] = (model.score(self.__x, self.__y))
# Plotting a graph
plt.figure(figsize = figsize)
plt.plot(k, scores_knn)
plt.title('KNN graph for values of K and their scores')
plt.xlabel('Ranges of K values')
plt.ylabel('Scores')
plt.show()
# Getting the best score
b = (0, 0)
for key, value in scores_store.items():
if value > b[1]:
b = (key, value)
print(f'\n\nKNN Regressor ------> Finding the besk K value:\nThe best k-value is {b[0]} with a score of {b[1]}.')
else:
raise TypeError(f"Check that the parameter 'algorithm' is one of the following: {algorithms}. Also, check that the parameter 'weight' is one of the following: {weights}")
return b[0]
[docs]
def unique_elements_in_columns(self, count: bool = False):
"""
Extracts unique elements in each column of the dataset.
This method generates a DataFrame containing unique elements in each column. If specified, it can also provide the count of unique elements in each column.
Parameters
----------
count : bool, optional, default=False
If True, returns the count of unique elements in each column.
Returns
-------
pd.DataFrame or pd.Series
If count is False, a DataFrame with unique elements. If count is True, a Series with counts.
Notes
-----
This method utilizes Pandas for extracting unique elements and their counts.
Examples
--------
>>> from buildml import SupervisedLearning
>>> model = SupervisedLearning(dataset)
>>> unique_elements = model.unique_elements_in_columns(count=True)
References
----------
- Pandas unique: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.unique.html
- Pandas nunique: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.nunique.html
"""
column = [col for col in self.__data.columns]
dataframe = pd.DataFrame()
for element in column:
data = self.__data[element].unique()
data = pd.Series(data, name = element)
dataframe = pd.concat([dataframe, data], axis = 1)
if count == True:
dataframe = dataframe.nunique()
return dataframe
[docs]
def simple_linregres_graph(self, regressor, title: str, xlabel: str, ylabel: str, figsize: tuple = (15, 10), line_style: str = "dashed", line_width: float = 2, line_marker: str = "o", line_marker_size: float = 12, train_color_marker: str = "red", test_color_marker: str = "red", line_color: str = "green", size_train_marker: float = 10, size_test_marker: float = 10, whole_dataset: bool = False):
"""
Generate a simple linear regression graph with optional visualization of training and test datasets.
Parameters:
-----------
regressor (object or list):
Single or list of regression models (e.g., sklearn.linear_model.LinearRegression) to visualize.
title (str):
Title of the graph.
xlabel : str
A title for the xaxis.
ylabel : str
A title for the yaxis.
figsize : str, optional, default: (15, 10)
The size(length, breadth) of the figure frame where we plot our graph.
line_style : str, optional, default: "dashed"
Style of the regression line ("solid", "dashed", "dashdot", etc.).
line_width (float, optional):
Width of the regression line. Default is 2.
line_marker (str, optional):
Marker style for data points on the regression line. Default is "o".
line_marker_size (float, optional):
Size of the marker for data points on the regression line. Default is 12.
train_color_marker (str, optional):
Color of markers for the training dataset. Default is "red".
test_color_marker (str, optional):
Color of markers for the test dataset. Default is "red".
line_color (str, optional):
Color of the regression line. Default is "green".
size_train_marker (float, optional):
Size of markers for the training dataset. Default is 10.
size_test_marker (float, optional):
Size of markers for the test dataset. Default is 10.
whole_dataset (bool, optional):
If True, visualize the entire dataset with the regression line. If False, visualize training and test datasets separately. Default is False.
Returns:
--------
None
Displays a simple linear regression graph.
Examples:
---------
>>> # Example 1: Visualize a simple linear regression model
>>> model.simple_linregres_graph(regressor=LinearRegression(),
title="Simple Linear Regression",
xlabel="Specify your title for xaxis",
ylabel="Specify your title for yaxis")
>>> # Example 2: Visualize multiple linear regression models
>>> regressors = [LinearRegression(), Ridge(), Lasso()]
>>> model.simple_linregres_graph(regressor=regressors,
title="Analyzing Impact of Expenditure on Growth",
xlabel="Expenditure",
ylabel="Growth")
References:
-----------
- `matplotlib.pyplot`: Matplotlib's plotting interface. [Matplotlib Documentation](https://matplotlib.org/stable/contents.html)
- `scikit-learn`: Scikit-learn for machine learning tools. [Scikit-learn Documentation](https://scikit-learn.org/stable/documentation.html)
- `numpy`: NumPy for numerical operations. [NumPy Documentation](https://numpy.org/doc/stable/)
- `pandas`: Pandas for data manipulation. [Pandas Documentation](https://pandas.pydata.org/pandas-docs/stable/index.html)
- `matplotlib`: Matplotlib library for plotting. [Matplotlib Documentation](https://matplotlib.org/stable/contents.html)
"""
name_x = [col for col in self.__x.columns]
if not (isinstance(regressor, list) or isinstance(regressor, tuple)):
if len(name_x) == 1:
if not whole_dataset:
# Visualising the Training set results
plt.figure(figsize = figsize)
plt.scatter(self.__x_train, self.__y_train, color = train_color_marker, s=size_train_marker)
plt.plot(self.__x_train, self.model_regressor.predict(self.__x_train), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} (Training Dataset)")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
# Visualising the Test set results
plt.figure(figsize = figsize)
plt.scatter(self.__x_test, self.__y_test, color = test_color_marker, s=size_test_marker)
plt.plot(self.__x_train, self.model_regressor.predict(self.__x_train), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} (Test Dataset)")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
else:
plt.figure(figsize = figsize)
plt.scatter(self.__x, self.__y, color = train_color_marker, s=size_train_marker)
plt.plot(self.__x, self.model_regressor.predict(self.__x), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(title)
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
else:
raise TypeError("Simple Linear Regression involves only one independent variable. Ensure that your dataframe for x has just one column.")
else:
for each_regressor in regressor:
if len(name_x) == 1:
if not whole_dataset:
# Visualising the Training set results
plt.figure(figsize = figsize)
plt.scatter(self.__x_train, self.__y_train, color = train_color_marker, s=size_train_marker)
plt.plot(self.__x_train, each_regressor.fit(self.__x_train, self.__y_train).predict(self.__x_train), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} (Training Dataset) for {each_regressor.__class__.__name__}")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
# Visualising the Test set results
plt.figure(figsize = figsize)
plt.scatter(self.__x_test, self.__y_test, color = test_color_marker, s=size_test_marker)
plt.plot(self.__x_train, each_regressor.fit(self.__x_train, self.__y_train).predict(self.__x_train), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} (Test Dataset) for {each_regressor.__class__.__name__}")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
else:
plt.figure(figsize = figsize)
plt.scatter(self.__x, self.__y, color = train_color_marker, s=size_train_marker)
plt.plot(self.__x, each_regressor.fit(self.__x, self.__y).predict(self.__x), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} for {each_regressor.__class__.__name__}")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
else:
raise TypeError("Simple Linear Regression involves only one independent variable. Ensure that your dataframe for x has just one column.")
[docs]
def polyreg_graph(self, title: str, xlabel: str, ylabel: str, figsize: tuple = (15, 10), line_style: str = "dashed", line_width: float = 2, line_marker: str = "o", line_marker_size: float = 12, train_color_marker: str = "red", test_color_marker: str = "red", line_color: str = "green", size_train_marker: float = 10, size_test_marker: float = 10, whole_dataset: bool = False):
"""
Generate a polynomial regression graph for visualization.
Parameters
----------
title : str
The title of the graph.
xlabel : str
A title for the xaxis.
ylabel : str
A title for the yaxis.
figsize : str, optional, default: (15, 10)
The size(length, breadth) of the figure frame where we plot our graph.
line_style : str, optional, default: "dashed"
Style of the regression line ("solid", "dashed", "dashdot", etc.).
line_width : float, optional, default: 2
Width of the regression line.
line_marker : str, optional, default: "o"
Marker style for data points on the regression line.
line_marker_size : float, optional, default: 12
Size of the marker on the regression line.
train_color_marker : str, optional, default: "red"
Color of markers for training data.
test_color_marker : str, optional, default: "red"
Color of markers for test data.
line_color : str, optional, default: "green"
Color of the regression line.
size_train_marker : float, optional, default: 10
Size of markers for training data.
size_test_marker : float, optional, default: 10
Size of markers for test data.
whole_dataset : bool, optional, default: False
If True, visualize the regression line on the entire dataset.
If False, visualize on training and test datasets separately.
Returns
-------
None
Displays the polynomial regression graph.
See Also
--------
- `matplotlib.pyplot.scatter`: Plot a scatter plot using Matplotlib.
- `matplotlib.pyplot.plot`: Plot lines and/or markers using Matplotlib.
- `numpy`: Fundamental package for scientific computing with Python.
- `scikit-learn`: Simple and efficient tools for predictive data analysis.
Example
-------
>>> import pandas as pd
>>> import numpy as np
>>> from buildml import SupervisedLearning
>>> from sklearn.linear_model import LinearRegression
>>>
>>> # Get the Dataset
>>> dataset = pd.read_csv("Your dataset/path")
>>>
>>> # Assuming `automate` is an instance of the SupervisedLearning class
>>> automate = SupervisedLearning(dataset)
>>> regressor = LinearRegression()
>>>
>>> # Further Data Preparation and Segregation
>>> select_variables = automate.select_dependent_and_independent(predict = "Salary")
>>> poly_x = automate.polyreg_x(degree = 5)
>>>
>>> # Model Building
>>> training = automate.train_model_regressor(regressor)
>>> prediction = automate.regressor_predict()
>>> evaluation = automate.regressor_evaluation()
>>> poly_reg = automate.polyreg_graph(title = "Analyzing salary across different levels",
>>> xlabel = "Levels",
>>> ylabel = "Salary",
>>> whole_dataset = True,
>>> line_marker = None,
>>> line_style = "solid")
"""
model = self.model_regressor
if not whole_dataset:
# Visualising the Training set results
plt.figure(figsize = figsize)
plt.scatter(self.__x_train1, self.__y_train, color = train_color_marker, s=size_train_marker)
plt.plot(self.__x_train1, model.predict(self.__x_train), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} (Training Dataset)")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
# Visualising the Test set results
plt.figure(figsize = figsize)
plt.scatter(self.__x_test1, self.__y_test, color = test_color_marker, s=size_test_marker)
plt.plot(self.__x_test1, model.predict(self.__x_test), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.title(f"{title} (Test Dataset)")
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
else:
plt.figure(figsize = figsize)
plt.title(title)
plt.scatter(self.__x1, self.__y, color = train_color_marker, s=size_train_marker)
plt.plot(self.__x1, model.predict(self.__x), color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_marker_size)
plt.xlabel(f"{xlabel}")
plt.ylabel(f"{ylabel}")
plt.show()
[docs]
def polyreg_x(self, degree: int, include_bias: bool = False):
"""
Polynomial Regression Feature Expansion.
This method performs polynomial regression feature expansion on the independent variables (features).
It uses scikit-learn's PolynomialFeatures to generate polynomial and interaction features up to a specified degree.
Parameters
----------
degree : int
The degree of the polynomial features.
include_bias : bool, optional, default=False
If True, the polynomial features include a bias column (intercept).
Returns
-------
pd.DataFrame
DataFrame with polynomial features.
Notes
-----
This method utilizes scikit-learn's PolynomialFeatures for feature expansion.
Examples
--------
>>> from buildml import SupervisedLearning
>>> model = SupervisedLearning(dataset)
>>> model.polyreg_x(degree=2, include_bias=True)
References
----------
- Scikit-learn PolynomialFeatures: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html
- Numpy: https://numpy.org/
- Pandas: https://pandas.pydata.org/
- Scikit-learn: https://scikit-learn.org/
"""
self.__poly_features = sp.PolynomialFeatures(degree = degree, include_bias = include_bias)
poly_x = self.__poly_features.fit_transform(self.__x)
_, b = poly_x.shape
column = [f"x{num}" for num in range(1, (b + 1))]
self.__poly_x = pd.DataFrame(poly_x, columns = column)
self.__x1 = self.__x
self.__polynomial_regression = True
self.__x = self.__poly_x
return self.__x
[docs]
def poly_get_optimal_degree(self, max_degree: int = 10, whole_dataset: bool = False, test_size: float = 0.2, random_state: int = 0, include_bias: bool = True, cross_validation: bool = False, kfold: int = 5):
"""
This method is designed to determine the optimal degree for polynomial regression. It evaluates the performance of polynomial regression models with degrees ranging from 1 to a specified maximum degree. The evaluation includes training and testing the models, as well as optional cross-validation metrics.
Parameters
----------
max_degree : int, optional, default=10
The maximum degree of the polynomial to evaluate.
whole_dataset : bool, optional, default=False
If True, the model is trained on the entire dataset without splitting into training and testing sets.
test_size : float, optional, default=0.2
The proportion of the dataset to include in the test split if not using the entire dataset.
random_state : int, optional, default=0
Seed for the random number generator.
include_bias : bool, optional, default=True
Whether to include a bias column in the polynomial features.
cross_validation : bool, optional, default=False
If True, includes cross-validation metrics in the output.
kfold : int, optional, default=5
Number of folds for cross-validation.
Returns
----------
- If cross_validation is False:
DataFrame: A DataFrame containing metrics for each degree, including training R2, training RMSE, test R2, and test RMSE.
- If cross_validation is True:
Dictionary: A dictionary containing two keys:
- "Degree Metrics": A DataFrame with metrics for each degree, including training R2, training RMSE, test R2, test RMSE, cross-validation mean, and cross-validation standard deviation.
- "Cross Validation Info": An array containing cross-validation scores.
Example
-------
>>> # Import Libraries
>>> import pandas as pd
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from buildml import SupervisedLearning
>>>
>>> # Get the Dataset
>>> dataset = pd.read_csv("Your dataset")
>>>
>>> # Using BuildML
>>> automate = SupervisedLearning(data)
>>>
>>> # EDA
>>> eda = automate.eda()
>>>
>>> # Further Data Preparation and Segregation
>>> select_variables = automate.select_dependent_and_independent(predict = "Salary")
>>> best_degree = automate.poly_get_optimal_degree(max_degree=5,
>>> whole_dataset=False,
>>> test_size=0.2,
>>> random_state=42,
>>> include_bias=True,
>>> cross_validation=True)
Notes
-----
- Cross-validation scores are only available in the output when cross_validation is True.
- This method uses polynomial regression models and linear regression as the base algorithm.
- The output provides insights into model performance with various degrees, aiding in selecting the optimal degree for polynomial regression.
"""
x = self.__x
y = self.__y
if cross_validation is False:
data = []
regressor = slm.LinearRegression()
if not whole_dataset:
for num in range(1, (max_degree + 1)):
info = []
poly_features = sp.PolynomialFeatures(degree = num, include_bias = include_bias)
poly_x = poly_features.fit_transform(x)
x_train, x_test, y_train, y_test = sms.train_test_split(poly_x, y, test_size = test_size, random_state = random_state)
# Model Training
model = regressor.fit(x_train, y_train)
# Model Prediction
y_pred = model.predict(x_train)
y_pred1 = model.predict(x_test)
# Model Evaluation
train_r2 = sm.r2_score(y_train, y_pred)
train_rmse = np.sqrt(sm.mean_squared_error(y_train, y_pred))
test_r2 = sm.r2_score(y_test, y_pred1)
test_rmse = np.sqrt(sm.mean_squared_error(y_test, y_pred1))
info.append(num)
info.append(regressor.__class__.__name__)
info.append(train_r2)
info.append(train_rmse)
info.append(test_r2)
info.append(test_rmse)
data.append(info)
data = pd.DataFrame(data, columns = ["Degree", "Base Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE"])
else:
for num in range(1, (max_degree + 1)):
info = []
poly_features = sp.PolynomialFeatures(degree = num, include_bias = include_bias)
poly_x = poly_features.fit_transform(x)
# Model Training
model = regressor.fit(poly_x, y)
# Model Prediction
y_pred = model.predict(poly_x)
# Model Evaluation
r2 = sm.r2_score(y, y_pred)
rmse = np.sqrt(sm.mean_squared_error(y, y_pred))
info.append(num)
info.append(regressor.__class__.__name__)
info.append(r2)
info.append(rmse)
data.append(info)
data = pd.DataFrame(data, columns = ["Degree", "Base Algorithm", "R-Squared", "RMSE"])
return data
else:
data = []
regressor = slm.LinearRegression()
if not whole_dataset:
for num in range(1, (max_degree + 1)):
info = []
poly_features = sp.PolynomialFeatures(degree = num, include_bias = include_bias)
poly_x = poly_features.fit_transform(x)
x_train, x_test, y_train, y_test = sms.train_test_split(poly_x, y, test_size = test_size, random_state = random_state)
# Model Training
model = regressor.fit(x_train, y_train)
# Model Prediction
y_pred = model.predict(x_train)
y_pred1 = model.predict(x_test)
# Model Evaluation
train_r2 = sm.r2_score(y_train, y_pred)
train_rmse = np.sqrt(sm.mean_squared_error(y_train, y_pred))
test_r2 = sm.r2_score(y_test, y_pred1)
test_rmse = np.sqrt(sm.mean_squared_error(y_test, y_pred1))
cross_validation = sms.cross_val_score(estimator = regressor, X = x, y = y, cv = kfold)
cross_val_mean = np.mean(cross_validation)
cross_val_standard_deviation = np.std(cross_validation)
info.append(num)
info.append(regressor.__class__.__name__)
info.append(train_r2)
info.append(train_rmse)
info.append(test_r2)
info.append(test_rmse)
info.append(cross_val_mean)
info.append(cross_val_standard_deviation)
data.append(info)
data = pd.DataFrame(data, columns = ["Degree", "Base Algorithm", "Training R2", "Training RMSE", "Test R2", "Test RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
else:
for num in range(1, (max_degree + 1)):
info = []
poly_features = sp.PolynomialFeatures(degree = num, include_bias = include_bias)
poly_x = poly_features.fit_transform(x)
# Model Training
model = regressor.fit(poly_x, y)
# Model Prediction
y_pred = model.predict(poly_x)
# Model Evaluation
r2 = sm.r2_score(y, y_pred)
rmse = np.sqrt(sm.mean_squared_error(y, y_pred))
cross_validation = sms.cross_val_score(estimator = regressor, X = x, y = y, cv = kfold)
cross_val_mean = np.mean(cross_validation)
cross_val_standard_deviation = np.std(cross_validation)
info.append(num)
info.append(regressor.__class__.__name__)
info.append(r2)
info.append(rmse)
info.append(cross_val_mean)
info.append(cross_val_standard_deviation)
data.append(info)
data = pd.DataFrame(data, columns = ["Degree", "Base Algorithm", "R-Squared", "RMSE", "Cross Validation Mean", "Cross Validation Standard Deviation"])
return {"Degree Metrics": data, "Cross Validation Info": cross_validation}