{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Library Tutorial\n", "\n", "## The Journey to Building the Best Classifier: A Regular Story" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It was an overcast Wednesday morning when Alex decided to tackle a classification challenge. Armed with the `sklearn` datasets and a toolbox of custom Python functions from the `classifierpromax` package, Alex set out to build the best possible model to classify data efficiently and effectively." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from classifierpromax.ClassifierTrainer import ClassifierTrainer\n", "from classifierpromax.ClassifierOptimizer import ClassifierOptimizer\n", "from classifierpromax.FeatureSelector import FeatureSelector\n", "from classifierpromax.ResultHandler import ResultHandler\n", "from sklearn.pipeline import make_pipeline\n", "from sklearn.preprocessing import StandardScaler\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import classification_report\n", "from sklearn import datasets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loading the Dataset\n", "Alex started by loading a familiar dataset from `sklearn`. For this project, the Iris dataset served as the training grounds—a well-known dataset for classifying different types of iris flowers." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)0
905.52.64.41.21
294.73.21.60.20
656.73.14.41.41
825.82.73.91.21
1357.73.06.12.32
..................
304.83.11.60.20
795.72.63.51.01
195.13.81.50.30
535.52.34.01.31
876.32.34.41.31
\n", "

75 rows × 5 columns

\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \\\n", "90 5.5 2.6 4.4 1.2 \n", "29 4.7 3.2 1.6 0.2 \n", "65 6.7 3.1 4.4 1.4 \n", "82 5.8 2.7 3.9 1.2 \n", "135 7.7 3.0 6.1 2.3 \n", ".. ... ... ... ... \n", "30 4.8 3.1 1.6 0.2 \n", "79 5.7 2.6 3.5 1.0 \n", "19 5.1 3.8 1.5 0.3 \n", "53 5.5 2.3 4.0 1.3 \n", "87 6.3 2.3 4.4 1.3 \n", "\n", " 0 \n", "90 1 \n", "29 0 \n", "65 1 \n", "82 1 \n", "135 2 \n", ".. .. \n", "30 0 \n", "79 1 \n", "19 0 \n", "53 1 \n", "87 1 \n", "\n", "[75 rows x 5 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Load the dataset\n", "iris = datasets.load_iris()\n", "X, y = pd.DataFrame(iris.data, columns=iris.feature_names), pd.Series(iris.target)\n", "\n", "# Split the data\n", "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=421)\n", "pd.concat([X_train, y_train], axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With the data ready, Alex built a preprocessing pipeline to ensure the input features were standardized." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Preprocessing pipeline\n", "preprocessor = make_pipeline(StandardScaler())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Training the Initial Models\n", "The first step in Alex’s workflow was training baseline models using the `ClassifierTrainer` function. This function automatically trained several models, including Logistic Regression, SVC, and Random Forest, and evaluated them using cross-validation metrics." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
dummylogregsvcrandom_forest
meanstdmeanstdmeanstdmeanstd
fit_time0.0021101.164137e-030.0018350.0005620.0010430.0000730.0373020.000230
score_time0.0052872.824569e-030.0026060.0003030.0023210.0000790.0041440.000036
test_accuracy0.3333330.000000e+000.9333330.0816500.9466670.0557770.9333330.047140
train_accuracy0.3466677.453560e-030.9533330.0139440.9666670.0204121.0000000.000000
test_precision0.1111111.551584e-170.9393330.0795880.9511110.0547720.9480630.033914
train_precision0.1202225.093266e-030.9535690.0138770.9675080.0196371.0000000.000000
test_recall0.3333330.000000e+000.9333330.0816500.9466670.0557770.9333330.047140
train_recall0.3466677.453560e-030.9533330.0139440.9666670.0204121.0000000.000000
test_f10.1666670.000000e+000.9329290.0824770.9463970.0558590.9320880.049128
train_f10.1785196.625387e-030.9532960.0139560.9666210.0204681.0000000.000000
\n", "
" ], "text/plain": [ " dummy logreg svc \\\n", " mean std mean std mean \n", "fit_time 0.002110 1.164137e-03 0.001835 0.000562 0.001043 \n", "score_time 0.005287 2.824569e-03 0.002606 0.000303 0.002321 \n", "test_accuracy 0.333333 0.000000e+00 0.933333 0.081650 0.946667 \n", "train_accuracy 0.346667 7.453560e-03 0.953333 0.013944 0.966667 \n", "test_precision 0.111111 1.551584e-17 0.939333 0.079588 0.951111 \n", "train_precision 0.120222 5.093266e-03 0.953569 0.013877 0.967508 \n", "test_recall 0.333333 0.000000e+00 0.933333 0.081650 0.946667 \n", "train_recall 0.346667 7.453560e-03 0.953333 0.013944 0.966667 \n", "test_f1 0.166667 0.000000e+00 0.932929 0.082477 0.946397 \n", "train_f1 0.178519 6.625387e-03 0.953296 0.013956 0.966621 \n", "\n", " random_forest \n", " std mean std \n", "fit_time 0.000073 0.037302 0.000230 \n", "score_time 0.000079 0.004144 0.000036 \n", "test_accuracy 0.055777 0.933333 0.047140 \n", "train_accuracy 0.020412 1.000000 0.000000 \n", "test_precision 0.054772 0.948063 0.033914 \n", "train_precision 0.019637 1.000000 0.000000 \n", "test_recall 0.055777 0.933333 0.047140 \n", "train_recall 0.020412 1.000000 0.000000 \n", "test_f1 0.055859 0.932088 0.049128 \n", "train_f1 0.020468 1.000000 0.000000 " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "trained_models, initial_scores = ClassifierTrainer(preprocessor, X_train, y_train, seed=421)\n", "ResultHandler(initial_scores)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As Alex examined the results, they noticed that Random Forest showed promise, but its performance could likely improve with feature selection and hyperparameter tuning." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Selecting Features for Simplicity\n", "With a sense that the dataset contained redundant features, Alex decided to use the `FeatureSelector` function to refine the models further. They opted for **Recursive Feature Elimination (RFE)** to identify and select the most informative features." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "feature_selected_models = FeatureSelector(\n", " preprocessor, trained_models, X_train, y_train, method='RFE', n_features_to_select=2\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now equipped with models that only used the top two features, Alex could already see improvements in simplicity and interpretability. But there was one final step to maximize the models’ potential." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Optimizing Model Hyperparameters\n", "The models were performing well, but Alex wanted them to be great. Enter the `ClassifierOptimizer` function. This function searched for the best hyperparameters using `RandomizedSearchCV`, tuning each model to its optimal configuration." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Training logreg...\n", "\n", "Training svc...\n", "\n", "Training random_forest...\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
logregsvcrandom_forest
meanstdmeanstdmeanstd
fit_time0.0044570.0008200.0024090.0000610.1296780.000447
score_time0.0026870.0001490.0025880.0000710.0032580.000093
test_accuracy0.9466670.0557770.9466670.0557770.9333330.047140
train_accuracy0.9500000.0117850.9533330.0074541.0000000.000000
test_precision0.9591750.0408280.9515560.0547140.9480630.033914
train_precision0.9504750.0117930.9539270.0071231.0000000.000000
test_recall0.9466670.0557770.9466670.0557770.9333330.047140
train_recall0.9500000.0117850.9533330.0074541.0000000.000000
test_f10.9455560.0577900.9466670.0557790.9320880.049128
train_f10.9500060.0117850.9533210.0074611.0000000.000000
\n", "
" ], "text/plain": [ " logreg svc random_forest \\\n", " mean std mean std mean \n", "fit_time 0.004457 0.000820 0.002409 0.000061 0.129678 \n", "score_time 0.002687 0.000149 0.002588 0.000071 0.003258 \n", "test_accuracy 0.946667 0.055777 0.946667 0.055777 0.933333 \n", "train_accuracy 0.950000 0.011785 0.953333 0.007454 1.000000 \n", "test_precision 0.959175 0.040828 0.951556 0.054714 0.948063 \n", "train_precision 0.950475 0.011793 0.953927 0.007123 1.000000 \n", "test_recall 0.946667 0.055777 0.946667 0.055777 0.933333 \n", "train_recall 0.950000 0.011785 0.953333 0.007454 1.000000 \n", "test_f1 0.945556 0.057790 0.946667 0.055779 0.932088 \n", "train_f1 0.950006 0.011785 0.953321 0.007461 1.000000 \n", "\n", " \n", " std \n", "fit_time 0.000447 \n", "score_time 0.000093 \n", "test_accuracy 0.047140 \n", "train_accuracy 0.000000 \n", "test_precision 0.033914 \n", "train_precision 0.000000 \n", "test_recall 0.047140 \n", "train_recall 0.000000 \n", "test_f1 0.049128 \n", "train_f1 0.000000 " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "optimized_models, optimized_scores = ClassifierOptimizer(\n", " feature_selected_models, X_train, y_train, scoring='f1', n_iter=10, random_state=421\n", ")\n", "ResultHandler(optimized_scores)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After a few minutes of computation, the function returned the optimized models and their performance metrics. Alex was thrilled to see that the Random Forest classifier now had the best F1 score among all models.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summarizing the Results\n", "To present the results clearly, Alex used the `ResultHandler` function to compile the performance metrics and hyperparameters into a tidy DataFrame." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
dummy_baselinelogreg_baselinelogreg_optimizedrandom_forest_baselinerandom_forest_optimizedsvc_baselinesvc_optimized
fit_time0.0011690.0016900.0044570.0386150.1296780.0011240.002409
score_time0.0026420.0024090.0026870.0042790.0032580.0025010.002588
test_accuracy0.3333330.9333330.9466670.9333330.9333330.9466670.946667
train_accuracy0.3466670.9533330.9500001.0000001.0000000.9666670.953333
test_precision0.1111110.9393330.9591750.9480630.9480630.9511110.951556
train_precision0.1202220.9535690.9504751.0000001.0000000.9675080.953927
test_recall0.3333330.9333330.9466670.9333330.9333330.9466670.946667
train_recall0.3466670.9533330.9500001.0000001.0000000.9666670.953333
test_f10.1666670.9329290.9455560.9320880.9320880.9463970.946667
train_f10.1785190.9532960.9500061.0000001.0000000.9666210.953321
\n", "
" ], "text/plain": [ " dummy_baseline logreg_baseline logreg_optimized \\\n", "fit_time 0.001169 0.001690 0.004457 \n", "score_time 0.002642 0.002409 0.002687 \n", "test_accuracy 0.333333 0.933333 0.946667 \n", "train_accuracy 0.346667 0.953333 0.950000 \n", "test_precision 0.111111 0.939333 0.959175 \n", "train_precision 0.120222 0.953569 0.950475 \n", "test_recall 0.333333 0.933333 0.946667 \n", "train_recall 0.346667 0.953333 0.950000 \n", "test_f1 0.166667 0.932929 0.945556 \n", "train_f1 0.178519 0.953296 0.950006 \n", "\n", " random_forest_baseline random_forest_optimized \\\n", "fit_time 0.038615 0.129678 \n", "score_time 0.004279 0.003258 \n", "test_accuracy 0.933333 0.933333 \n", "train_accuracy 1.000000 1.000000 \n", "test_precision 0.948063 0.948063 \n", "train_precision 1.000000 1.000000 \n", "test_recall 0.933333 0.933333 \n", "train_recall 1.000000 1.000000 \n", "test_f1 0.932088 0.932088 \n", "train_f1 1.000000 1.000000 \n", "\n", " svc_baseline svc_optimized \n", "fit_time 0.001124 0.002409 \n", "score_time 0.002501 0.002588 \n", "test_accuracy 0.946667 0.946667 \n", "train_accuracy 0.966667 0.953333 \n", "test_precision 0.951111 0.951556 \n", "train_precision 0.967508 0.953927 \n", "test_recall 0.946667 0.946667 \n", "train_recall 0.966667 0.953333 \n", "test_f1 0.946397 0.946667 \n", "train_f1 0.966621 0.953321 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results_df = ResultHandler(initial_scores, optimized_scores)\n", "results_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Testing the Final Model\n", "The optimized Random Forest model was deployed for testing on the test dataset. Alex measured its performance and confirmed that it generalized well beyond the training data." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " precision recall f1-score support\n", "\n", " 0 1.00 1.00 1.00 25\n", " 1 0.96 0.96 0.96 26\n", " 2 0.96 0.96 0.96 24\n", "\n", " accuracy 0.97 75\n", " macro avg 0.97 0.97 0.97 75\n", "weighted avg 0.97 0.97 0.97 75\n", "\n" ] } ], "source": [ "# Testing the final Random Forest model\n", "final_model = optimized_models['random_forest']\n", "y_pred = final_model.predict(X_test)\n", "\n", "print(classification_report(y_test, y_pred))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reflection\n", "By combining tools like `ClassifierTrainer`, `FeatureSelector`, `ClassifierOptimizer`, and `ResultHandler`, Alex had created an efficient, repeatable, and transparent machine learning pipeline. It was a productive day of problem-solving, leaving Alex eager to tackle their next project." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.8" } }, "nbformat": 4, "nbformat_minor": 4 }