{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Multi-class Classification\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": "In this lab, we will learn the different strategies of Multi-class classification and implement the same on a real-world dataset.\n"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **Objectives**\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": "After completing this lab we will be able to:\n"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Understand the use of one-hot encoding for categorical variables.\n",
"2. Implement logistic regression for multi-class classification using **One-vs-All (OvA)** and **One-vs-One (OvO)** strategies.\n",
"3. Evaluate model performance using appropriate metrics.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Import Necessary Libraries\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, to ensure the availability of the required libraries, execute the cell below.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:37:40.612955Z",
"start_time": "2025-11-13T14:37:36.732569Z"
}
},
"source": [
"!pip install numpy==2.2.0\n!pip install pandas==2.2.3\n!pip install scikit-learn==1.6.0\n!pip install matplotlib==3.9.3\n!pip install seaborn==0.13.2"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: numpy==2.2.0 in ./.venv/lib/python3.12/site-packages (2.2.0)\r\n",
"\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.3\u001B[0m\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\r\n",
"Requirement already satisfied: pandas==2.2.3 in ./.venv/lib/python3.12/site-packages (2.2.3)\r\n",
"Requirement already satisfied: numpy>=1.26.0 in ./.venv/lib/python3.12/site-packages (from pandas==2.2.3) (2.2.0)\r\n",
"Requirement already satisfied: python-dateutil>=2.8.2 in ./.venv/lib/python3.12/site-packages (from pandas==2.2.3) (2.9.0.post0)\r\n",
"Requirement already satisfied: pytz>=2020.1 in ./.venv/lib/python3.12/site-packages (from pandas==2.2.3) (2025.2)\r\n",
"Requirement already satisfied: tzdata>=2022.7 in ./.venv/lib/python3.12/site-packages (from pandas==2.2.3) (2025.2)\r\n",
"Requirement already satisfied: six>=1.5 in ./.venv/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas==2.2.3) (1.17.0)\r\n",
"\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.3\u001B[0m\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\r\n",
"Requirement already satisfied: scikit-learn==1.6.0 in ./.venv/lib/python3.12/site-packages (1.6.0)\r\n",
"Requirement already satisfied: numpy>=1.19.5 in ./.venv/lib/python3.12/site-packages (from scikit-learn==1.6.0) (2.2.0)\r\n",
"Requirement already satisfied: scipy>=1.6.0 in ./.venv/lib/python3.12/site-packages (from scikit-learn==1.6.0) (1.16.3)\r\n",
"Requirement already satisfied: joblib>=1.2.0 in ./.venv/lib/python3.12/site-packages (from scikit-learn==1.6.0) (1.5.2)\r\n",
"Requirement already satisfied: threadpoolctl>=3.1.0 in ./.venv/lib/python3.12/site-packages (from scikit-learn==1.6.0) (3.6.0)\r\n",
"\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.3\u001B[0m\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\r\n",
"Requirement already satisfied: matplotlib==3.9.3 in ./.venv/lib/python3.12/site-packages (3.9.3)\r\n",
"Requirement already satisfied: contourpy>=1.0.1 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (1.3.3)\r\n",
"Requirement already satisfied: cycler>=0.10 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (0.12.1)\r\n",
"Requirement already satisfied: fonttools>=4.22.0 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (4.60.1)\r\n",
"Requirement already satisfied: kiwisolver>=1.3.1 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (1.4.9)\r\n",
"Requirement already satisfied: numpy>=1.23 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (2.2.0)\r\n",
"Requirement already satisfied: packaging>=20.0 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (25.0)\r\n",
"Requirement already satisfied: pillow>=8 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (12.0.0)\r\n",
"Requirement already satisfied: pyparsing>=2.3.1 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (3.2.5)\r\n",
"Requirement already satisfied: python-dateutil>=2.7 in ./.venv/lib/python3.12/site-packages (from matplotlib==3.9.3) (2.9.0.post0)\r\n",
"Requirement already satisfied: six>=1.5 in ./.venv/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib==3.9.3) (1.17.0)\r\n",
"\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.3\u001B[0m\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\r\n",
"Requirement already satisfied: seaborn==0.13.2 in ./.venv/lib/python3.12/site-packages (0.13.2)\r\n",
"Requirement already satisfied: numpy!=1.24.0,>=1.20 in ./.venv/lib/python3.12/site-packages (from seaborn==0.13.2) (2.2.0)\r\n",
"Requirement already satisfied: pandas>=1.2 in ./.venv/lib/python3.12/site-packages (from seaborn==0.13.2) (2.2.3)\r\n",
"Requirement already satisfied: matplotlib!=3.6.1,>=3.4 in ./.venv/lib/python3.12/site-packages (from seaborn==0.13.2) (3.9.3)\r\n",
"Requirement already satisfied: contourpy>=1.0.1 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (1.3.3)\r\n",
"Requirement already satisfied: cycler>=0.10 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (0.12.1)\r\n",
"Requirement already satisfied: fonttools>=4.22.0 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (4.60.1)\r\n",
"Requirement already satisfied: kiwisolver>=1.3.1 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (1.4.9)\r\n",
"Requirement already satisfied: packaging>=20.0 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (25.0)\r\n",
"Requirement already satisfied: pillow>=8 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (12.0.0)\r\n",
"Requirement already satisfied: pyparsing>=2.3.1 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (3.2.5)\r\n",
"Requirement already satisfied: python-dateutil>=2.7 in ./.venv/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (2.9.0.post0)\r\n",
"Requirement already satisfied: pytz>=2020.1 in ./.venv/lib/python3.12/site-packages (from pandas>=1.2->seaborn==0.13.2) (2025.2)\r\n",
"Requirement already satisfied: tzdata>=2022.7 in ./.venv/lib/python3.12/site-packages (from pandas>=1.2->seaborn==0.13.2) (2025.2)\r\n",
"Requirement already satisfied: six>=1.5 in ./.venv/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.4->seaborn==0.13.2) (1.17.0)\r\n",
"\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.3\u001B[0m\r\n",
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\r\n"
]
}
],
"execution_count": 30
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, import the necessary libraries for data processing, model training, and evaluation.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:37:44.299435Z",
"start_time": "2025-11-13T14:37:44.296968Z"
}
},
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.preprocessing import OneHotEncoder, StandardScaler\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.multiclass import OneVsOneClassifier, OneVsRestClassifier\n",
"from sklearn.metrics import accuracy_score\n",
"\n",
"import warnings\n",
"warnings.filterwarnings('ignore')"
],
"outputs": [],
"execution_count": 31
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## About the dataset\n",
"The data set being used for this lab is the \"Obesity Risk Prediction\" data set publically available on UCI Library under the CCA 4.0 license. The data set has 17 attributes in total along with 2,111 samples. \n",
"\n",
"The attributes of the dataset are descibed below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"
\n",
"
\n",
"
Variable Name
\n",
"
Type
\n",
"
Description
\n",
"
\n",
"\n",
"
\n",
"
Gender
\n",
"
Categorical
\n",
"
\n",
"
\n",
"
\n",
"
Age
\n",
"
Continuous
\n",
"
\n",
"
\n",
"
\n",
"
Height
\n",
"
Continuous
\n",
"
\n",
"
\n",
"
\n",
"
Weight
\n",
"
Continuous
\n",
"
\n",
"
\n",
"
\n",
"
family_history_with_overweight
\n",
"
Binary
\n",
"
Has a family member suffered or suffers from overweight?
\n",
"
\n",
"
\n",
"
FAVC
\n",
"
Binary
\n",
"
Do you eat high caloric food frequently?
\n",
"
\n",
"
\n",
"
FCVC
\n",
"
Integer
\n",
"
Do you usually eat vegetables in your meals?
\n",
"
\n",
"
\n",
"
NCP
\n",
"
Continuous
\n",
"
How many main meals do you have daily?
\n",
"
\n",
"
\n",
"
CAEC
\n",
"
Categorical
\n",
"
Do you eat any food between meals?
\n",
"
\n",
"
\n",
"
SMOKE
\n",
"
Binary
\n",
"
Do you smoke?
\n",
"
\n",
"
\n",
"
CH2O
\n",
"
Continuous
\n",
"
How much water do you drink daily?
\n",
"
\n",
"
\n",
"
SCC
\n",
"
Binary
\n",
"
Do you monitor the calories you eat daily?
\n",
"
\n",
"
\n",
"
FAF
\n",
"
Continuous
\n",
"
How often do you have physical activity?
\n",
"
\n",
"
\n",
"
TUE
\n",
"
Integer
\n",
"
How much time do you use technological devices such as cell phone, videogames, television, computer and others?
\n",
"
\n",
"
\n",
"
CALC
\n",
"
Categorical
\n",
"
How often do you drink alcohol?
\n",
"
\n",
"
\n",
"
MTRANS
\n",
"
Categorical
\n",
"
Which transportation do you usually use?
\n",
"
\n",
"
\n",
"
NObeyesdad
\n",
"
Categorical
\n",
"
Obesity level
\n",
"
\n",
"
\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load the dataset\n",
"\n",
"Load the data set by executing the code cell below.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:37:49.394162Z",
"start_time": "2025-11-13T14:37:49.381623Z"
}
},
"source": [
"file_path = \"data/Obesity_level_prediction_dataset.csv\"\n",
"data = pd.read_csv(file_path)\n",
"data.head()"
],
"outputs": [
{
"data": {
"text/plain": [
" Gender Age Height Weight family_history_with_overweight FAVC FCVC \\\n",
"0 Female 21.0 1.62 64.0 yes no 2.0 \n",
"1 Female 21.0 1.52 56.0 yes no 3.0 \n",
"2 Male 23.0 1.80 77.0 yes no 2.0 \n",
"3 Male 27.0 1.80 87.0 no no 3.0 \n",
"4 Male 22.0 1.78 89.8 no no 2.0 \n",
"\n",
" NCP CAEC SMOKE CH2O SCC FAF TUE CALC \\\n",
"0 3.0 Sometimes no 2.0 no 0.0 1.0 no \n",
"1 3.0 Sometimes yes 3.0 yes 3.0 0.0 Sometimes \n",
"2 3.0 Sometimes no 2.0 no 2.0 1.0 Frequently \n",
"3 3.0 Sometimes no 2.0 no 2.0 0.0 Frequently \n",
"4 1.0 Sometimes no 2.0 no 0.0 0.0 Sometimes \n",
"\n",
" MTRANS NObeyesdad \n",
"0 Public_Transportation Normal_Weight \n",
"1 Public_Transportation Normal_Weight \n",
"2 Public_Transportation Normal_Weight \n",
"3 Walking Overweight_Level_I \n",
"4 Public_Transportation Overweight_Level_II "
],
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
Gender
\n",
"
Age
\n",
"
Height
\n",
"
Weight
\n",
"
family_history_with_overweight
\n",
"
FAVC
\n",
"
FCVC
\n",
"
NCP
\n",
"
CAEC
\n",
"
SMOKE
\n",
"
CH2O
\n",
"
SCC
\n",
"
FAF
\n",
"
TUE
\n",
"
CALC
\n",
"
MTRANS
\n",
"
NObeyesdad
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
Female
\n",
"
21.0
\n",
"
1.62
\n",
"
64.0
\n",
"
yes
\n",
"
no
\n",
"
2.0
\n",
"
3.0
\n",
"
Sometimes
\n",
"
no
\n",
"
2.0
\n",
"
no
\n",
"
0.0
\n",
"
1.0
\n",
"
no
\n",
"
Public_Transportation
\n",
"
Normal_Weight
\n",
"
\n",
"
\n",
"
1
\n",
"
Female
\n",
"
21.0
\n",
"
1.52
\n",
"
56.0
\n",
"
yes
\n",
"
no
\n",
"
3.0
\n",
"
3.0
\n",
"
Sometimes
\n",
"
yes
\n",
"
3.0
\n",
"
yes
\n",
"
3.0
\n",
"
0.0
\n",
"
Sometimes
\n",
"
Public_Transportation
\n",
"
Normal_Weight
\n",
"
\n",
"
\n",
"
2
\n",
"
Male
\n",
"
23.0
\n",
"
1.80
\n",
"
77.0
\n",
"
yes
\n",
"
no
\n",
"
2.0
\n",
"
3.0
\n",
"
Sometimes
\n",
"
no
\n",
"
2.0
\n",
"
no
\n",
"
2.0
\n",
"
1.0
\n",
"
Frequently
\n",
"
Public_Transportation
\n",
"
Normal_Weight
\n",
"
\n",
"
\n",
"
3
\n",
"
Male
\n",
"
27.0
\n",
"
1.80
\n",
"
87.0
\n",
"
no
\n",
"
no
\n",
"
3.0
\n",
"
3.0
\n",
"
Sometimes
\n",
"
no
\n",
"
2.0
\n",
"
no
\n",
"
2.0
\n",
"
0.0
\n",
"
Frequently
\n",
"
Walking
\n",
"
Overweight_Level_I
\n",
"
\n",
"
\n",
"
4
\n",
"
Male
\n",
"
22.0
\n",
"
1.78
\n",
"
89.8
\n",
"
no
\n",
"
no
\n",
"
2.0
\n",
"
1.0
\n",
"
Sometimes
\n",
"
no
\n",
"
2.0
\n",
"
no
\n",
"
0.0
\n",
"
0.0
\n",
"
Sometimes
\n",
"
Public_Transportation
\n",
"
Overweight_Level_II
\n",
"
\n",
" \n",
"
\n",
"
"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 32
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exploratory Data Analysis\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Visualize the distribution of the target variable to understand the class balance.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:37:53.233966Z",
"start_time": "2025-11-13T14:37:53.155556Z"
}
},
"source": [
"# Distribution of target variable\nsns.countplot(y='NObeyesdad', data=data)\nplt.title('Distribution of Obesity Levels')\nplt.show()"
],
"outputs": [
{
"data": {
"text/plain": [
"
"
],
"image/png": "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kZTkczdEHsInwlbx4gWzexfCBm1BW3Bu8O8k2t4zEhOTbN++wwTQCET4RNgaMmuxrd6+J7t3AwAQYpVKF7Wh3ZpZbGwM4TMCET4RtjbF/2WrtxE+AQCIJDl/UAgAAAByDMInAAAAQobwCQAAgJAhfAIAACBkCJ8AAAAIGcInAAAAQobwCQAAgJAhfAIAACBkCJ8AAAAIGcInAAAAQobwCQAAgJAhfAIAACBkCJ8AAAAImagNn9WrV7f777//pPvffvtta9GihYWD0aNH2y233JLu85YvX+6OZ/v27cnuv/rqq6127dp27Ngx/30nTpywOnXq2IIFC9Ldrrb53Xffpfu8rVu3uufqa1rmzZtnu3fvTndbAAAgskVt+JQPPvjAvvnmG8vpzj//fCtQoIALoZ4dO3bYtm3brGDBgrZ06VL//b/++qsdP37cLrzwwnS3u2jRIqtfv36W90/70a9fPzty5EiWtwUAAHK2qA6f5cuXt8GDB7swlpPlzp3b6tWrlyx8qmJZq1Ytu/jii5NVL5ctW2Z/+9vfrFixYulut1SpUpY3b94s75/P58vyNgAAQGSI6vCpapwqhJMnT07zOX/++afdc889LsQ1atTIhg4d6g+r6qK/4YYbrG/fvtawYUN77733XDe5ttezZ0/XvX399dfbpk2bbNCgQa6K2KpVK1uyZIl/+wsXLrROnTq57nFVI++77z47dOjQaR+LfnfFihX+nxU4tc+6ffvtt/77f/75Z3efFwpfeukla9q0qfv9u+66K1nXfWC3+9GjR23gwIHuOJs1a2ZvvfWWq7gGdrWrK79ly5ZWt25dt639+/e7+6+88kr/V7UZAACIXlEdPsuUKWN33323jR8/3rZs2XLS4wqZ3bt3d93Fr732mo0cOdI+//xze+655/zPUZd21apVbdasWS7EiQJd165dXdA6cOCAC6BxcXE2e/Zsq1atmguwsnnzZhdsu3Xr5sZEavuLFy922zpdCo+rVq2ypKSkk8KnQunhw4f9++uFz+nTp9v7779v//73v+3NN9+0kiVL2m233ebGhaakfdbvKli/8MILNmnSJEtMTEz2nLlz59qIESNs2rRpbl8mTpzo7ldQ9b62adPmtI8NAABEjqgOn6JKZYUKFeypp5466bGvvvrKVUaHDx/uqoBNmjSxxx57zN544w1/dTImJsb69Olj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1apVLpTVrl071ccbNmxoa9ascWHok08+8d+/bNky27dvn1155ZW2a9cuu/POO13Yev/9961Xr14ubCqAeRRS+/XrZxMmTHDBUoHP8/3337vg9eeff7qfv/76axc0ZeDAgXbgwAFXfR07dqytWLHCBg8efNJ+amyq9qFIkSIuJCvgjhkzJtlztm/fbhs2bHDhTtuYMmWKffnlly7kDRgwwM4++2wXfMuWLZulNj1Ve1SpUsUFzcC2VDDVPuh19UFA+63xt3PnznXtf+utt9r+/fuztE8AACC6hU349EKNQltqvPs7derkQuHBgwf9gUkhslChQm5s6CWXXGI333yzVahQwTp27Gh///vfberUqf7tKNwqwKoSqGC5evVqFyoV1BRiVa386aef3HO/+eYbV2ndvHmzLViwwIYPH+6qhfpdVT4VyvS7gb799lsXYIcNG2ZVq1Z11UbtT6A8efLY0KFDrVKlStamTRsXArUf6r4vXLiwq/yqGz9lBfh0pdceGsrw8ccf+5+vttT+iIY+KLiqElyxYkUX2MuXL2/vvfdelvYJAABEt7AZ81m0aFF/97sqf6nNgpcLLrjABbMvvvjCH57UHS7r16+3zz77zFXvPCdOnHAhz6MA5VEgU5e+KoFHjhxxv6eg9eOPP1rjxo3t999/d+FNP2uyk7r3A+m+TZs2JbtPXdN6PYVhj8asaiKRp2TJklagQAH/zwqcmuUebOm1h4LmCy+8YDt27HD3KwC3bt3a3y2vsD1ixAj/7x47dsx1zQMAAOT48KmKpCp9K1euTDV86n5VHVUdVGhSlU7hce/evXb55Zf7u7xVabzrrruS/W7u3P87zHz58iV77NJLL7UlS5a4YKXxnApm6lZXBVP7pIprYmKiC4iBY009ZcqUsZ9//tn/s44h5aShlD+nVtE8ExON0muPc845xx2jqro6fo0/9SZO6Zg1BEBjYwMFhmoAAIAc2+1eokQJa9mypQt+Cj6B1I09e/Zs69q1q/tZFU91vSuAqgs9f/787n4FR1UiFUq928KFC914x7SoW13hU13tCl/e2FJtW49521X3ekxMjH+7mmz03HPPnVSxrFatmqsOesMCvPGsGaXXCJaMtIeC/Oeff+4CqNo18Hc19jXwd7UElMbYAgAA5Pjw6U3q0dhPzXhXV7gm5mhCjCa6XHzxxdatWzf3vJo1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btzYXblJV3CqXr16hhbgz8jzMuL48eM2a9asDD33ySefdIv9B1q6dKnbl4cffjjZ/e+++65dfPHFlpSUdMptvv3229aiRYsMvb7+NvobpeXgwYP2zjvvZGhbAAAg8oV9+AyFl19+2c477zybN2+eXXPNNTZ8+HDr1q2bW9u0S5cutmjRonS3oaCakedlhBbzHz9+fIaee+GFF9qqVauSBUoF4dKlS7uvKUO2np/eVanatGljs2fPtmB49dVXbc6cOUHZFgAAyPkIn2Z24MABq1Onjp1zzjlWqFAh97MqhLqaU968ea1UqVLpNmRGn5cRPp8vw89VmFR1cf369f77FDq7d+/uLoO6ZcuWZOFTx5Wes846y0qUKGGhPhYAABD5ckz4VFewundHjRpljRo1cqHr6aef9oeb7du322233eYqkE2aNLEhQ4bYiRMnUu2611Wa1C2tr3psyZIl9tJLL7n7vK5zhTc9lrI7fdOmTXb77be717n88stt2rRp7v6Uz/vjjz/srrvusrp167ou7DFjxlhiYmK6x6LtPPLII7Zt2zb/Pp6KLnN67rnn2ooVK/xd9j/99JNdeeWVVqNGDfv222/d/UeOHLE1a9b4L32a3v4FdruvXLnSunbt6gL6DTfcYC+++GKyrna1s7r/GzRoYJdccolNmTLFvx1tV+0brCEJAAAgZ8sx4dMby7hhwwZ74403bNCgQS74LV682D2msFmgQAE3vlBB8qOPPsrQuEmFUgVJBVd1m3td57o/5VjTY8eOuecVLFjQbfuxxx6zF154wT777LNkz1OI/Oc//2klS5a0uXPnumD5/vvvJ+tKT+tYtC8DBgyws88+2+1L2bJl0z0Ghdfly5e77/W1SJEiVqlSJRdsvfCpcJo/f36rWbNmhvbPoypwr1697IILLnBt265dOzdMIeXfJU+ePO7x3r172zPPPGPr1q1z3ffeB4JgDUkAAAA5W44Kn6rMKWRWrlzZOnbs6Cp7XsVPlcLChQtbuXLlXAVOAal58+bpbrNYsWIuOCm4qtvc6zovWrSoeyyQAtSePXts2LBhVq1aNVcdfPTRR08aQ6nAp0qst68KgQ899JC/SnqqY1H3vY4jV65cbl/09XTCp17b61rXV1UdU473zMj+ef7zn/+4ttFx6rk333yzXX311SdVX1Wt1bjZHj16uPD722+/ue57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mj6fz6655posbVMh7sSJE+77V155xZYuXeru85QoUSKLew0AAHBmRWz4HDJkiJ177rk2adIky5Url7tPP9erV89VQN944w3Lnz//GXv9UqVK+b9X8AyGYsWK+b8vUKCA5cmTJ9nrAAAAhLuI7HaPj4+3Tz/91O644w5/8PSUK1fOOnfubLNmzfLfN2LECGvQoIE1a9bMXnvttWTPnzlzpuuar1+/vus6/u233/yPffPNN9axY0erXbu2XXnlle65KbuhVZmcO3euu2k748aNs/bt2yd7DVUxu3XrlqVjPnr0qDuGjz/+2H+fqqSNGjVy+6n9uPfee+2RRx6xunXr2tVXX20LFy70P/f48eM2dOhQ93zdHnjgAdu3b1+W9gkAACAqwueqVatctVGhMDUNGza01atXu8C1bds2FyjffPNNu+++++zZZ5/1j11UgB0zZowbN6rwqN+79dZbbf/+/ZaYmGj9+vWz1q1bu/Gc99xzjz355JP2+++/J3ut2267zXW36zZ79mxXdV2zZo1t2LDB/xz9vu7PirPOOstatmxpH330kf++xYsXW+7cue3iiy92P3/yySeuXTTW9brrrrO7777bv78K4CtXrrSJEyfatGnT7ODBg+6YAAAAgikiw6fCoRQpUiTVx7379bx8+fLZM888Y9WqVbNrr73WVSW9Cqa67O+880674oorrGLFii5sli9f3t577z07cOCAqwzGxcXZOeecYx06dLApU6ac1A1esGBBFwx105jM8847z01+mj9/vntc4feXX35xITarFGA/++wzO3bsmPtZr6HtetVfjUEdPHiwValSxXr37u2quXPmzLEjR47Y9OnTXXjWvqlq+9xzz9mSJUuSVXoBAACyKiLDpzfRR93vac2C956ncaDFixf3P3b++efbunXr3Pf6Onz4cBfSvJsqphs3bnTjL2+88UZ79NFHXThVqCtcuLD/tdMLiV74VNVTlcmSJUtm+bgvvfRSy5s3r3311Veuy33BggXWpk0b/+O1atVyjwf+rGPcsmWLe74maHnH2bx5c0tKSnLHCgAAECwROeFI3e2q9qkb+eyzzz7pcd2v6p6CWGxs8vytwKWJPKKu9QEDBliTJk2SPadQoULu6xNPPGE33XSTC3m6qet+7NixLridigKhuvc3bdrkusm7du0ahKM218WusZzapo5B+6lxoIGPB9Lx6fj1VV5//XU3kSlQMEIxAABARFc+1b2t8Y8Kgl6wClyCSWMvvcCnqp+6nT3Lly93yzNJpUqV7M8//7QKFSr4b+PHj7dly5bZrl27XDe17uvTp4/rvm7cuLEbJ5pSTExMsp9Lly7tqp36HVVSW7VqFbRj17CBL7/80u2HutwDX1td6ArXKUO4qr8K6xpG4B2nguvTTz/t1igFAAAIlogMnzJw4EA3plMz3n/44Qfbvn27m3CjCUMKft7sco2PfOihh2zt2rVurKeqht27d3eP9ezZ06ZOnWrvvPOObd682XXBq5tcYybVva7tDRs2zD32/fffuyCpbvuUtKSTxnbu2LHDf1+7du3s1VdfdV3lGemqzyhNitLraYJUyklMCto6hvXr17tZ95qYdf3117ug2aVLF1fJ1WQrTULq37+/q8xqPCsAAECwRGS3u2hReS2npOqnlg3as2ePq/BpXKPCpdfdXrNmTfdcVUI19lNhUmMhve5xjRsdNWqU+1q1alUX2jT5SLRtPV+TjTSxSEFOIS4lLcfUt29f9zwtcK9qpKqdCnuBYzKDQdtWxVOVT+84PFpiSe3QqVMndwwvv/yyaxN5+OGH3VAAzYDX+M+LLrrIPZ5yqSoAAICsiPEFawV0nBZN5FEI/Prrr11wDab777/fdZ0rSHq0zqdmr6dcxzSc9Ro735Zu+O/kMAAAcpoa5UvYjH7tbO/eQ5aQ8L9hb9lBo/Di4gpbfPwBO1PJz3uNqK18hiutn6lLb2pykrrFgxk8NRZVXelaPP6DDz4I2nYBAACChfCZDbQ8k9b71PhLjyb2aJLUqeha7qeiJZZ0tSRdyShYYzU1AcsbA5saXTHqww8/DMprAQCAyEe3e5jQrPytW7ee8jnqSg81XQVKKwSkRcs3aeH9M4FudwBATka3e+qofIYJTezJjnCZHq2FGo77BQAAcqaIXWoJAAAA4YfwCQAAgJAhfAIAACBkCJ8AAAAIGcInAAAAQobwCQAAgJAhfAIAACBkCJ8AAAAIGcInAAAAQoYrHCFsVYgrYkeOJ2T3bgAAkCmVShel5VLBtd0BAADOkMTEJNu377AlJfmytY1jYszi4gpbfPwB8/nO7Gukh8onwtbevYeyexfCQvHiBWkL2oJzg38nvGfk0PdQhc7sDp7hhvCJsJWUlGRJSRbV9CnS++R8pj6p5hS0Be3BucG/E943IgMTjgAAABAyhE8AAACEDN3uCOtuVq+rNVp5xx/t7SC0Be3BucG/E943wvs9NKPbZrY7AAAAQoZudwAAAIQM4RMAAAAhQ/gEAABAyBA+AQAAEDKETwAAAIQM4RMAAAAhQ/gEAABAyBA+AQAAEDKETwAAAIQM4RNh5dixYzZgwAC78MILrWnTpvbKK69YtPjkk0+sevXqyW533323e+yXX36xLl26WN26de26666zlStXWiQ6fvy4tWvXzr777jv/fVu2bLEePXpYvXr1rE2bNrZo0aJkv7N48WL3O2qbW2+91T0/kttj6NChJ50n06dP9z/+wQcfWMuWLV179O3b1/bs2WM52Y4dO9y/g4svvtiaNWtmTz/9tHufiMZz41RtEW3nhWzatMluv/12q1+/vl1++eU2adIk/2PRdm5sOkVbhOW54QPCyODBg33t27f3rVy50vfxxx/76tev75s3b54vGowdO9Z35513+nbu3Om/7d+/33fo0CHfpZde6nvmmWd8v//+u2/IkCG+Sy65xN0fSY4ePerr27ev729/+5vv22+/dfclJSW58+H+++93xz5+/Hhf3bp1fdu2bXOP62u9evV8kydP9q1Zs8Z3zz33+Nq1a+d+LxLbQ3r06OGbMGFCsvPk8OHD7rGff/7ZV6dOHd/cuXN9v/76q+/mm2/29e7d25dT6e/YtWtXX69evdzf9/vvv/ddddVV7t9CtJ0bp2qLaDsvJDEx0deqVSv399+wYYPv888/9zVo0MD33nvvRd25kXiKtgjXc4PwibChMFW7du1k/6N96aWX3D+GaKA3jn//+98n3f/WW2/5WrRo4X9j1Ff9T2fOnDm+SLF27Vpfhw4d3P8wAsPW4sWL3f8kAoN29+7dfaNGjXLfjxw5Mtn5oTdUfWAJPIciqT2kWbNmvq+++irV33vwwQd9Dz30kP/n7du3+6pXr+7bvHmzLydScNDx79q1y3/f+++/72vatGnUnRunaotoOy9kx44dLjQeOHDAf58+rD3++ONRd27sOEVbhOu5Qbc7wsbq1astISHBdRt4GjZsaD///LMlJSVZpFu3bp1VrFjxpPt1/GqHmJgY97O+NmjQwJYtW2aRYsmSJdaoUSN78803Tzr2888/3woUKOC/T23hHbse1xANT/78+e2CCy7I8W2TVnscPHjQdb2mdp6k1h5ly5a1cuXKuftzolKlSrnuw7i4uJPaIdrOjVO1RbSdF1K6dGkbOXKkFSpUSEU0+/HHH+377793QxKi7dwofYq2CNdzI/cZ3TpwGnbt2mXFixe3vHnz+u/TG63GNO3bt89KlCgRse2pN4wNGza4cUkTJkywxMREa926tRvfpXapWrVqsueXLFnS1q5da5GiW7duqd6vY9cba8pj//PPPzP0eKS1hz6g6MPH+PHj7csvv7RixYpZz5497dprr3WP79y5M6Lao0iRIm5so0cfQjVWrXHjxlF3bpyqLaLtvEipRYsWtn37drviiivs6quvtmHDhkXVuXGqttD8gHA8NwifCBtHjhxJFjzF+1kTLyKZ3iy849cn2K1bt7pB4kePHk2zXSK9TSS9Y4+2tlm/fr37H0nlypXt5ptvdtWNQYMGuYrHVVdd5c6XSG6P4cOHu8l3s2fPtldffTWqz43Atli1alVUnxejRo2y+Ph4e+KJJ9wkrGh+3xiVoi1U0Q3Hc4PwibCRL1++k0547+ezzjrLIln58uXdjOaiRYu6N4qaNWu6ysaDDz7ouk5Sa5dIbxPvnFDVO61jT+ucUZUoEnXq1MlVNFS9kBo1atjGjRvtjTfecP8jSas91K0YCWFr6tSp9sILL9jf/va3qD43UrZFtWrVova8kNq1a7uv6iV74IEH3IogCpjReG7UTtEWP/30U1ieG4z5RNgoU6aM7d2714379Kh7RG8YkfCmkB69OXjjOqVKlSruDURjvfRJNpB+TtlVEqnnxKmOPa3H1WaRSOeH9z8RjyoaGtMVye0xZMgQmzJligtd6kqM5nMjtbaIxvNC+79gwYJk92l40okTJ9J9z4y09og/RVtozGc4nhuET4QNVfty586dbNC3Bk7rk1xsbGSfql999ZWbYBL4af3XX391bxoaKL906VI3LlT0VZ9mtSZbpNMxqktRXUOB54R37Pqqnz1qP3VFRmrbvPjii27twpQT9fQ/k9Ta448//nC3nNweY8aMsZkzZ9qIESOsbdu2UX1upNUW0XheaGjSP//5T3+IEo1v1NwAvWdG07mx9RRt8dprr4XnuXFG59IDp2nQoEG+tm3burXHPvnkE7dW2UcffRTx7aglMrQcxn333edbt26dW6dNS6i8/PLL7rHGjRu79T21BI++at3PSFvn0xO4tFBCQoKvTZs2vn79+rn1+LRWnZZQ8dbr27Jli1ueS/d76/VpeaKcul5feu2hfxfnn3++b9KkSb5Nmzb5ZsyY4atVq5bvp59+co/r6wUXXOCbNWuWf80+rR2bU2l5oZo1a/peeOGFZGsU6hZt58ap2iLazgvR379z586+2267zb0v6j1T6x+/+uqrUXduJJyiLcL13CB8IqxovbX+/fu7NwqFrylTpviihd4EtRiwjl3hcvTo0f43Q72BdOrUyb1hXn/99b5Vq1b5IlXKdS03btzou+mmm9wbpj6YfP3118merzdaLbCshZK1ll9OXrswI+2hD2X6H6XOhdatW5/04UzrvzZv3tydR1rrb8+ePb6cSuFAx5/aLdrOjfTaIprOC8+ff/7pjkVFCr1njhs3zv+eGU3nRnptEY7nRoz+c2ZrqwAAAMB/RfZAOgAAAIQVwicAAABChvAJAACAkCF8AgAAIGQInwAAAAgZwicAAABChvAJAACAkCF8AgDC3pYtW+yLL77I7t0AEASETwBA2BswYIAtX748u3cDQBAQPgEAABAyhE8AwGnZtGmT3X777Va/fn27/PLLbdq0ae7+devWufsbNGhgzZo1szFjxlhSUpJ7bPTo0XbLLbck206LFi3s7bffdt/rsXHjxrnfr1Onjl199dX21VdfuccefvhhW7Jkidteym0AyHkInwCADDt27JjddtttVrBgQZs1a5Y99thj9sILL9i7775r3bp1s9KlS9tbb71ljz/+uE2fPt0fTDNi/Pjx1rZtW/vggw+sRo0aNmjQIBdeBw4c6IKuXlchFkDOlju7dwAAkHMsWrTI9uzZY8OGDbNChQpZtWrV7NFHH7V9+/ZZ/vz5bciQIZY7d26rUqWK7dq1y1566SXr0aNHhrbdvHlz69y5s/u+T58+1rFjR7eNMmXKWJ48eaxAgQJWrFixM3yEAM40Kp8AgAzbsGGDVapUyQVPz3XXXWfr16+3Cy64wAVPj6qVCo9//fVXhrZdsWJF//fe9hMSEvjrABGG8AkAyLDAcBkoX758J93njfdMTEy0mJiYkx5PGSxV3UzJ5/Px1wEiDN3uAIAMU3VSE46OHDniutnl2Weftddff93i4uLsxIkT/hC5dOlSK1GihOsq132HDh3yb0ffq/seQPSh8gkAyLCmTZu6kKmJRprdvnDhQps5c6aNHDnSjh8/7r9/wYIFbnLQjTfe6KqetWvXttWrV9u8efNc172eFxub8f8Fabznxo0bbffu3fy1gByOyicAIOP/08id28aOHWuDBw+2a6+91gXR/v37W8uWLa1cuXL21FNPWadOnVzFs3v37nbnnXe632vSpImbeOSFzp49e9rOnTsz/LpdunRxC8336tXL5s6dy18MyMFifAyoAQAAQIjQ7Q4AAICQIXwCAAAgZAifAAAACBnCJwAAAEKG8AkAAICQIXwCAAAgZAifAAAACBnCJwAAAEKG8AkAAICQIXwCAAAgZAifAAAACBnCJwAAACxU/g9VEAHEccCgawAAAABJRU5ErkJggg=="
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 33
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This shows that the dataset is fairly balanced and does not require any special attention in terms of biased training.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Request 1\n",
"Check for null values, and display a summary of the dataset (use `.info()` and `.describe()` methods).\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:37:59.265213Z",
"start_time": "2025-11-13T14:37:59.250068Z"
}
},
"source": [
"# Checking for null values\n",
"print(data.isnull().sum())\n",
"\n",
"# Dataset summary\n",
"print(data.info())\n",
"print(data.describe())"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gender 0\n",
"Age 0\n",
"Height 0\n",
"Weight 0\n",
"family_history_with_overweight 0\n",
"FAVC 0\n",
"FCVC 0\n",
"NCP 0\n",
"CAEC 0\n",
"SMOKE 0\n",
"CH2O 0\n",
"SCC 0\n",
"FAF 0\n",
"TUE 0\n",
"CALC 0\n",
"MTRANS 0\n",
"NObeyesdad 0\n",
"dtype: int64\n",
"\n",
"RangeIndex: 2111 entries, 0 to 2110\n",
"Data columns (total 17 columns):\n",
" # Column Non-Null Count Dtype \n",
"--- ------ -------------- ----- \n",
" 0 Gender 2111 non-null object \n",
" 1 Age 2111 non-null float64\n",
" 2 Height 2111 non-null float64\n",
" 3 Weight 2111 non-null float64\n",
" 4 family_history_with_overweight 2111 non-null object \n",
" 5 FAVC 2111 non-null object \n",
" 6 FCVC 2111 non-null float64\n",
" 7 NCP 2111 non-null float64\n",
" 8 CAEC 2111 non-null object \n",
" 9 SMOKE 2111 non-null object \n",
" 10 CH2O 2111 non-null float64\n",
" 11 SCC 2111 non-null object \n",
" 12 FAF 2111 non-null float64\n",
" 13 TUE 2111 non-null float64\n",
" 14 CALC 2111 non-null object \n",
" 15 MTRANS 2111 non-null object \n",
" 16 NObeyesdad 2111 non-null object \n",
"dtypes: float64(8), object(9)\n",
"memory usage: 280.5+ KB\n",
"None\n",
" Age Height Weight FCVC NCP \\\n",
"count 2111.000000 2111.000000 2111.000000 2111.000000 2111.000000 \n",
"mean 24.312600 1.701677 86.586058 2.419043 2.685628 \n",
"std 6.345968 0.093305 26.191172 0.533927 0.778039 \n",
"min 14.000000 1.450000 39.000000 1.000000 1.000000 \n",
"25% 19.947192 1.630000 65.473343 2.000000 2.658738 \n",
"50% 22.777890 1.700499 83.000000 2.385502 3.000000 \n",
"75% 26.000000 1.768464 107.430682 3.000000 3.000000 \n",
"max 61.000000 1.980000 173.000000 3.000000 4.000000 \n",
"\n",
" CH2O FAF TUE \n",
"count 2111.000000 2111.000000 2111.000000 \n",
"mean 2.008011 1.010298 0.657866 \n",
"std 0.612953 0.850592 0.608927 \n",
"min 1.000000 0.000000 0.000000 \n",
"25% 1.584812 0.124505 0.000000 \n",
"50% 2.000000 1.000000 0.625350 \n",
"75% 2.477420 1.666678 1.000000 \n",
"max 3.000000 3.000000 2.000000 \n"
]
}
],
"execution_count": 34
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Expected Output:\n",
"\n",
"* Counts of null values for each column (likely zero for this dataset).\n",
"* Dataset info including column names, data types, and memory usage.\n",
"* Descriptive statistics for numerical columns.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Preprocessing the data\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature scaling\n",
"Scale the numerical features to standardize their ranges for better model performance.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:05.399638Z",
"start_time": "2025-11-13T14:38:05.393290Z"
}
},
"source": [
"# Standardizing continuous numerical features\ncontinuous_columns = data.select_dtypes(include=['float64']).columns.tolist()\n\nscaler = StandardScaler()\nscaled_features = scaler.fit_transform(data[continuous_columns])\n\n# Converting to a DataFrame\nscaled_df = pd.DataFrame(scaled_features, columns=scaler.get_feature_names_out(continuous_columns))\n\n# Combining with the original dataset\nscaled_data = pd.concat([data.drop(columns=continuous_columns), scaled_df], axis=1)"
],
"outputs": [],
"execution_count": 35
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Standardization of data is important to better define the decision boundaries between classes by making sure that the feature variations are in similar scales. The data is now ready to be used for training and testing.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### One-hot encoding\n",
"Convert categorical variables into numerical format using one-hot encoding.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:09.399978Z",
"start_time": "2025-11-13T14:38:09.388839Z"
}
},
"source": [
"# Identifying categorical columns\ncategorical_columns = scaled_data.select_dtypes(include=['object']).columns.tolist()\ncategorical_columns.remove('NObeyesdad') # Exclude target column\n\n# Applying one-hot encoding\nencoder = OneHotEncoder(sparse_output=False, drop='first')\nencoded_features = encoder.fit_transform(scaled_data[categorical_columns])\n\n# Converting to a DataFrame\nencoded_df = pd.DataFrame(encoded_features, columns=encoder.get_feature_names_out(categorical_columns))\n\n# Combining with the original dataset\nprepped_data = pd.concat([scaled_data.drop(columns=categorical_columns), encoded_df], axis=1)"
],
"outputs": [],
"execution_count": 36
},
{
"cell_type": "markdown",
"metadata": {},
"source": "We will observe that all the categorical variables have now been modified to one-hot encoded features. This increases the overall number of fields to 24. \n"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Encode the target variable\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:14.179071Z",
"start_time": "2025-11-13T14:38:14.168179Z"
}
},
"source": [
"# Encoding the target variable\nprepped_data['NObeyesdad'] = prepped_data['NObeyesdad'].astype('category').cat.codes\nprepped_data.head()"
],
"outputs": [
{
"data": {
"text/plain": [
" NObeyesdad Age Height Weight FCVC NCP CH2O \\\n",
"0 1 -0.522124 -0.875589 -0.862558 -0.785019 0.404153 -0.013073 \n",
"1 1 -0.522124 -1.947599 -1.168077 1.088342 0.404153 1.618759 \n",
"2 1 -0.206889 1.054029 -0.366090 -0.785019 0.404153 -0.013073 \n",
"3 5 0.423582 1.054029 0.015808 1.088342 0.404153 -0.013073 \n",
"4 6 -0.364507 0.839627 0.122740 -0.785019 -2.167023 -0.013073 \n",
"\n",
" FAF TUE Gender_Male ... CAEC_no SMOKE_yes SCC_yes \\\n",
"0 -1.188039 0.561997 0.0 ... 0.0 0.0 0.0 \n",
"1 2.339750 -1.080625 0.0 ... 0.0 1.0 1.0 \n",
"2 1.163820 0.561997 1.0 ... 0.0 0.0 0.0 \n",
"3 1.163820 -1.080625 1.0 ... 0.0 0.0 0.0 \n",
"4 -1.188039 -1.080625 1.0 ... 0.0 0.0 0.0 \n",
"\n",
" CALC_Frequently CALC_Sometimes CALC_no MTRANS_Bike MTRANS_Motorbike \\\n",
"0 0.0 0.0 1.0 0.0 0.0 \n",
"1 0.0 1.0 0.0 0.0 0.0 \n",
"2 1.0 0.0 0.0 0.0 0.0 \n",
"3 1.0 0.0 0.0 0.0 0.0 \n",
"4 0.0 1.0 0.0 0.0 0.0 \n",
"\n",
" MTRANS_Public_Transportation MTRANS_Walking \n",
"0 1.0 0.0 \n",
"1 1.0 0.0 \n",
"2 1.0 0.0 \n",
"3 0.0 1.0 \n",
"4 1.0 0.0 \n",
"\n",
"[5 rows x 24 columns]"
],
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
NObeyesdad
\n",
"
Age
\n",
"
Height
\n",
"
Weight
\n",
"
FCVC
\n",
"
NCP
\n",
"
CH2O
\n",
"
FAF
\n",
"
TUE
\n",
"
Gender_Male
\n",
"
...
\n",
"
CAEC_no
\n",
"
SMOKE_yes
\n",
"
SCC_yes
\n",
"
CALC_Frequently
\n",
"
CALC_Sometimes
\n",
"
CALC_no
\n",
"
MTRANS_Bike
\n",
"
MTRANS_Motorbike
\n",
"
MTRANS_Public_Transportation
\n",
"
MTRANS_Walking
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
-0.522124
\n",
"
-0.875589
\n",
"
-0.862558
\n",
"
-0.785019
\n",
"
0.404153
\n",
"
-0.013073
\n",
"
-1.188039
\n",
"
0.561997
\n",
"
0.0
\n",
"
...
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
\n",
"
\n",
"
1
\n",
"
1
\n",
"
-0.522124
\n",
"
-1.947599
\n",
"
-1.168077
\n",
"
1.088342
\n",
"
0.404153
\n",
"
1.618759
\n",
"
2.339750
\n",
"
-1.080625
\n",
"
0.0
\n",
"
...
\n",
"
0.0
\n",
"
1.0
\n",
"
1.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
\n",
"
\n",
"
2
\n",
"
1
\n",
"
-0.206889
\n",
"
1.054029
\n",
"
-0.366090
\n",
"
-0.785019
\n",
"
0.404153
\n",
"
-0.013073
\n",
"
1.163820
\n",
"
0.561997
\n",
"
1.0
\n",
"
...
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
\n",
"
\n",
"
3
\n",
"
5
\n",
"
0.423582
\n",
"
1.054029
\n",
"
0.015808
\n",
"
1.088342
\n",
"
0.404153
\n",
"
-0.013073
\n",
"
1.163820
\n",
"
-1.080625
\n",
"
1.0
\n",
"
...
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
\n",
"
\n",
"
4
\n",
"
6
\n",
"
-0.364507
\n",
"
0.839627
\n",
"
0.122740
\n",
"
-0.785019
\n",
"
-2.167023
\n",
"
-0.013073
\n",
"
-1.188039
\n",
"
-1.080625
\n",
"
1.0
\n",
"
...
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
0.0
\n",
"
0.0
\n",
"
1.0
\n",
"
0.0
\n",
"
\n",
" \n",
"
\n",
"
5 rows × 24 columns
\n",
"
"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 37
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Separate the input and target data\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:18.135880Z",
"start_time": "2025-11-13T14:38:18.132397Z"
}
},
"source": [
"# Preparing final dataset\nX = prepped_data.drop('NObeyesdad', axis=1)\ny = prepped_data['NObeyesdad']"
],
"outputs": [],
"execution_count": 38
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Model training and evaluation \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Splitting the data set\n",
"Split the data into training and testing subsets.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:22.069860Z",
"start_time": "2025-11-13T14:38:22.062484Z"
}
},
"source": [
"# Splitting data\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)"
],
"outputs": [],
"execution_count": 39
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Logistic Regression with One-vs-All\n",
"In the One-vs-All approach:\n",
"\n",
"* The algorithm trains a single binary classifier for each class.\n",
"* Each classifier learns to distinguish a single class from all the others combined.\n",
"* If there are k classes, k classifiers are trained.\n",
"* During prediction, the algorithm evaluates all classifiers on each input, and selects the class with the highest confidence score as the predicted class.\n",
"\n",
"#### Advantages:\n",
"* Simpler and more efficient in terms of the number of classifiers (k)\n",
"* Easier to implement for algorithms that naturally provide confidence scores (e.g., logistic regression, SVM).\n",
"\n",
"#### Disadvantages:\n",
"* Classifiers may struggle with class imbalance since each binary classifier must distinguish between one class and the rest.\n",
"* Requires the classifier to perform well even with highly imbalanced datasets, as the \"all\" group typically contains more samples than the \"one\" class.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Train a logistic regression model using the One-vs-All strategy and evaluate its performance.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:27.677127Z",
"start_time": "2025-11-13T14:38:27.637666Z"
}
},
"source": [
"# Training logistic regression model using One-vs-All (default)\n",
"model_ova = LogisticRegression(multi_class='ovr', max_iter=1000)\n",
"# model_ova = OneVsRestClassifier(LogisticRegression(max_iter=1000))\n",
"model_ova.fit(X_train, y_train)"
],
"outputs": [
{
"data": {
"text/plain": [
"LogisticRegression(max_iter=1000, multi_class='ovr')"
],
"text/html": [
"
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 40
},
{
"cell_type": "markdown",
"metadata": {},
"source": "We can now evaluate the accuracy of the trained model as a measure of its performance on unseen testing data.\n"
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:31.549685Z",
"start_time": "2025-11-13T14:38:31.542599Z"
}
},
"source": [
"# Predictions\ny_pred_ova = model_ova.predict(X_test)\n\n# Evaluation metrics for OvA\nprint(\"One-vs-All (OvA) Strategy\")\nprint(f\"Accuracy: {np.round(100*accuracy_score(y_test, y_pred_ova),2)}%\")"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"One-vs-All (OvA) Strategy\n",
"Accuracy: 76.12%\n"
]
}
],
"execution_count": 41
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Logistic Regression with OvO\n",
"\n",
"In the One-vs-One approach:\n",
"* The algorithm trains a binary classifier for every pair of classes in the dataset.\n",
"* If there are k classes, this results in $k(k-1)/2$ classifiers.\n",
"* Each classifier is trained to distinguish between two specific classes, ignoring the rest.\n",
"* During prediction, all classifiers are used, and a \"voting\" mechanism decides the final class by selecting the class that wins the majority of pairwise comparisons.\n",
"\n",
"#### Advantages:\n",
"* Suitable for algorithms that are computationally expensive to train on many samples because each binary classifier deals with a smaller dataset (only samples from two classes).\n",
"* Can be more accurate in some cases since classifiers focus on distinguishing between two specific classes at a time.\n",
"\n",
"#### Disadvantages:\n",
"* Computationally expensive for datasets with a large number of classes due to the large number of classifiers required.\n",
"* May lead to ambiguous predictions if voting results in a tie.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Train a logistic regression model using the One-vs-One (OvO) strategy and evaluate its performance.\n"
]
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-13T14:38:39.109903Z",
"start_time": "2025-11-13T14:38:39.068992Z"
}
},
"source": [
"# Training logistic regression model using One-vs-One\n",
"model_ovo = OneVsOneClassifier(LogisticRegression(max_iter=1000))\n",
"model_ovo.fit(X_train, y_train)"
],
"outputs": [
{
"data": {
"text/plain": [
"OneVsOneClassifier(estimator=LogisticRegression(max_iter=1000))"
],
"text/html": [
"
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.