Files
Esercizi-MLN/Labs/Lab 8/lab_8.ipynb
2024-11-28 23:01:35 +01:00

1304 lines
173 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "0f2ab399",
"metadata": {},
"source": [
"<center><b><font size=6>Lab-8 <b><center>\n",
"<center><b><font size=6> Supervised learning with model selection, validation and hyper-parameter tuning<b><center>"
]
},
{
"cell_type": "markdown",
"id": "cce64de2",
"metadata": {},
"source": [
"### Objective: Applying the following techniques for supervised learning\n",
"1. **Validation curve** plots performance score over a single varying hyper-parameter. Therefore, we will also need to perform model validation, with a validation set or with cross-validation. \n",
"2. **Grid search** analyzes the combination of different hyper-parameters. It traverses all the possible combinations of selected values for selected hyper-parameters, training a hypothesis and examining the corresponding performance, eventually outputting the best parameter setting. We need to perform model validation, with a validation set or with cross-validation. \n",
"3. **Learning curve** studies the minimum amount of training samples needed to produce acceptable performance. This is helpful to understand if more data would likely improve the results, or if less data is already enough. We need to perform model validation also on the learning curve."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "936e1268",
"metadata": {},
"outputs": [],
"source": [
"# import needed python libraries\n",
"\n",
"%matplotlib inline\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"import pandas as pd\n",
"import numpy as np\n",
"import random\n",
"import math\n",
"import copy\n",
"\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.tree import DecisionTreeClassifier\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"from sklearn.preprocessing import StandardScaler\n",
"from sklearn.metrics import classification_report, accuracy_score, confusion_matrix\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.naive_bayes import GaussianNB\n",
"\n",
"from sklearn.model_selection import cross_validate, StratifiedShuffleSplit"
]
},
{
"cell_type": "markdown",
"id": "cdb08d90",
"metadata": {},
"source": [
"### 1. Tutorial - advanced classification"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "f654c7f0",
"metadata": {},
"outputs": [],
"source": [
"# load dataset of IRIS flowers\n",
"from sklearn import datasets\n",
"iris_data = datasets.load_iris()\n",
"features_iris = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']\n",
"df_iris = pd.DataFrame(iris_data.data, columns = features_iris)\n",
"df_iris['type'] = 'setosa'\n",
"df_iris.loc[50:99, 'type'] = 'versicolor'\n",
"df_iris.loc[100:149, 'type'] = 'virginica'\n",
"\n",
"# note that we need to convert the type of flowers to numerical labels\n",
"df_iris['label'] = pd.Categorical(df_iris['type']).codes\n",
"\n",
"# data segmentation\n",
"# we still split the dataset into training and test sets with portions of 70% and 30% for now\n",
"# but in the later stage, you need to further split the training set into training and validation sets\n",
"# therefore, we do not name training set as X_train and y_train, but X and y\n",
"X, X_test, y, y_test = train_test_split(\n",
" df_iris[features_iris], \n",
" df_iris['label'], \n",
" stratify = df_iris['label'], \n",
" train_size = 0.7, \n",
" random_state = 15\n",
")"
]
},
{
"cell_type": "markdown",
"id": "2149c055",
"metadata": {},
"source": [
"#### Two approaches for model validation\n",
"The Test set is always excluded during model development, and in order to consolidate the model selection and tuning, we need a validation set to evaluate the performance as an intermediate outcome. However, ML models are sensitive to data so that the outcome might be too dependant on a certain segmentation of data if you always stick to the same training and validation sets. Therefore, to better evaluate the model, we can repeat the process multiple times using different data to train and validate the model, and then averaging the metrics to derive an overall unbiased performance of the model (but notice that the obtained hypothesis might be different).\n",
"\n",
"There are multiple ways, and here we introduce two of them.\n",
"\n",
"1. k-fold cross-validation: \n",
" - After setting apart the test set, you split the data into k-folds (k blocks). \n",
" - We select one fold for validation and we train on all the remaining folds. \n",
" - We repeat the process k times, each time with a different validation fold. \n",
" - During each trial, you record the metrics and finally, you can calculate the min, max, mean value of the metrics to evaluate the model performance.\n",
"2. Randomly stratified sampling:\n",
" - After setting apart the test set, you randomly split the remaining data in a stratified way (usually according to the label) into training and validation with a certain proportion (e.g., 70% and 30%)\n",
" - You repeat the random split multiple times. In each trial, you end up with somewhat different data segmentation. \n",
" - During each trial, you record the metrics and finally, you can calculate the min, max, mean value of the metrics to evaluate the model performance.\n",
"\n",
"<center><img src=\"validation.png\" width=\"vp\"/></center>"
]
},
{
"cell_type": "markdown",
"id": "2c9ec483",
"metadata": {},
"source": [
"### 1.1 Validation curve\n",
"One way to find the best value of an hyper-parameter of a model (keeping the other ones constant) is the validation curve. It evaluates the model performance on validation set as we change the value of a certain hyper-parameters. Note that you can also simplify the work by using the ``validation_curve()`` (<a href=\"https://scikit-learn.org/stable/modules/learning_curve.html\">documentation</a>) provided by sklearn to do everything in one shot without manually setting up the for loop.\n",
"\n",
"Here we are finding the best value for max_depth in a RandomForestClassifier between 2 and 9, by using cross validation with 5 folds. Use as a metric the accuracy.\n",
"\n",
"Note: the function ``cross_validate`` automatically handles the data segmentation into training and validation sets, but it is possible to do it manually."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "5cae7d7e",
"metadata": {},
"outputs": [],
"source": [
"acc_train_means = []\n",
"acc_train_maxs = []\n",
"acc_train_mins = []\n",
"acc_val_means = []\n",
"acc_val_maxs = []\n",
"acc_val_mins = []\n",
"\n",
"#we choose the model RandomForestClassifier and change its hyper-parameter max_depth, using integer values from 2 to 9\n",
"for n in range(2, 10):\n",
" rf_clf = RandomForestClassifier(max_depth=n)\n",
" scores = cross_validate(rf_clf, X, y, cv=5, scoring='accuracy', return_train_score=True)\n",
" acc_train_means.append(scores['train_score'].mean())\n",
" acc_train_maxs.append(scores['train_score'].max())\n",
" acc_train_mins.append(scores['train_score'].min())\n",
" acc_val_means.append(scores['test_score'].mean())\n",
" acc_val_maxs.append(scores['test_score'].max())\n",
" acc_val_mins.append(scores['test_score'].min())"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "06528dcd",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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Zs+eLdq2bStWrFghNm/eLEaOHCkAiL179zqff62fW4fDIUaMGCGCgoLEmTNnhBBCrFy5UgAQ7777brXjK3/uwIEDhV6vFy+//LLYsmWLeO6550TLli3dvguHDx8WJpNJdO7cWaxevVps2bJFPPHEE0KlUonnn3/e2a/8OxMVFeX2HQkICBCnTp0SQghx8uRJMW7cOAHA+blPSUkRxcXFzs9L8+bNRa9evcTHH38sNm7cKG699Vah0Wic26hOVd+b8s9kTEyMePbZZ0VycrJYsGCB0Ov1YtKkSVfcXvn/T19fX7f2cePGCY1GIy5cuODSDkBMnTpVlJSUuNyu9Dml+oUBiOq1AQMGiNDQUGG1Wp1tTzzxhAAgjh8/XuVzbDabKCkpEYMHDxZjx451eexqAchut4vIyEjRrVs3l7/Izpw5I7RabZVhoJzdbhclJSXihRdeECEhIS7P79ixoxgwYIDbc6r6i7x3796icePGIi8vz2WfOnXqJJo2bercbnkAmjp1qss2X3vtNQFApKenVztWIYRo1aqVaNWqlSgqKqq2T00DkMlkEhcvXnRpP3jwoAAgli9f7tLeq1cv0b17d+f9pKQkoVKpxJ49e1z6ffrppwKA2Lhx4xX3p3xMFUPN0aNHq3yPdu/eLQCIv//97862AQMGCADi22+/veLrlLv//vsFAPHZZ58520pKSkSjRo0EAGfIFUKI7OxsoVarxaxZs6rd3pU+t1lZWaJp06aiV69e4ueffxY+Pj7i3nvvveoYN23aJACIhQsXurS//PLLbt+F+Ph40bRpU7eg+uijjwqDweD8/1r+nanuO/LAAw8426ZNm+b2OSkHQISFhQmz2exsy8jIECqVSiQlJV1xv64UgF577TWXvlOnThUGg+GqwaQ8AJUHmaysLLFs2TKhUqlcPicVx1/V7Z133rni61D9wSUwqtemTJmCrKwsfPXVVwAAm82GDz/8EP369UObNm2c/d5++21069YNBoMBGo0GWq0W3377LY4ePVqj10tNTcX58+dxzz33uCzxREdHIy4uzq3/d999hyFDhsBkMkGtVkOr1eLZZ59FdnY2MjMza7y/BQUF2L17N8aNGwc/Pz9nu1qtRmJiIv744w+kpqa6POcvf/mLy/0uXboAAH7//fdqX+f48eM4deoUpkyZAoPBUONxVmfQoEEICgpyaevc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+w1jx47Fr7/+CkmSIISAJEnOx+12uyfHSERERORRtSqCnj59Olq0aIELFy7Ax8cHhw4dwvbt29GjRw9s27bN86MkIiIi8qBazQClpKTgu+++Q6NGjaBSqaBWq3HLLbcgKSkJjz/+OPbv3+/5kRIRERF5SK1mgOx2O/z8/AAAoaGhOH/+PAAgOjoaqampnh0hERERkYfVagaoU6dOOHjwIFq2bInY2Fi89tpr0Ol0WL58OVq2bOn5URIRERF5UK0C0Ny5c1FQUAAAeOmllzBy5Ej069cPISEhWL9+vafHSERERORRkhBCeGJDFy9eRFBQkMvRYA2V2WyGyWRCbm4uAgIC5B4OERERXYOa/H577MJdwcHBntoUERERUZ2qVRE0ERERUUPGAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKI3sAWrp0KVq0aAGDwYDu3btjx44dV+y/Zs0adO3aFT4+PoiIiMCkSZOQnZ3t0uezzz5Dhw4doNfr0aFDB2zYsKGO94KIiIgaElkD0Pr16zFjxgzMmTMH+/fvR79+/TB8+HCkpaVV2X/nzp247777MGXKFBw+fBiffPIJ9uzZgwceeMDZJyUlBQkJCUhMTMSBAweQmJiI8ePHY/fu3V7cMyIiIqrPJCGEkOvFY2Nj0a1bNyxbtszZ1r59e4wZMwZJSUlu/f/5z39i2bJlOHXqlLNt0aJFeO2113D27FkAQEJCAsxmMzZt2uTsM2zYMAQFBWHt2rXXNC6z2QyTyYTc3FwEBARc514SERGRN9Tk91u2GSCr1Yp9+/Zh6NChLu1Dhw7Frl27qnxOXFwc/vjjD2zcuBFCCFy4cAGffvopbr/9dmeflJQUt23Gx8dXu00iIiJSHtkCUFZWFux2O8LCwlzaw8LCkJGRUeVz4uLisGbNGiQkJECn0yE8PByBgYFYtGiRs09GRkaNtgkAFosFZrPZ5UZEREQ3LtmLoCVJcrkvhHBrK3fkyBE8/vjjePbZZ7Fv3z7897//xenTp/Hwww/XepsAkJSUBJPJ5LxFRUVd1z4RERFR/SZbAAoNDYVarXabmcnMzHSbwSmXlJSEvn374qmnnkKXLl0QHx+PpUuXYuXKlUhPTwcAhIeH12ibADB79mzk5uY6b+X1RERERHRjki0A6XQ6dO/eHcnJyS7tycnJiIuLq/I5hYWFUKlch6xWq4GyWR4A6NOnj9s2t2zZUu02AUCv1yMgIMDlRkRERDcujZwvPmvWLCQmJqJHjx7o06cPli9fjrS0NOeS1uzZs3Hu3DmsXr0aADBq1Cg8+OCDWLZsGeLj45Geno4ZM2agV69eiIyMBABMnz4d/fv3x6uvvorRo0fjyy+/xNatW7Fz5045d5WIiIjqEVkDUEJCArKzs/HCCy8gPT0dnTp1wsaNGxEdHQ0ASE9Pdzkn0MSJE5GXl4fFixfjiSeeQGBgIAYNGoRXX33V2ScuLg7r1q3D3LlzMW/ePLRq1Qrr169HbGysLPtIRERE9Y+s5wGqr3geICIiooanQZwHiIiIiEguDEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDiyB6ClS5eiRYsWMBgM6N69O3bs2FFt34kTJ0KSJLdbx44dnX1WrVpVZZ/i4mIv7RERERHVd7IGoPXr12PGjBmYM2cO9u/fj379+mH48OFIS0ursv/ChQuRnp7uvJ09exbBwcG48847XfoFBAS49EtPT4fBYPDSXhEREVF9J2sAWrBgAaZMmYIHHngA7du3x5tvvomoqCgsW7asyv4mkwnh4eHO2969e3Hp0iVMmjTJpZ8kSS79wsPDvbRHRERE1BDIFoCsViv27duHoUOHurQPHToUu3btuqZtrFixAkOGDEF0dLRLe35+PqKjo9G0aVOMHDkS+/fvv+J2LBYLzGazy42IiIhuXLIFoKysLNjtdoSFhbm0h4WFISMj46rPT09Px6ZNm/DAAw+4tLdr1w6rVq3CV199hbVr18JgMKBv3744ceJEtdtKSkqCyWRy3qKioq5jz4iIiKi+k70IWpIkl/tCCLe2qqxatQqBgYEYM2aMS3vv3r1x7733omvXrujXrx8+/vhjtG3bFosWLap2W7Nnz0Zubq7zdvbs2evYIyIiIqrvNHK9cGhoKNRqtdtsT2ZmptusUGVCCKxcuRKJiYnQ6XRX7KtSqdCzZ88rzgDp9Xro9foa7gERERE1VLLNAOl0OnTv3h3Jycku7cnJyYiLi7vic7dv346TJ09iypQpV30dIQR++eUXREREXPeYiYiI6MYg2wwQAMyaNQuJiYno0aMH+vTpg+XLlyMtLQ0PP/wwULY0de7cOaxevdrleStWrEBsbCw6derkts358+ejd+/eaNOmDcxmM9566y388ssvWLJkidf2i4iIiOo3WQNQQkICsrOz8cILLyA9PR2dOnXCxo0bnUd1paenu50TKDc3F5999hkWLlxY5TZzcnLw0EMPISMjAyaTCTfffDN++OEH9OrVyyv7RERERPWfJIQQcg+ivjGbzTCZTMjNzUVAQIDcwyEiIqJrUJPfb9mPAiMiIiLyNlmXwBo6u92OkpISuYfRIGm1WqjVarmHQURECsUAVAtCCGRkZCAnJ0fuoTRogYGBCA8Pv6bzPhEREXkSA1AtlIefxo0bw8fHhz/gNSSEQGFhITIzMwGApyggIiKvYwCqIbvd7gw/ISEhcg+nwTIajUDZiS8bN27M5TAiIvIqFkHXUHnNj4+Pj9xDafDK30PWURERkbcxANUSl72uH99DIiKSCwMQ1Urz5s3x5ptvyj0MIiKiWmENkILceuutuOmmmzwSXPbs2QNfX1+PjIuIiMjbGIDISQgBu90OjebqH4tGjRp5ZUxERER1gUtgCjFx4kRs374dCxcuhCRJkCQJq1atgiRJ2Lx5M3r06AG9Xo8dO3bg1KlTGD16NMLCwuDn54eePXti69atLturvAQmSRLeffddjB07Fj4+PmjTpg2++uorGfaUiIjo6hiAPEAIgUKrTZbbtV7KbeHChejTpw8efPBBpKenIz09HVFRUQCAp59+GklJSTh69Ci6dOmC/Px8jBgxAlu3bsX+/fsRHx+PUaNGuV2YtrL58+dj/PjxOHjwIEaMGIEJEybg4sWLHnmPiYiIPIlLYB5QVGJHh2c3y/LaR16Ih4/u6v8bTSYTdDodfHx8EB4eDgA4duwYAOCFF17Abbfd5uwbEhKCrl27Ou+/9NJL2LBhA7766is8+uij1b7GxIkTcffddwMA/vGPf2DRokX46aefMGzYsOvaRyIiIk/jDBChR48eLvcLCgrw9NNPo0OHDggMDISfnx+OHTt21RmgLl26OP/s6+sLf39/59meiYiI6hPOAHmAUavGkRfiZXvt61X5aK6nnnoKmzdvxj//+U+0bt0aRqMR48aNg9VqveJ2tFqty31JkuBwOK57fERERJ7GAOQBkiRd0zKU3HQ6Hex2+1X77dixAxMnTsTYsWMBAPn5+Thz5owXRkhEROQdXAJTkObNm2P37t04c+YMsrKyqp2dad26NT7//HP88ssvOHDgAO655x7O5BAR0Q2FAUhBnnzySajVanTo0AGNGjWqtqbnX//6F4KCghAXF4dRo0YhPj4e3bp18/p4iYiI6ookrvU4agUxm80wmUzIzc1FQECAy2PFxcU4ffo0WrRoAYPBINsYbwR8L4mIyJOu9PtdGWeAiIiISHEYgIiIiEhxGICIiIhIcRiAiIiISHEYgIiIiEhxGICIiIhIcRiAiIiISHEYgIiIiEhxGICIiIhIcRiA6Jo1b94cb775ptzDICIium4MQERERKQ4DEBERESkOAxACvHvf/8bTZo0gcPhcGn/y1/+gvvvvx+nTp3C6NGjERYWBj8/P/Ts2RNbt26VbbxERER1iQHIA4QQcBQWynITQlzTGO+8805kZWXh+++/d7ZdunQJmzdvxoQJE5Cfn48RI0Zg69at2L9/P+Lj4zFq1CikpaXV4TtHREQkD43cA7gRiKIipHbrLstrx/y8D5KPz1X7BQcHY9iwYfjoo48wePBgAMAnn3yC4OBgDB48GGq1Gl27dnX2f+mll7BhwwZ89dVXePTRR+t0H4iIiLyNM0AKMmHCBHz22WewWCwAgDVr1uCuu+6CWq1GQUEBnn76aXTo0AGBgYHw8/PDsWPHOANEREQ3JM4AeYBkNCLm532yvfa1GjVqFBwOB/7zn/+gZ8+e2LFjBxYsWAAAeOqpp7B582b885//ROvWrWE0GjFu3DhYrdY6HD0REZE8GIA8QJKka1qGkpvRaMQdd9yBNWvW4OTJk2jbti26dy9dutuxYwcmTpyIsWPHAgDy8/Nx5swZmUdMRERUNxiAFGbChAkYNWoUDh8+jHvvvdfZ3rp1a3z++ecYNWoUJEnCvHnz3I4YIyIiulGwBkhhBg0ahODgYKSmpuKee+5xtv/rX/9CUFAQ4uLiMGrUKMTHx6Nbt26yjpWIiKiucAZIYdRqNc6fP+/W3rx5c3z33XcubdOmTXO5zyUxIiK6UXAGiIiIiBSHAYiIiIgUhwGIiIiIFIcBiIiIiBSHAYiIiIgUhwGolq71IqRUPb6HREQkFwagGtJqtQCAwsJCuYfS4JW/h+XvKRERkbfwPEA1pFarERgYiMzMTACAj48PJEmSe1gNihAChYWFyMzMRGBgINRqtdxDIiIihWEAqoXw8HAAcIYgqp3AwEDne0lERORNDEC1IEkSIiIi0LhxY5SUlMg9nAZJq9Vy5oeIiGQjewBaunQpXn/9daSnp6Njx45488030a9fvyr7Tpw4Ee+//75be4cOHXD48GHn/c8++wzz5s3DqVOn0KpVK7z88svOq5x7klqt5o84ERFRAyRrEfT69esxY8YMzJkzB/v370e/fv0wfPhwpKWlVdl/4cKFSE9Pd97Onj2L4OBg3Hnnnc4+KSkpSEhIQGJiIg4cOIDExESMHz8eu3fv9uKeERERUX0mCRmPRY6NjUW3bt2wbNkyZ1v79u0xZswYJCUlXfX5X3zxBe644w6cPn0a0dHRAICEhASYzWZs2rTJ2W/YsGEICgrC2rVrr2lcZrMZJpMJubm5CAgIqNW+ERERkXfV5Pdbthkgq9WKffv2YejQoS7tQ4cOxa5du65pGytWrMCQIUOc4QdlM0CVtxkfH3/N2yQiIqIbn2w1QFlZWbDb7QgLC3NpDwsLQ0ZGxlWfn56ejk2bNuGjjz5yac/IyKjxNi0WCywWi/N+bm4uUJYkiYiIqGEo/92+lsUt2YugK59DRwhxTefVWbVqFQIDAzFmzJjr3mZSUhLmz5/v1h4VFXXVcRAREVH9kpeXB5PJdMU+sgWg0NBQqNVqt5mZzMxMtxmcyoQQWLlyJRITE6HT6VweCw8Pr/E2Z8+ejVmzZjnvOxwOXLx4ESEhIR4/yaHZbEZUVBTOnj2ryPoipe8/+B5w/xW+/+B7oPj9Rx2+B0II5OXlITIy8qp9ZQtAOp0O3bt3R3Jysssh6snJyRg9evQVn7t9+3acPHkSU6ZMcXusT58+SE5OxsyZM51tW7ZsQVxcXLXb0+v10Ov1Lm2BgYE13KOaCQgIUOwHH9x/gO8B91/h+w++B4rff9TRe3C1mZ9ysi6BzZo1C4mJiejRowf69OmD5cuXIy0tDQ8//DBQNjNz7tw5rF692uV5K1asQGxsLDp16uS2zenTp6N///549dVXMXr0aHz55ZfYunUrdu7c6bX9IiIiovpN1gCUkJCA7OxsvPDCC0hPT0enTp2wceNG51Fd6enpbucEys3NxWeffYaFCxdWuc24uDisW7cOc+fOxbx589CqVSusX78esbGxXtknIiIiqv9kL4KeOnUqpk6dWuVjq1atcmszmUxXvRL7uHHjMG7cOI+N0ZP0ej2ee+45tyU3pVD6/oPvAfdf4fsPvgeK33/Uk/dA1hMhEhEREclB1kthEBEREcmBAYiIiIgUhwGIiIiIFIcBiIiIiBSHAcgLkpKS0LNnT/j7+6Nx48YYM2YMUlNT5R6WVy1btgxdunRxnvSqT58+2LRpk9zDkk1SUhIkScKMGTPkHorXPP/885AkyeUWHh4u97C86ty5c7j33nsREhICHx8f3HTTTdi3b5/cw/Ka5s2bu30GJEnCtGnT5B6aV9hsNsydOxctWrSA0WhEy5Yt8cILL8DhcMg9NK/Jy8vDjBkzEB0dDaPRiLi4OOzZs0eWsch+GLwSbN++HdOmTUPPnj1hs9kwZ84cDB06FEeOHIGvr6/cw/OKpk2b4pVXXkHr1q0BAO+//z5Gjx6N/fv3o2PHjnIPz6v27NmD5cuXo0uXLnIPxes6duyIrVu3Ou+r1WpZx+NNly5dQt++fTFw4EBs2rQJjRs3xqlTp+r8rPP1yZ49e2C32533Dx06hNtuuw133nmnrOPylldffRVvv/023n//fXTs2BF79+7FpEmTYDKZMH36dLmH5xUPPPAADh06hA8++ACRkZH48MMPMWTIEBw5cgRNmjTx7mAEeV1mZqYAILZv3y73UGQVFBQk3n33XbmH4VV5eXmiTZs2Ijk5WQwYMEBMnz5d7iF5zXPPPSe6du0q9zBk87e//U3ccsstcg+jXpk+fbpo1aqVcDgccg/FK26//XYxefJkl7Y77rhD3HvvvbKNyZsKCwuFWq0W33zzjUt7165dxZw5c7w+Hi6BySA3NxcAEBwcLPdQZGG327Fu3ToUFBSgT58+cg/Hq6ZNm4bbb78dQ4YMkXsosjhx4gQiIyPRokUL3HXXXfjtt9/kHpLXfPXVV+jRowfuvPNONG7cGDfffDPeeecduYclG6vVig8//BCTJ0/2+EWn66tbbrkF3377LY4fPw4AOHDgAHbu3IkRI0bIPTSvsNlssNvtMBgMLu1Go1Gey1V5PXIpnMPhEKNGjVLkvwQPHjwofH19hVqtFiaTSfznP/+Re0hetXbtWtGpUydRVFQkhBCKmwHauHGj+PTTT8XBgwedM2BhYWEiKytL7qF5hV6vF3q9XsyePVv8/PPP4u233xYGg0G8//77cg9NFuvXrxdqtVqcO3dO7qF4jcPhEM8884yQJEloNBohSZL4xz/+IfewvKpPnz5iwIAB4ty5c8Jms4kPPvhASJIk2rZt6/WxMAB52dSpU0V0dLQ4e/as3EPxOovFIk6cOCH27NkjnnnmGREaGioOHz4s97C8Ii0tTTRu3Fj88ssvzjalBaDK8vPzRVhYmHjjjTfkHopXaLVa0adPH5e2xx57TPTu3Vu2Mclp6NChYuTIkXIPw6vWrl0rmjZtKtauXSsOHjwoVq9eLYKDg8WqVavkHprXnDx5UvTv318AEGq1WvTs2VNMmDBBtG/f3utjYQDyokcffVQ0bdpU/Pbbb3IPpV4YPHiweOihh+Qehlds2LDB+YUvvwEQkiQJtVotbDab3EOUxZAhQ8TDDz8s9zC8olmzZmLKlCkubUuXLhWRkZGyjUkuZ86cESqVSnzxxRdyD8WrmjZtKhYvXuzS9uKLL4qYmBjZxiSX/Px8cf78eSGEEOPHjxcjRozw+hh4FJgXCCHw2GOPYcOGDdi2bRtatGgh95DqBSEELBaL3MPwisGDB+PXX391aZs0aRLatWuHv/3tb4o6GqqcxWLB0aNH0a9fP7mH4hV9+/Z1O/3F8ePHER0dLduY5PLee++hcePGuP322+UeilcVFhZCpXItvVWr1Yo6DL6cr68vfH19cenSJWzevBmvvfaa18fAAOQF06ZNw0cffYQvv/wS/v7+yMjIAMqubG80GuUenlf8/e9/x/DhwxEVFYW8vDysW7cO27Ztw3//+1+5h+YV/v7+6NSpk0ubr68vQkJC3NpvVE8++SRGjRqFZs2aITMzEy+99BLMZjPuv/9+uYfmFTNnzkRcXBz+8Y9/YPz48fjpp5+wfPlyLF++XO6heZXD4cB7772H+++/HxqNsn6CRo0ahZdffhnNmjVDx44dsX//fixYsACTJ0+We2hes3nzZgghEBMTg5MnT+Kpp55CTEwMJk2a5P3BeH3OSYEAVHl777335B6a10yePFlER0cLnU4nGjVqJAYPHiy2bNki97BkpbQaoISEBBERESG0Wq2IjIwUd9xxh2JqwMp9/fXXolOnTkKv14t27dqJ5cuXyz0kr9u8ebMAIFJTU+UeiteZzWYxffp00axZM2EwGETLli3FnDlzhMVikXtoXrN+/XrRsmVLodPpRHh4uJg2bZrIycmRZSySKP2BJiIiIlIMngeIiIiIFIcBiIiIiBSHAYiIiIgUhwGIiIiIFIcBiIiIiBSHAYiIiIgUhwGIiIiIFIcBiIgUT5IkfPHFF3X+Otu2bYMkScjJyanz1yKiK2MAIiKqA7feeitmzJgh9zCIqBoMQERERKQ4DEBEVOduvfVWPPbYY5gxYwaCgoIQFhaG5cuXo6CgAJMmTYK/vz9atWqFTZs2OZ9jt9sxZcoUtGjRAkajETExMVi4cKHz8eLiYnTs2BEPPfSQs+306dMwmUx45513qh3LiRMn0L9/fxgMBnTo0AHJyclufc6dO4eEhAQEBQUhJCQEo0ePxpkzZ5yPT5w4EWPGjMH8+fPRuHFjBAQE4P/+7/9gtVqdj2/fvh0LFy6EJEmQJMnl+fv27UOPHj3g4+ODuLg4t6vEE1HdYwAiIq94//33ERoaip9++gmPPfYYHnnkEdx5552Ii4vDzz//jPj4eCQmJqKwsBAou2p406ZN8fHHH+PIkSN49tln8fe//x0ff/wxAMBgMGDNmjV4//338cUXX8ButyMxMREDBw7Egw8+WOUYHA4H7rjjDqjVavz44494++238be//c2lT2FhIQYOHAg/Pz/88MMP2LlzJ/z8/DBs2DBnwAGAb7/9FkePHsX333+PtWvXYsOGDZg/fz4AYOHChejTpw8efPBBpKenIz09HVFRUc7nzpkzB2+88Qb27t0LjUajqKuBE9UbslyClYgUZcCAAeKWW25x3rfZbMLX11ckJiY629LT0wUAkZKSUu12pk6dKv7617+6tL322msiNDRUPPbYYyI8PFz8+eef1T5/8+bNQq1Wi7NnzzrbNm3aJACIDRs2CCGEWLFihYiJiREOh8PZx2KxCKPRKDZv3iyEEOL+++8XwcHBoqCgwNln2bJlws/PT9jtduc+T58+3eX1v//+ewFAbN261dn2n//8RwAQRUVF1Y6biDyPM0BE5BVdunRx/lmtViMkJASdO3d2toWFhQEAMjMznW1vv/02evTogUaNGsHPzw/vvPMO0tLSXLb7xBNPICYmBosWLcJ7772H0NDQasdw9OhRNGvWDE2bNnW29enTx6XPvn37cPLkSfj7+8PPzw9+fn4IDg5GcXExTp065ezXtWtX+Pj4uGwnPz8fZ8+erdF7ERER4bbfRFT3NHIPgIiUQavVutyXJMmlTZIkoGyZCgA+/vhjzJw5E2+88Qb69OkDf39/vP7669i9e7fLdjIzM5Gamgq1Wo0TJ05g2LBh1Y5BCOHWVv665RwOB7p37441a9a49W3UqNFV97Py9qpypf0mIu9gACKiemnHjh2Ii4vD1KlTnW0VZ2DKTZ48GZ06dcKDDz6IKVOmYPDgwejQoUOV2+zQoQPS0tJw/vx5REZGAgBSUlJc+nTr1g3r1693FjdX58CBAygqKoLRaAQA/Pjjj/Dz83POLul0Otjt9lruPRHVNS6BEVG91Lp1a+zduxebN2/G8ePHMW/ePOzZs8elz5IlS5CSkoLVq1fjnnvuwbhx4zBhwgSXYuWKhgwZgpiYGNx33304cOAAduzYgTlz5rj0mTBhAkJDQzF69Gjs2LEDp0+fxvbt2zF9+nT88ccfzn5WqxVTpkzBkSNHsGnTJjz33HN49NFHoVKV/rXavHlz7N69G2fOnEFWVhZneIjqGQYgIqqXHn74Ydxxxx1ISEhAbGwssrOzXWaDjh07hqeeegpLly51HmG1ZMkS5OTkYN68eVVuU6VSYcOGDbBYLOjVqxceeOABvPzyyy59fHx88MMPP6BZs2a444470L59e0yePBlFRUUuM0KDBw9GmzZt0L9/f4wfPx6jRo3C888/73z8ySefhFqtRocOHdCoUSO32iUikpckqloUJyKiak2cOBE5OTleuXwGEdUNzgARERGR4jAAERERkeJwCYyIiIgUhzNAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOAxAREREpDgMQERERKQ4DEBERESkOP8PONxdFn6zZvEAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure()\n",
"x = list(range(2, 10))\n",
"plt.plot(x, acc_train_means, color='tab:blue', label='train')\n",
"plt.fill_between(x, acc_train_mins, acc_train_maxs, alpha=0.5, color='tab:blue')\n",
"plt.plot(x, acc_val_means, color='tab:red', label='val')\n",
"plt.fill_between(x, acc_val_mins, acc_val_maxs, alpha=0.5, color='tab:red')\n",
"plt.xlabel('max depth')\n",
"plt.ylabel('accuracy')\n",
"plt.legend()\n",
"plt.title(\"Validation curve for max depth in RF\")\n",
"plt.ylim(0.7,1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "542195cd",
"metadata": {},
"source": [
"### 1.2 Grid search\n",
"The grid search exhaustively use all combinations of candidates from a grid of hyper-parameter values. It is used to identify the best combinations of ML hyper-parameters for a task, and can be used either for supervised or unsupervised learning problems. First, you select a bunch of hyper-parameters that you want to optimize, and for each of them, determine its value range. Then, the grid search will iterate over all the possible combinations of values of hyper-parameters, building and evaluating a model on each of them, and eventually choosing the one with best performance. Note that we are not doing a cross validation for simplicity, but you can also use ``GridSearchCV`` (<a href=\"https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html\">documentation</a>) provided by sklearn to do it in one line of code.\n",
"\n",
"Here we are finding the best combination of values for max_depth and n_estimators in a RandomForestClassifier, by using a single validation set. We use the accuracy metric to compare the performance.\n",
"\n",
"For using a single validation set, we further split the previous ``X`` and ``y`` into training and validation sets, so that their occupation in the original dataset will be 50% and 20%."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "89b0827e",
"metadata": {},
"outputs": [],
"source": [
"# note that here we do not perform standardization for simplicity\n",
"X_train, X_val, y_train, y_val = train_test_split(\n",
" X, \n",
" y, \n",
" stratify = y, \n",
" train_size = 0.5/0.7, \n",
" random_state = 15\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "b674f0b9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"#trees: 10, max depth: 2, accuracy: train - 0.9866666666666667 | val - 0.9\n",
"#trees: 10, max depth: 3, accuracy: train - 0.9866666666666667 | val - 0.9\n",
"#trees: 10, max depth: 4, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 10, max depth: 5, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 10, max depth: None, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 20, max depth: 2, accuracy: train - 0.9866666666666667 | val - 0.9\n",
"#trees: 20, max depth: 3, accuracy: train - 0.9866666666666667 | val - 0.9\n",
"#trees: 20, max depth: 4, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 20, max depth: 5, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 20, max depth: None, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 30, max depth: 2, accuracy: train - 0.9866666666666667 | val - 0.9333333333333333\n",
"#trees: 30, max depth: 3, accuracy: train - 0.9866666666666667 | val - 0.9333333333333333\n",
"#trees: 30, max depth: 4, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 30, max depth: 5, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 30, max depth: None, accuracy: train - 1.0 | val - 0.9\n",
"#trees: 40, max depth: 2, accuracy: train - 0.9866666666666667 | val - 0.9333333333333333\n",
"#trees: 40, max depth: 3, accuracy: train - 0.9866666666666667 | val - 0.9333333333333333\n",
"#trees: 40, max depth: 4, accuracy: train - 1.0 | val - 0.9333333333333333\n",
"#trees: 40, max depth: 5, accuracy: train - 1.0 | val - 0.9333333333333333\n",
"#trees: 40, max depth: None, accuracy: train - 1.0 | val - 0.9333333333333333\n"
]
}
],
"source": [
"# e.g., RF - parameters to be optimized:\n",
" # n_estimators: number of trees\n",
" # max_depth: the maximum depth of trees\n",
"\n",
"# iterate over all possible combinations\n",
"for n_estimators in range(10, 50, 10):\n",
" for max_depth in [2, 3, 4, 5, None]:\n",
" # initialize and fit a model per pair of parameters\n",
" rf_tmp = RandomForestClassifier(n_estimators=n_estimators, max_depth=max_depth, random_state=12)\n",
" rf_tmp.fit(X_train, y_train)\n",
" # here we only refer to accuracy for simplicity\n",
" acc_train = accuracy_score(y_train, rf_tmp.predict(X_train))\n",
" acc_val = accuracy_score(y_val, rf_tmp.predict(X_val))\n",
" print(f'#trees: {n_estimators}, max depth: {max_depth}, accuracy: train - {acc_train} | val - {acc_val}')"
]
},
{
"cell_type": "markdown",
"id": "534c3c92",
"metadata": {},
"source": [
"### 1.3 Learning curves\n",
"The learning curve shows how performance changes by varying (i.e., reducing) the available data points (e.g., sample size, number of features).\n",
"\n",
"Normally, we need a sampling strategy to create subsets of the data, and such data should be representative. Available sampling strategies are arithmetic sampling, geometric sampling, random sampling, etc. \n",
"\n",
"You can start with a small portion of the original data to train the model and check the performance, and then keep increasing the portion, observing the performance with respect to the amount of data. Note that, given a value of the portion, the sampling randomly selects data, possibly impacting performance. Therefore, to take it into consideration we can use multiple random states to sample data and computing the statistics of performance (mean, max, min). \n",
"\n",
"Here we are using a Decision Tree classifier with default hyper-parameters. Start from a subset of training set containing 10% of the data up to 90%. Use randomly stratified sampling and repeat the computation 10 times for each subset with a different initialization state. Use as a metric the accuracy."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "307ba80b",
"metadata": {},
"outputs": [],
"source": [
"# here we only refer to accuracy for simplicity\n",
"info_accuracy_train = []\n",
"info_accuracy_val = []\n",
"\n",
"for train_size in np.arange(0.1, 1, 0.1):\n",
" # select 10 random states\n",
" random_states = set()\n",
" while len(random_states) < 10:\n",
" n = random.randint(0,1000000)\n",
" random_states.add(n)\n",
"\n",
" accuraries_train_tmp = []\n",
" accuraries_val_tmp = []\n",
" \n",
" # iterate over all random states with same training size to derive the 10 different performance\n",
" for random_state in random_states:\n",
" # do a stratified random sampling from the training set \n",
" sss = StratifiedShuffleSplit(n_splits=1, train_size=train_size, random_state=random_state)\n",
" index_selected = list(sss.split(X_train, y_train))[0][0]\n",
" X_train_selected = X_train.iloc[index_selected]\n",
" y_train_selected = y_train.iloc[index_selected]\n",
" \n",
" # initialize and fit a DT model per time\n",
" dt_tmp = DecisionTreeClassifier(random_state=0)\n",
" dt_tmp.fit(X_train_selected, y_train_selected)\n",
" accuraries_train_tmp.append(accuracy_score(y_train_selected, dt_tmp.predict(X_train_selected)))\n",
" accuraries_val_tmp.append(accuracy_score(y_val, dt_tmp.predict(X_val)))\n",
"\n",
" # calculate the statistics to generate overall performance\n",
" accuraries_tmp = np.array(accuraries_train_tmp)\n",
" mean_acc = accuraries_tmp.mean()\n",
" min_acc = accuraries_tmp.min()\n",
" max_acc = accuraries_tmp.max()\n",
" info_accuracy_train.append((mean_acc, min_acc, max_acc))\n",
" \n",
" accuraries_tmp = np.array(accuraries_val_tmp)\n",
" mean_acc = accuraries_tmp.mean()\n",
" min_acc = accuraries_tmp.min()\n",
" max_acc = accuraries_tmp.max()\n",
" info_accuracy_val.append((mean_acc, min_acc, max_acc))"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "1ff4a1d0",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "'yerr' must not contain negative values",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[16], line 12\u001b[0m\n\u001b[1;32m 1\u001b[0m plt\u001b[38;5;241m.\u001b[39mfigure()\n\u001b[1;32m 2\u001b[0m plt\u001b[38;5;241m.\u001b[39merrorbar(\n\u001b[1;32m 3\u001b[0m [train_size \u001b[38;5;28;01mfor\u001b[39;00m train_size \u001b[38;5;129;01min\u001b[39;00m np\u001b[38;5;241m.\u001b[39marange(\u001b[38;5;241m0.1\u001b[39m, \u001b[38;5;241m1.0\u001b[39m, \u001b[38;5;241m0.1\u001b[39m)], \u001b[38;5;66;03m# x-location of each error bar\u001b[39;00m\n\u001b[1;32m 4\u001b[0m [info[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m info \u001b[38;5;129;01min\u001b[39;00m info_accuracy_train], \u001b[38;5;66;03m# y-location of each error bar\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 10\u001b[0m color\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtab:blue\u001b[39m\u001b[38;5;124m'\u001b[39m, label\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtrain\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 11\u001b[0m )\n\u001b[0;32m---> 12\u001b[0m \u001b[43mplt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43merrorbar\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 13\u001b[0m \u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[43mtrain_size\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mtrain_size\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43marange\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m0.1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1.0\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0.1\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# x-location of each error bar\u001b[39;49;00m\n\u001b[1;32m 14\u001b[0m \u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[43minfo\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minfo\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minfo_accuracy_val\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# y-location of each error bar\u001b[39;49;00m\n\u001b[1;32m 15\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# the size of each error bar\u001b[39;49;00m\n\u001b[1;32m 16\u001b[0m \u001b[43m \u001b[49m\u001b[43myerr\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m[\u001b[49m\n\u001b[1;32m 17\u001b[0m \u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[43minfo\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43minfo\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minfo\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minfo_accuracy_val\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 18\u001b[0m \u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[43minfo\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43minfo\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minfo\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minfo_accuracy_val\u001b[49m\u001b[43m]\u001b[49m\n\u001b[1;32m 19\u001b[0m \u001b[43m \u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 20\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolor\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mtab:red\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlabel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mval\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\n\u001b[1;32m 21\u001b[0m \u001b[43m)\u001b[49m\n\u001b[1;32m 22\u001b[0m plt\u001b[38;5;241m.\u001b[39mgrid()\n\u001b[1;32m 23\u001b[0m plt\u001b[38;5;241m.\u001b[39mxlabel(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mPortion of training set\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"File \u001b[0;32m/usr/lib64/python3.13/site-packages/matplotlib/pyplot.py:3246\u001b[0m, in \u001b[0;36merrorbar\u001b[0;34m(x, y, yerr, xerr, fmt, ecolor, elinewidth, capsize, barsabove, lolims, uplims, xlolims, xuplims, errorevery, capthick, data, **kwargs)\u001b[0m\n\u001b[1;32m 3225\u001b[0m \u001b[38;5;129m@_copy_docstring_and_deprecators\u001b[39m(Axes\u001b[38;5;241m.\u001b[39merrorbar)\n\u001b[1;32m 3226\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21merrorbar\u001b[39m(\n\u001b[1;32m 3227\u001b[0m x: \u001b[38;5;28mfloat\u001b[39m \u001b[38;5;241m|\u001b[39m ArrayLike,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 3244\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[1;32m 3245\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ErrorbarContainer:\n\u001b[0;32m-> 3246\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mgca\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43merrorbar\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 3247\u001b[0m \u001b[43m \u001b[49m\u001b[43mx\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3248\u001b[0m \u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3249\u001b[0m \u001b[43m \u001b[49m\u001b[43myerr\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43myerr\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3250\u001b[0m \u001b[43m \u001b[49m\u001b[43mxerr\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mxerr\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3251\u001b[0m \u001b[43m \u001b[49m\u001b[43mfmt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfmt\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3252\u001b[0m \u001b[43m \u001b[49m\u001b[43mecolor\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mecolor\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3253\u001b[0m \u001b[43m \u001b[49m\u001b[43melinewidth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43melinewidth\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3254\u001b[0m \u001b[43m \u001b[49m\u001b[43mcapsize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcapsize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3255\u001b[0m \u001b[43m \u001b[49m\u001b[43mbarsabove\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbarsabove\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3256\u001b[0m \u001b[43m \u001b[49m\u001b[43mlolims\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlolims\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3257\u001b[0m \u001b[43m \u001b[49m\u001b[43muplims\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43muplims\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3258\u001b[0m \u001b[43m \u001b[49m\u001b[43mxlolims\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mxlolims\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3259\u001b[0m \u001b[43m \u001b[49m\u001b[43mxuplims\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mxuplims\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3260\u001b[0m \u001b[43m \u001b[49m\u001b[43merrorevery\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43merrorevery\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3261\u001b[0m \u001b[43m \u001b[49m\u001b[43mcapthick\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcapthick\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3262\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mdata\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m}\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mis\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mnot\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3263\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3264\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m/usr/lib64/python3.13/site-packages/matplotlib/__init__.py:1476\u001b[0m, in \u001b[0;36m_preprocess_data.<locals>.inner\u001b[0;34m(ax, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1473\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 1474\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21minner\u001b[39m(ax, \u001b[38;5;241m*\u001b[39margs, data\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 1475\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m-> 1476\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1477\u001b[0m \u001b[43m \u001b[49m\u001b[43max\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1478\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mmap\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43msanitize_sequence\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1479\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m{\u001b[49m\u001b[43mk\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43msanitize_sequence\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mv\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mitems\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1481\u001b[0m bound \u001b[38;5;241m=\u001b[39m new_sig\u001b[38;5;241m.\u001b[39mbind(ax, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 1482\u001b[0m auto_label \u001b[38;5;241m=\u001b[39m (bound\u001b[38;5;241m.\u001b[39marguments\u001b[38;5;241m.\u001b[39mget(label_namer)\n\u001b[1;32m 1483\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m bound\u001b[38;5;241m.\u001b[39mkwargs\u001b[38;5;241m.\u001b[39mget(label_namer))\n",
"File \u001b[0;32m/usr/lib64/python3.13/site-packages/matplotlib/axes/_axes.py:3743\u001b[0m, in \u001b[0;36mAxes.errorbar\u001b[0;34m(self, x, y, yerr, xerr, fmt, ecolor, elinewidth, capsize, barsabove, lolims, uplims, xlolims, xuplims, errorevery, capthick, **kwargs)\u001b[0m\n\u001b[1;32m 3740\u001b[0m res \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mzeros(err\u001b[38;5;241m.\u001b[39mshape, dtype\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mbool\u001b[39m) \u001b[38;5;66;03m# Default in case of nan\u001b[39;00m\n\u001b[1;32m 3741\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m np\u001b[38;5;241m.\u001b[39many(np\u001b[38;5;241m.\u001b[39mless(err, \u001b[38;5;241m-\u001b[39merr, out\u001b[38;5;241m=\u001b[39mres, where\u001b[38;5;241m=\u001b[39m(err \u001b[38;5;241m==\u001b[39m err))):\n\u001b[1;32m 3742\u001b[0m \u001b[38;5;66;03m# like err<0, but also works for timedelta and nan.\u001b[39;00m\n\u001b[0;32m-> 3743\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 3744\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdep_axis\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124merr\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m must not contain negative values\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 3745\u001b[0m \u001b[38;5;66;03m# This is like\u001b[39;00m\n\u001b[1;32m 3746\u001b[0m \u001b[38;5;66;03m# elow, ehigh = np.broadcast_to(...)\u001b[39;00m\n\u001b[1;32m 3747\u001b[0m \u001b[38;5;66;03m# return dep - elow * ~lolims, dep + ehigh * ~uplims\u001b[39;00m\n\u001b[1;32m 3748\u001b[0m \u001b[38;5;66;03m# except that broadcast_to would strip units.\u001b[39;00m\n\u001b[1;32m 3749\u001b[0m low, high \u001b[38;5;241m=\u001b[39m dep \u001b[38;5;241m+\u001b[39m np\u001b[38;5;241m.\u001b[39mvstack([\u001b[38;5;241m-\u001b[39m(\u001b[38;5;241m1\u001b[39m \u001b[38;5;241m-\u001b[39m lolims), \u001b[38;5;241m1\u001b[39m \u001b[38;5;241m-\u001b[39m uplims]) \u001b[38;5;241m*\u001b[39m err\n",
"\u001b[0;31mValueError\u001b[0m: 'yerr' must not contain negative values"
]
},
{
"data": {
"image/png": "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nJyc8Nhjj+G7775Dv3796jwuERERtW4mP6emJeNzaoiIiFqeRnlODREREVFzxVBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLLAUENERESywFBDREREssBQQ0RERLJgVqiJi4uDn58frK2tERAQgCNHjjyw/6pVq+Dv7w8bGxt07twZGzduNPr+mjVrEBoaChcXF7i4uGDgwIE4ceKEUZ8FCxZAoVAYbZ6enuaUT0RERDJkcqjZsmULoqOjMWfOHKSnpyM0NBTh4eHIysqqtX98fDxiYmKwYMECnD17FgsXLsQbb7yBL7/80tDn0KFDGD16NL799lscPXoUHTp0QFhYGK5evWp0rG7duiE3N9ew/fTTT+bMmYiIiGRIIYQQpuwQGBiIPn36ID4+3tDm7++P4cOHIzY2tkb/4OBghISEYMmSJYa26OhonDx5EikpKbWOodfr4eLigpUrV2LcuHHA3ZWa3bt349SpU6aUa0Sj0cDJyQklJSVwdHQ0+zhERETUdOr6+W3SSo1Op0NaWhrCwsKM2sPCwpCamlrrPlqtFtbW1kZtNjY2OHHiBCorK2vdp7y8HJWVlXB1dTVqv3jxItq1awc/Pz+MGjUKly9ffmC9Wq0WGo3GaCMiIiJ5MinUFBQUQK/Xw8PDw6jdw8MDeXl5te4zaNAgrF27FmlpaRBC4OTJk0hISEBlZSUKCgpq3Wf27Nlo3749Bg4caGgLDAzExo0bceDAAaxZswZ5eXkIDg5GYWHhfeuNjY2Fk5OTYfPx8TFlukRERNSCmHWhsEKhMPpaCFGj7Z65c+ciPDwcQUFBUKvVGDZsGCZMmAAAUKlUNfp/8MEHSEpKws6dO41WeMLDw/Hyyy+jR48eGDhwIPbu3QsA2LBhw33rjImJQUlJiWHLzs42Z7pERETUApgUatzc3KBSqWqsyuTn59dYvbnHxsYGCQkJKC8vx5UrV5CV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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure()\n",
"plt.errorbar(\n",
" [train_size for train_size in np.arange(0.1, 1.0, 0.1)], # x-location of each error bar\n",
" [info[0] for info in info_accuracy_train], # y-location of each error bar\n",
" # the size of each error bar\n",
" yerr=[\n",
" [info[0]-info[1] for info in info_accuracy_train], \n",
" [info[2]-info[0] for info in info_accuracy_train]\n",
" ], \n",
" color='tab:blue', label='train'\n",
")\n",
"plt.errorbar(\n",
" [train_size for train_size in np.arange(0.1, 1.0, 0.1)], # x-location of each error bar\n",
" [info[0] for info in info_accuracy_val], # y-location of each error bar\n",
" # the size of each error bar\n",
" yerr=[\n",
" [info[0]-info[1] for info in info_accuracy_val], \n",
" [info[2]-info[0] for info in info_accuracy_val]\n",
" ], \n",
" color='tab:red', label='val'\n",
")\n",
"plt.grid()\n",
"plt.xlabel('Portion of training set')\n",
"plt.ylabel('Accuracy')\n",
"plt.title('Learning curve for DT')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "ab5122d0",
"metadata": {},
"source": [
"### 2. Exercise - RTP dataset\n",
"In this exercise, we employ the same RTP dataset as in the previous laboratory, but we focus on multi-class classification instead of the binary one. The classes are **Audio, FEC-Audio, High Quality Video, Medium Quality Video, Low Quality Video, FEC-Video, and Screen Sharing**. \n",
"\n",
"You will:\n",
"- Load the dataset\n",
"- Perform necessary data processing\n",
"- Perform validation curve for k-NN classifier\n",
"- Perform grid search for decision tree classifier\n",
"- Choose one of the models with best hyper-parameters\n",
"- With this model and hyper-parameters, draw a learning curve"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "44ec27b7",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>interarrival_std</th>\n",
" <th>interarrival_mean</th>\n",
" <th>interarrival_min</th>\n",
" <th>interarrival_max</th>\n",
" <th>interarrival_max_min_diff</th>\n",
" <th>interarrival_p10</th>\n",
" <th>interarrival_p20</th>\n",
" <th>interarrival_p25</th>\n",
" <th>interarrival_p30</th>\n",
" <th>interarrival_p40</th>\n",
" <th>...</th>\n",
" <th>rtp_interarrival_max_min_R</th>\n",
" <th>rtp_interarrival_kurtosis</th>\n",
" <th>rtp_interarrival_skew</th>\n",
" <th>rtp_interarrival_moment3</th>\n",
" <th>rtp_interarrival_moment4</th>\n",
" <th>rtp_interarrival_len_unique_percent</th>\n",
" <th>rtp_interarrival_max_value_count_percent</th>\n",
" <th>rtp_interarrival_min_max_R</th>\n",
" <th>rtp_marker_sum_check</th>\n",
" <th>label</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.001927</td>\n",
" <td>0.010000</td>\n",
" <td>0.004951</td>\n",
" <td>0.014423</td>\n",
" <td>0.009472</td>\n",
" <td>7.619953e-05</td>\n",
" <td>8.045912e-05</td>\n",
" <td>8.572698e-05</td>\n",
" <td>9.030223e-05</td>\n",
" <td>9.799051e-05</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.010000</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>0</td>\n",
" <td>Audio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.000515</td>\n",
" <td>0.020009</td>\n",
" <td>0.019227</td>\n",
" <td>0.021251</td>\n",
" <td>0.002024</td>\n",
" <td>1.931565e-04</td>\n",
" <td>1.953020e-04</td>\n",
" <td>1.958430e-04</td>\n",
" <td>1.965890e-04</td>\n",
" <td>1.985469e-04</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.020000</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>0</td>\n",
" <td>Audio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.041315</td>\n",
" <td>0.019994</td>\n",
" <td>0.000000</td>\n",
" <td>0.143393</td>\n",
" <td>0.143393</td>\n",
" <td>9.536743e-09</td>\n",
" <td>9.536743e-09</td>\n",
" <td>9.536743e-09</td>\n",
" <td>1.907349e-08</td>\n",
" <td>4.053116e-08</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.019231</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>0</td>\n",
" <td>Audio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.008119</td>\n",
" <td>0.019954</td>\n",
" <td>0.000873</td>\n",
" <td>0.044432</td>\n",
" <td>0.043559</td>\n",
" <td>9.701633e-05</td>\n",
" <td>1.477895e-04</td>\n",
" <td>1.699674e-04</td>\n",
" <td>1.779909e-04</td>\n",
" <td>1.895509e-04</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.020000</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>0</td>\n",
" <td>Audio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0.018683</td>\n",
" <td>0.020117</td>\n",
" <td>0.000001</td>\n",
" <td>0.121093</td>\n",
" <td>0.121092</td>\n",
" <td>1.023531e-05</td>\n",
" <td>7.453918e-05</td>\n",
" <td>1.209468e-04</td>\n",
" <td>1.324451e-04</td>\n",
" <td>1.531601e-04</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.021739</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>0</td>\n",
" <td>Audio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>139995</th>\n",
" <td>0.000799</td>\n",
" <td>0.337698</td>\n",
" <td>0.336812</td>\n",
" <td>0.338365</td>\n",
" <td>0.001553</td>\n",
" <td>3.370330e-03</td>\n",
" <td>3.372540e-03</td>\n",
" <td>3.373646e-03</td>\n",
" <td>3.374751e-03</td>\n",
" <td>3.376961e-03</td>\n",
" <td>...</td>\n",
" <td>0.511905</td>\n",
" <td>-1.500000</td>\n",
" <td>-0.707107</td>\n",
" <td>-2.211840e+08</td>\n",
" <td>3.185050e+11</td>\n",
" <td>0.666667</td>\n",
" <td>0.666667</td>\n",
" <td>0.488095</td>\n",
" <td>3</td>\n",
" <td>ScreenSharing</td>\n",
" </tr>\n",
" <tr>\n",
" <th>139996</th>\n",
" <td>0.159892</td>\n",
" <td>0.239946</td>\n",
" <td>0.000108</td>\n",
" <td>0.320163</td>\n",
" <td>0.320055</td>\n",
" <td>9.596729e-04</td>\n",
" <td>1.918266e-03</td>\n",
" <td>2.397562e-03</td>\n",
" <td>2.876859e-03</td>\n",
" <td>3.196862e-03</td>\n",
" <td>...</td>\n",
" <td>1.000000</td>\n",
" <td>-0.671026</td>\n",
" <td>-1.148811</td>\n",
" <td>-2.524719e+12</td>\n",
" <td>6.654528e+16</td>\n",
" <td>1.000000</td>\n",
" <td>0.250000</td>\n",
" <td>0.000000</td>\n",
" <td>3</td>\n",
" <td>ScreenSharing</td>\n",
" </tr>\n",
" <tr>\n",
" <th>139997</th>\n",
" <td>0.045574</td>\n",
" <td>0.040176</td>\n",
" <td>0.000012</td>\n",
" <td>0.151814</td>\n",
" <td>0.151802</td>\n",
" <td>1.705837e-05</td>\n",
" <td>3.843689e-05</td>\n",
" <td>6.171942e-05</td>\n",
" <td>1.125135e-04</td>\n",
" <td>2.727780e-04</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.043478</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>23</td>\n",
" <td>ScreenSharing</td>\n",
" </tr>\n",
" <tr>\n",
" <th>139998</th>\n",
" <td>0.028728</td>\n",
" <td>0.325410</td>\n",
" <td>0.299745</td>\n",
" <td>0.356444</td>\n",
" <td>0.056699</td>\n",
" <td>3.038041e-03</td>\n",
" <td>3.078630e-03</td>\n",
" <td>3.098925e-03</td>\n",
" <td>3.119220e-03</td>\n",
" <td>3.159810e-03</td>\n",
" <td>...</td>\n",
" <td>0.511144</td>\n",
" <td>-1.500000</td>\n",
" <td>-0.695813</td>\n",
" <td>-1.628640e+08</td>\n",
" <td>2.163721e+11</td>\n",
" <td>1.000000</td>\n",
" <td>0.333333</td>\n",
" <td>0.488856</td>\n",
" <td>3</td>\n",
" <td>ScreenSharing</td>\n",
" </tr>\n",
" <tr>\n",
" <th>139999</th>\n",
" <td>0.004189</td>\n",
" <td>0.040222</td>\n",
" <td>0.032511</td>\n",
" <td>0.049401</td>\n",
" <td>0.016890</td>\n",
" <td>3.474479e-04</td>\n",
" <td>3.678946e-04</td>\n",
" <td>3.826904e-04</td>\n",
" <td>3.873811e-04</td>\n",
" <td>3.936524e-04</td>\n",
" <td>...</td>\n",
" <td>0.500000</td>\n",
" <td>-3.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.040000</td>\n",
" <td>1.000000</td>\n",
" <td>0.500000</td>\n",
" <td>25</td>\n",
" <td>ScreenSharing</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>140000 rows × 96 columns</p>\n",
"</div>"
],
"text/plain": [
" interarrival_std interarrival_mean interarrival_min \\\n",
"0 0.001927 0.010000 0.004951 \n",
"1 0.000515 0.020009 0.019227 \n",
"2 0.041315 0.019994 0.000000 \n",
"3 0.008119 0.019954 0.000873 \n",
"4 0.018683 0.020117 0.000001 \n",
"... ... ... ... \n",
"139995 0.000799 0.337698 0.336812 \n",
"139996 0.159892 0.239946 0.000108 \n",
"139997 0.045574 0.040176 0.000012 \n",
"139998 0.028728 0.325410 0.299745 \n",
"139999 0.004189 0.040222 0.032511 \n",
"\n",
" interarrival_max interarrival_max_min_diff interarrival_p10 \\\n",
"0 0.014423 0.009472 7.619953e-05 \n",
"1 0.021251 0.002024 1.931565e-04 \n",
"2 0.143393 0.143393 9.536743e-09 \n",
"3 0.044432 0.043559 9.701633e-05 \n",
"4 0.121093 0.121092 1.023531e-05 \n",
"... ... ... ... \n",
"139995 0.338365 0.001553 3.370330e-03 \n",
"139996 0.320163 0.320055 9.596729e-04 \n",
"139997 0.151814 0.151802 1.705837e-05 \n",
"139998 0.356444 0.056699 3.038041e-03 \n",
"139999 0.049401 0.016890 3.474479e-04 \n",
"\n",
" interarrival_p20 interarrival_p25 interarrival_p30 \\\n",
"0 8.045912e-05 8.572698e-05 9.030223e-05 \n",
"1 1.953020e-04 1.958430e-04 1.965890e-04 \n",
"2 9.536743e-09 9.536743e-09 1.907349e-08 \n",
"3 1.477895e-04 1.699674e-04 1.779909e-04 \n",
"4 7.453918e-05 1.209468e-04 1.324451e-04 \n",
"... ... ... ... \n",
"139995 3.372540e-03 3.373646e-03 3.374751e-03 \n",
"139996 1.918266e-03 2.397562e-03 2.876859e-03 \n",
"139997 3.843689e-05 6.171942e-05 1.125135e-04 \n",
"139998 3.078630e-03 3.098925e-03 3.119220e-03 \n",
"139999 3.678946e-04 3.826904e-04 3.873811e-04 \n",
"\n",
" interarrival_p40 ... rtp_interarrival_max_min_R \\\n",
"0 9.799051e-05 ... 0.500000 \n",
"1 1.985469e-04 ... 0.500000 \n",
"2 4.053116e-08 ... 0.500000 \n",
"3 1.895509e-04 ... 0.500000 \n",
"4 1.531601e-04 ... 0.500000 \n",
"... ... ... ... \n",
"139995 3.376961e-03 ... 0.511905 \n",
"139996 3.196862e-03 ... 1.000000 \n",
"139997 2.727780e-04 ... 0.500000 \n",
"139998 3.159810e-03 ... 0.511144 \n",
"139999 3.936524e-04 ... 0.500000 \n",
"\n",
" rtp_interarrival_kurtosis rtp_interarrival_skew \\\n",
"0 -3.000000 0.000000 \n",
"1 -3.000000 0.000000 \n",
"2 -3.000000 0.000000 \n",
"3 -3.000000 0.000000 \n",
"4 -3.000000 0.000000 \n",
"... ... ... \n",
"139995 -1.500000 -0.707107 \n",
"139996 -0.671026 -1.148811 \n",
"139997 -3.000000 0.000000 \n",
"139998 -1.500000 -0.695813 \n",
"139999 -3.000000 0.000000 \n",
"\n",
" rtp_interarrival_moment3 rtp_interarrival_moment4 \\\n",
"0 0.000000e+00 0.000000e+00 \n",
"1 0.000000e+00 0.000000e+00 \n",
"2 0.000000e+00 0.000000e+00 \n",
"3 0.000000e+00 0.000000e+00 \n",
"4 0.000000e+00 0.000000e+00 \n",
"... ... ... \n",
"139995 -2.211840e+08 3.185050e+11 \n",
"139996 -2.524719e+12 6.654528e+16 \n",
"139997 0.000000e+00 0.000000e+00 \n",
"139998 -1.628640e+08 2.163721e+11 \n",
"139999 0.000000e+00 0.000000e+00 \n",
"\n",
" rtp_interarrival_len_unique_percent \\\n",
"0 0.010000 \n",
"1 0.020000 \n",
"2 0.019231 \n",
"3 0.020000 \n",
"4 0.021739 \n",
"... ... \n",
"139995 0.666667 \n",
"139996 1.000000 \n",
"139997 0.043478 \n",
"139998 1.000000 \n",
"139999 0.040000 \n",
"\n",
" rtp_interarrival_max_value_count_percent rtp_interarrival_min_max_R \\\n",
"0 1.000000 0.500000 \n",
"1 1.000000 0.500000 \n",
"2 1.000000 0.500000 \n",
"3 1.000000 0.500000 \n",
"4 1.000000 0.500000 \n",
"... ... ... \n",
"139995 0.666667 0.488095 \n",
"139996 0.250000 0.000000 \n",
"139997 1.000000 0.500000 \n",
"139998 0.333333 0.488856 \n",
"139999 1.000000 0.500000 \n",
"\n",
" rtp_marker_sum_check label \n",
"0 0 Audio \n",
"1 0 Audio \n",
"2 0 Audio \n",
"3 0 Audio \n",
"4 0 Audio \n",
"... ... ... \n",
"139995 3 ScreenSharing \n",
"139996 3 ScreenSharing \n",
"139997 23 ScreenSharing \n",
"139998 3 ScreenSharing \n",
"139999 25 ScreenSharing \n",
"\n",
"[140000 rows x 96 columns]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# load the dataset\n",
"df = pd.read_csv(\"RTP_dataset.csv\")\n",
"df"
]
},
{
"cell_type": "markdown",
"id": "09ce9f59",
"metadata": {},
"source": [
"### 2.1 Dataset processing\n",
"1. Do a single stratified split based on the labels to segment the dataset into training and test sets with portions of 70% and 30% (the validation set will be needed later on, and in that case, you will have to further split the training set).\n",
"2. Standardize the dataset by fitting the scaler on training set and then transforming the entire dataset.\n",
"3. Repeat the process of removing correlated features, as in the previous lab, examining the correlation in training set and then removing the correlated ones from all datasets."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "8caca196",
"metadata": {},
"outputs": [],
"source": [
"# This part is already provided\n",
"# Here, it is basically the same that you have done during the previous lab except that you are dealing with multiple classes\n",
"\n",
"# Prepare the dataset extracting Features (X) and Labels (Y) \n",
"# Stratify the dataset by having 70% of the data in the training set and 30% in the test set\n",
"df_copy = df.copy()\n",
"df_copy['label'] = pd.Categorical(df_copy['label']).codes # transform to numerical labels\n",
"X = df_copy.drop(columns=['label']).to_numpy()\n",
"y = df_copy[['label']].to_numpy()\n",
"\n",
"# Run stratified training-test splitting\n",
"# Herem X and y are needed for further split when validation set is needed, while test set is withheld to be evaluate at the very last\n",
"X, X_test, y, y_test = train_test_split(X, y, stratify=y, train_size=0.7, random_state=15)\n",
"y, y_test = np.ravel(y), np.ravel(y_test)\n",
"\n",
"# Standardize data\n",
"scaler = StandardScaler()\n",
"scaler.fit(X)\n",
"X_s, X_test_s = scaler.transform(X), scaler.transform(X_test)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "533a1c5a",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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yk0HKD09XQIgpaenl+k6LKENpqjDEtpgijosoQ2WUocltMEUdVhCGyylDktogynqMEUbLFV2draUnp4uHAV19B53RI4ePSrkz5kzR2rYsKHBa86fPy+5ublJCxYskM6ePSvt379fatasmTRs2DBdGRsbG2nz5s3CdRs3bpTs7OyMvq85KLoQIhERERnPzq7oWz1Vr14darUaqampQn5aWpqw28KTIiIi0KFDB0ycOBEA0Lx5czg5OaFTp06YM2cO3Nzc4OrqWmidxtzXHBgDREREVA7Y2trCx8cHsbGxQn5sbCz8/PwMXpOZmQkrK7GroFargf+G0AAA2rdvr1fnwYMHdXUac19z4AgQERFROREaGoqgoCC0bt0a7du3x8qVK5GUlITRo0cDAMLCwpCcnIwNGzYAAHr16oWRI0ciJiYGAQEBSElJQUhICNq2bQt3d3cAwPjx4/Hiiy8iMjISffr0wbfffosff/wRR44cKfJ9FaHY5JuZWUIgninqsIQ2mKIOS2iDKeqwhDZYSh2W0AZT1GEJbbCUOiyhDaao41kOgjbGsmXLJA8PD8nW1lZ64YUXpLi4ON25wYMHS507dxbKL168WGrSpInk4OAgubm5SQMHDpRu3rwplPn666+lhg0bSjY2NlKjRo2kHTt2FOu+SigX6wARERERPYkxQERERFTusANERERE5Q47QERERFTusANERERE5Q47QMXEmHEiIqKy75ldB+jmzZuIiYnB0aNHkZqaCpVKBRcXF/j5+WH06NGoU6eOUfXa2dnh7NmzaNy4scnbTERERObxTD4Gf+TIEXTv3h116tSBv78/XFxcIEkS0tLSEBsbi7/++gv79u1Dhw4dCqwjNDTUYP6iRYvw7rvvolq1agCAqKioQtuyZMkSxMfHo0ePHujXrx+++uorREREID8/H2+88QZmz54Na2vL74c+fPgQmzdv1utQdujQAQMGDICTk1Ox66xXrx4OHDiA+vXrF6n8d999h/j4eLz66qto3749fv75Z3z66ae69/K9994z4pWZX2m8lyjm+/msvJfg76ZJWcLvJkz0ft68eROVK1dGhQoVhHytVotjx47hxRdfNOq10LPjmewAtWnTBh07dsTnn39u8PyECRNw5MgRnDx5ssA6rKys0KJFC1SuXFnIj4uLQ+vWreHk5ASVSoWff/65wDo++eQT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hw9j6NChSE9P140qhYeHA49WZd69e7fQhsqVK2PdunUAgOvXr0OlUmH79u3o0qUL7O3tsXHjRgDA2rVr0bhxY9jb26NRo0ZYvny5Gd8pIqLi4wgQURly4MABvPvuu1i8eDE6deqEP//8E++99x4AYObMmcCjLToWL14MT09PXLt2DcHBwfj444+xfPly+Pn5ITo6GjNmzMDly5cBABUqVChWGyZNmoTPPvsMa9euhZ2dHVatWoWZM2di6dKlaNWqFU6fPo2RI0fCyckJgwcPLoV3gYjIBJReiZGI9A0ePFhSq9WSk5OT7njrrbekTp06SfPmzRPKfvXVV5Kbm1uBdW3fvl2qVq2aLr127VrJ2dlZrxwAadeuXUKes7OztHbtWkl6tIkkACk6OlooU6dOHWnz5s1C3ieffCK1b9++mK+aiMh8OAJEZKG6du2q22QTAJycnPD888/j5MmTmDt3ri4/Ly8P2dnZyMzMhKOjIw4dOoR58+bhwoULuH//PnJzc5GdnY2HDx/CycmpxO1q3bq17v//+ecf/PXXXxg+fDhGjhypy8/NzYWzs3OJ70VEVFrYASKyUI87PE/Kz8/HrFmz8MYbb+iVt7e3x40bN/Daa69h9OjR+OSTT1C1alUcOXIEw4cPh1arLfR+KpUK8p1xDF3zZCcqPz8fALBq1Sr4+voK5dRqdRFfKRGR+bEDRFSGvPDCC7h8+bJex+ix+Ph45Obm4rPPPoOV1X+fcdi+fbtQxtbWFnl5eXrX1qhRAykpKbr0lStXkJmZWWh7XFxcUKtWLVy9ehUDBw408lUREZkfO0BEZciMGTPQs2dP1KlTB2+//TasrKzwn//8B+fOncOcOXPw3HPPITc3F0uWLEGvXr3wf//3f1ixYoVQh6enJzIyMvDTTz+hRYsWcHR0hKOjI1566SUsXboU7dq1Q35+PiZNmlSkR9zDw8Mxbtw4VKpUCd27d4dGo0F8fDzu3buH0NDQUnw3iIiMx8fgicqQgIAAfP/994iNjUWbNm3Qrl07REVFwcPDAwDQsmVLREVFITIyEk2bNsWmTZsQEREh1OHn54fRo0cjMDAQNWrUwIIFCwAAn332GerUqYMXX3wR77zzDj766CM4Ojo+tU0jRozA6tWrsW7dOjRr1gydO3fGunXr4OXlVUrvAhFRyakk+aQ/ERER0TOOI0BERERU7rADREREROUOO0BERERU7rADREREROUOO0BERERU7rADREREROUOO0BERERU7rADREREROUOO0BERERU7rADREREROUOO0BERERU7rADREREROXO/wPFWtbRxQXnvAAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 640x480 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"59 features are removed\n"
]
}
],
"source": [
"# compute the correlation matrix\n",
"columns= [i for i in range(X_s.shape[1])]\n",
"df_tmp = pd.DataFrame(X_s, columns=columns)\n",
"correlation_matrix = df_tmp.corr().abs()\n",
"\n",
"# display the heatmap\n",
"plt.figure()\n",
"sns.heatmap(correlation_matrix, cmap='Blues', vmin=0.8, vmax=1, cbar_kws={'label':'Correlation'})\n",
"plt.xlabel('Feature')\n",
"plt.ylabel('Feature')\n",
"plt.show()\n",
"\n",
"# extract features having a correlation > 0.8\n",
"c = correlation_matrix[correlation_matrix>0.8]\n",
"s = c.unstack()\n",
"so = s.sort_values(ascending=False).reset_index()\n",
"\n",
"# get strongly correlated features removing pairs having correlation = 1 because of the diagonal, i.e., correlation between one feature and itself\n",
"so = so[(so[0].isnull()==False) & (so[\"level_0\"] != so[\"level_1\"])]\n",
"\n",
"to_be_deleted = []\n",
"candidates = list(so[\"level_0\"])\n",
"\n",
"# get the unique set of features to be deleted. Notice that we discard one feature per time considering the case where a feature is strongly correlated with multiple features\n",
"subset_so = so\n",
"for candidate in candidates:\n",
" if (candidate in list(subset_so[\"level_0\"])): \n",
" to_be_deleted.append(candidate)\n",
" subset_so = subset_so[(subset_so[\"level_0\"] != candidate) & (subset_so[\"level_1\"] != candidate)]\n",
"\n",
"# to_be_deleted contains the index of columns that you need to remove from both training and test sets\n",
"print(len(to_be_deleted), 'features are removed')\n",
"\n",
"# remove the correlated features from bot sets\n",
"\n",
"# Create a mask for the columns to keep\n",
"columns_to_keep = np.ones(X_s.shape[1], dtype=bool)\n",
"columns_to_keep[to_be_deleted] = False\n",
"\n",
"# Use the mask to select only the columns to keep\n",
"X_s = X_s[:, columns_to_keep]\n",
"X_test_s = X_test_s[:, columns_to_keep]"
]
},
{
"cell_type": "markdown",
"id": "5b786a31",
"metadata": {},
"source": [
"### 2.2 Validation curve\n",
"1. Use GaussianNB classifier. For the hyper-parameter `var_smoothing` (<a href=\"https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html\">documentation</a>) , define a range of possible values, for example ``np.logspace(-4,0,5)``.\n",
"2. For each value of `var_smoothing`, for validation use k-fold cross-validation or stratified random sampling for k times. **Note that, no matter which one do you choose, you need to stick to it for the following questions. Choose a low value for k, for example 5**\n",
"3. Record the max, min, and mean for each value of the hyper-parameter, and finally plot the performance.\n",
" - What is the best value of `var_smoothing`?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d8a65e9e",
"metadata": {},
"outputs": [],
"source": [
"acc_train_means = []\n",
"acc_train_maxs = []\n",
"acc_train_mins = []\n",
"acc_val_means = []\n",
"acc_val_maxs = []\n",
"acc_val_mins = []\n",
"\n",
"hyper_vals = np.logspace(-4,0,5)\n",
"\n",
"#we choose the model RandomForestClassifier and change its hyper-parameter max_depth, using integer values from 2 to 9\n",
"for n in hyper_vals:\n",
" gnb_clf = GaussianNB(var_smoothing=n)\n",
" scores = cross_validate(gnb_clf, X_s, y, cv=5, scoring='accuracy', return_train_score=True)\n",
" acc_train_means.append(scores['train_score'].mean())\n",
" acc_train_maxs.append(scores['train_score'].max())\n",
" acc_train_mins.append(scores['train_score'].min())\n",
" acc_val_means.append(scores['test_score'].mean())\n",
" acc_val_maxs.append(scores['test_score'].max())\n",
" acc_val_mins.append(scores['test_score'].min())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a76a68c3",
"metadata": {},
"outputs": [],
"source": [
"plt.figure()\n",
"plt.plot(hyper_vals, acc_train_means, color='tab:blue', label='train')\n",
"plt.xscale('log')\n",
"plt.fill_between(hyper_vals, acc_train_mins, acc_train_maxs, alpha=0.5, color='tab:blue')\n",
"plt.plot(hyper_vals, acc_val_means, color='tab:red', label='val')\n",
"plt.fill_between(hyper_vals, acc_val_mins, acc_val_maxs, alpha=0.5, color='tab:red')\n",
"plt.xlabel('max depth')\n",
"plt.ylabel('accuracy')\n",
"plt.legend()\n",
"plt.title(\"Validation curve for max depth in GaussianNB\")\n",
"plt.ylim(0.65,0.85)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "c5f309f2",
"metadata": {},
"source": [
"### 2.3 Grid search for decision tree\n",
"\n",
"1. Define the parameters' range (<a href=\"https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier\">documentation</a>) as following:\n",
" - ``criterion`` - ``['gini', 'entropy']``,\n",
" - ``max_depth`` - ``[4, 8, None]``,\n",
" - ``min_samples_split`` - ``[2, 4]``,\n",
"2. Perform the grid search among all the possible combinations of the defined parameters' range, and for each combination of configurations:\n",
" - Refer to the approach (k-fold cross-validation or randomly data segmentation for k times) you select in the previous question.\n",
" - Initialize and train the model with the choosing parameters, and evaluate the performance on training and validation set. Record the accuracy of for both sets.\n",
" - After the process, plot the accuracy for training and validation sets with respect to different configuration of parameters (on y-axis, output accuracy with either error bar or filled region between min and max, and on x-axis, specify the configuration index). In the figure, specify the best configuration by mark the highest mean accuracy on validation set.\n",
"3. At last, answer the following questions:\n",
" - What is the best combination of parameters?\n",
" - Try to explain why such parameters generate the best outcome. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "942ba83b",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import itertools\n",
"\n",
"criterion = ['gini', 'entropy']\n",
"max_depth = [4, 8, None]\n",
"min_samples_split = [2, 4]\n",
"\n",
"acc_train_means = []\n",
"acc_train_maxs = []\n",
"acc_train_mins = []\n",
"acc_val_means = []\n",
"acc_val_maxs = []\n",
"acc_val_mins = []\n",
"\n",
"# iterate over all possible combinations\n",
"for (c, md, mss) in itertools.product(criterion, max_depth, min_samples_split):\n",
" # initialize and fit a model per pair of parameters\n",
" dtc_tmp = DecisionTreeClassifier(criterion=c, max_depth=md, min_samples_split=mss, random_state=69)\n",
" dtc_tmp.fit(X_s, y)\n",
" # here we only refer to accuracy for simplicity\n",
" acc_train = accuracy_score(y, dtc_tmp.predict(X_s))\n",
" acc_val = accuracy_score(y_test, dtc_tmp.predict(X_test_s))\n",
" print(f'#criterion: {c},\\t max depth: {md},\\t min samples split {mss},\\t accuracy: train - {acc_train} | val - {acc_val}')\n",
"\n",
" scores = cross_validate(dtc_tmp, X_s, y, cv=5, scoring='accuracy', return_train_score=True)\n",
" acc_train_means.append(scores['train_score'].mean())\n",
" acc_train_maxs.append(scores['train_score'].max())\n",
" acc_train_mins.append(scores['train_score'].min())\n",
" acc_val_means.append(scores['test_score'].mean())\n",
" acc_val_maxs.append(scores['test_score'].max())\n",
" acc_val_mins.append(scores['test_score'].min())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "10ccdedc",
"metadata": {},
"outputs": [],
"source": [
"plt.figure()\n",
"x = list(range(12))\n",
"plt.plot(x, acc_train_means, color='tab:blue', label='train')\n",
"plt.fill_between(x, acc_train_mins, acc_train_maxs, alpha=0.5, color='tab:blue')\n",
"plt.plot(x, acc_val_means, color='tab:red', label='val')\n",
"plt.fill_between(x, acc_val_mins, acc_val_maxs, alpha=0.5, color='tab:red')\n",
"plt.xlabel('max depth')\n",
"plt.ylabel('combination number')\n",
"plt.legend()\n",
"plt.title(\"Validation curve for max depth in DT\")\n",
"plt.ylim(0.87,1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "6d2a9d7e",
"metadata": {},
"source": [
"### 2.4 Learning Curve\n",
"Once we find the best features and configurations, we can check the number of training samples required to create a reliable model by checking learning curve.\n",
"1. Select the best one of the previous models with the best configuration. Define the range of portion of training sample. Note that this is the portion of training samples out of the dataset used for model training (test set is excluded). The goal is to find the proper portion that can generate an accuracy on validation greater than a certain threshold, e.g., 96%, and to see whether it is needed to gather more data.\n",
"2. For each of the percentage in the range, refer to your previous selected approach (k-fold cross-validation or random stratified sampling for k times) and train your model with different portions of training set.\n",
"3. At each trial, record the accuracy, calculating the max, min and mean among the k repetitions.\n",
"4. Visualize the performance evolution with error bar as you increase the portion of training data.\n",
" - Which portion do you think is proper to derive a reliable result?\n",
" - Do you think whether we need more data?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8378f8c2",
"metadata": {},
"outputs": [],
"source": [
"\n",
"# here we only refer to accuracy for simplicity\n",
"info_accuracy_train = []\n",
"info_accuracy_val = []\n",
"\n",
"for train_size in np.arange(0.1, 1, 0.1):\n",
" # select 10 random states\n",
" random_states = set()\n",
" while len(random_states) < 10:\n",
" n = random.randint(0,1000000)\n",
" random_states.add(n)\n",
"\n",
" accuraries_train_tmp = []\n",
" accuraries_val_tmp = []\n",
" \n",
" # iterate over all random states with same training size to derive the 10 different performance\n",
" for random_state in random_states:\n",
" # do a stratified random sampling from the training set \n",
" sss = StratifiedShuffleSplit(n_splits=1, train_size=train_size, random_state=random_state)\n",
" index_selected = list(sss.split(X_s, y))[0][0]\n",
" X_train_selected = X_s[index_selected]\n",
" y_train_selected = y[index_selected]\n",
" \n",
" dtc_tmp = DecisionTreeClassifier(criterion=\"entropy\", max_depth=None, min_samples_split=4, random_state=69)\n",
" \n",
" # initialize and fit a DT model per time\n",
" dtc_tmp.fit(X_train_selected, y_train_selected)\n",
" accuraries_train_tmp.append(accuracy_score(y_train_selected, dtc_tmp.predict(X_train_selected)))\n",
" accuraries_val_tmp.append(accuracy_score(y_test, dtc_tmp.predict(X_test_s)))\n",
"\n",
" # calculate the statistics to generate overall performance\n",
" accuraries_tmp = np.array(accuraries_train_tmp)\n",
" mean_acc = accuraries_tmp.mean()\n",
" min_acc = accuraries_tmp.min()\n",
" max_acc = accuraries_tmp.max()\n",
" info_accuracy_train.append((mean_acc, min_acc, max_acc))\n",
" \n",
" accuraries_tmp = np.array(accuraries_val_tmp)\n",
" mean_acc = accuraries_tmp.mean()\n",
" min_acc = accuraries_tmp.min()\n",
" max_acc = accuraries_tmp.max()\n",
" info_accuracy_val.append((mean_acc, min_acc, max_acc))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "394e5480",
"metadata": {},
"outputs": [],
"source": [
"plt.figure()\n",
"plt.errorbar(\n",
" [train_size for train_size in np.arange(0.1, 1.0, 0.1)], # x-location of each error bar\n",
" [info[0] for info in info_accuracy_train], # y-location of each error bar\n",
" # the size of each error bar\n",
" yerr=[\n",
" [info[0]-info[1] for info in info_accuracy_train], \n",
" [info[2]-info[0] for info in info_accuracy_train]\n",
" ], \n",
" color='tab:blue', label='train'\n",
")\n",
"plt.errorbar(\n",
" [train_size for train_size in np.arange(0.1, 1.0, 0.1)], # x-location of each error bar\n",
" [info[0] for info in info_accuracy_val], # y-location of each error bar\n",
" # the size of each error bar\n",
" yerr=[\n",
" [info[0]-info[1] for info in info_accuracy_val], \n",
" [info[2]-info[0] for info in info_accuracy_val]\n",
" ], \n",
" color='tab:red', label='val'\n",
")\n",
"plt.grid()\n",
"plt.xlabel('Portion of training set')\n",
"plt.ylabel('Accuracy')\n",
"plt.title('Learning curve for DT')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "97c53dc0",
"metadata": {},
"source": [
"### 2.5 Test your best model on unseen data\n",
"Based on the previous considerations, retrain your model with all of the aforementioned best selections on all data except test set. Output the final performance in terms of classification report and confusion matrix on the test set.\n",
"- Which classes have good performance?\n",
"- Which classes have poor performance?\n",
"- Can you find some peculiar behavior for the performance of certain classes? Try to explain why."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5bde5bee",
"metadata": {},
"outputs": [],
"source": [
"# you answer here\n",
"model = dt_tmp = DecisionTreeClassifier(\n",
" criterion=\"entropy\", max_depth=None, min_samples_split=4, random_state=60\n",
")\n",
"\n",
"model.fit(X_s, y)\n",
"y_pred = model.predict(X_test_s)\n",
"print(classification_report(y_test, y_pred))\n",
"confusion_test = confusion_matrix(y_test, y_pred)\n",
"\n",
"# visualize the confusion matrix\n",
"plt.figure(figsize=(10, 10))\n",
"sns.heatmap(confusion_test, cmap=\"Blues\", annot=True, cbar_kws={\"label\": \"Occurrences\"})\n",
"plt.xlabel(\"Prediction\")\n",
"plt.ylabel(\"True\")\n",
"plt.title(\"Confusion matrix\")\n",
"plt.show()\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.11.2"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}