From d2db27e73c408cf3aa8a44152d15519de95859a7 Mon Sep 17 00:00:00 2001 From: ConstanzaSegoviaA Date: Thu, 26 Feb 2026 11:56:19 +0100 Subject: [PATCH] listo --- lab-hyper-tuning.ipynb | 3826 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 3781 insertions(+), 45 deletions(-) diff --git a/lab-hyper-tuning.ipynb b/lab-hyper-tuning.ipynb index 847d487..a666d85 100644 --- a/lab-hyper-tuning.ipynb +++ b/lab-hyper-tuning.ipynb @@ -35,14 +35,26 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "#Libraries\n", "import pandas as pd\n", "import numpy as np\n", - "from sklearn.model_selection import train_test_split" + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.preprocessing import StandardScaler,MinMaxScaler\n", + "from sklearn.neighbors import KNeighborsClassifier\n", + "from sklearn.metrics import accuracy_score, classification_report\n", + "from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\n", + "from sklearn.tree import DecisionTreeClassifier\n", + "from sklearn.ensemble import BaggingClassifier, RandomForestClassifier,AdaBoostClassifier, GradientBoostingClassifier\n", + "from sklearn.metrics import precision_score, recall_score, f1_score\n", + "\n", + "from sklearn.model_selection import GridSearchCV\n", + "from sklearn.model_selection import RandomizedSearchCV\n" ] }, { @@ -221,102 +233,3826 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "#your code here" - ] - }, - { - "cell_type": "markdown", + "execution_count": 3, "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HomePlanet 201\n", + "CryoSleep 217\n", + "Cabin 199\n", + "Destination 182\n", + "Age 179\n", + "VIP 203\n", + "RoomService 181\n", + "FoodCourt 183\n", + "ShoppingMall 208\n", + "Spa 183\n", + "VRDeck 188\n", + "Name 200\n", + "dtype: int64\n" + ] + } + ], "source": [ - "- Now let's use the best model we got so far in order to see how it can improve when we fine tune it's hyperparameters." + "nulos=spaceship.isnull().sum()\n", + "print(nulos[nulos>0]if nulos.any()else 'No hay nulos')" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "#your code here" + "df=spaceship.dropna()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "- Evaluate your model" + "Revisamos que no hay valores nulos" ] }, { "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "#your code here" - ] - }, - { - "cell_type": "markdown", + "execution_count": 5, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "PassengerId 0\n", + "HomePlanet 0\n", + "CryoSleep 0\n", + "Cabin 0\n", + "Destination 0\n", + "Age 0\n", + "VIP 0\n", + "RoomService 0\n", + "FoodCourt 0\n", + "ShoppingMall 0\n", + "Spa 0\n", + "VRDeck 0\n", + "Name 0\n", + "Transported 0\n", + "dtype: int64" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "**Grid/Random Search**" + "df.isnull().sum()" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 6, "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\tachi\\AppData\\Local\\Temp\\ipykernel_19752\\4183486857.py:1: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " df.drop(['PassengerId', 'Name'], axis=1, inplace=True)\n" + ] + } + ], "source": [ - "For this lab we will use Grid Search." + "df.drop(['PassengerId', 'Name'], axis=1, inplace=True)" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 7, "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\tachi\\AppData\\Local\\Temp\\ipykernel_19752\\641193852.py:1: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " df['Cabin'] = df['Cabin'].fillna('Unknown').astype(str).str[0]\n" + ] + } + ], "source": [ - "- Define hyperparameters to fine tune." + "df['Cabin'] = df['Cabin'].fillna('Unknown').astype(str).str[0]" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\tachi\\AppData\\Local\\Temp\\ipykernel_19752\\1236869429.py:2: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " df['Cabin'] = df['Cabin'].apply(lambda x: x if x in valid_decks else 'Unknown')\n" + ] + } + ], "source": [ - "#your code here" + "valid_decks = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'T'}\n", + "df['Cabin'] = df['Cabin'].apply(lambda x: x if x in valid_decks else 'Unknown')" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 9, "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\tachi\\AppData\\Local\\Temp\\ipykernel_19752\\709519558.py:2: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " df['VIP'] = df['VIP'].map(mapa)\n", + "C:\\Users\\tachi\\AppData\\Local\\Temp\\ipykernel_19752\\709519558.py:3: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " df[\"CryoSleep\"] = df[\"CryoSleep\"].map(mapa)\n", + "C:\\Users\\tachi\\AppData\\Local\\Temp\\ipykernel_19752\\709519558.py:4: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " df[\"Transported\"] = df[\"Transported\"].map(mapa)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
HomePlanetCryoSleepCabinDestinationAgeVIPRoomServiceFoodCourtShoppingMallSpaVRDeckTransported
0Europa0BTRAPPIST-1e39.000.00.00.00.00.00
1Earth0FTRAPPIST-1e24.00109.09.025.0549.044.01
2Europa0ATRAPPIST-1e58.0143.03576.00.06715.049.00
3Europa0ATRAPPIST-1e33.000.01283.0371.03329.0193.00
4Earth0FTRAPPIST-1e16.00303.070.0151.0565.02.01
\n", + "
" + ], + "text/plain": [ + " HomePlanet CryoSleep Cabin Destination Age VIP RoomService FoodCourt \\\n", + "0 Europa 0 B TRAPPIST-1e 39.0 0 0.0 0.0 \n", + "1 Earth 0 F TRAPPIST-1e 24.0 0 109.0 9.0 \n", + "2 Europa 0 A TRAPPIST-1e 58.0 1 43.0 3576.0 \n", + "3 Europa 0 A TRAPPIST-1e 33.0 0 0.0 1283.0 \n", + "4 Earth 0 F TRAPPIST-1e 16.0 0 303.0 70.0 \n", + "\n", + " ShoppingMall Spa VRDeck Transported \n", + "0 0.0 0.0 0.0 0 \n", + "1 25.0 549.0 44.0 1 \n", + "2 0.0 6715.0 49.0 0 \n", + "3 371.0 3329.0 193.0 0 \n", + "4 151.0 565.0 2.0 1 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "- Run Grid Search" + "mapa = {False: 0, True: 1}\n", + "df['VIP'] = df['VIP'].map(mapa)\n", + "df[\"CryoSleep\"] = df[\"CryoSleep\"].map(mapa)\n", + "df[\"Transported\"] = df[\"Transported\"].map(mapa)\n", + "df.head()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, "source": [ - "- Evaluate your model" + "df = pd.get_dummies(df, columns=['HomePlanet', 'CryoSleep', 'Cabin', 'Destination', 'VIP'], drop_first=False)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AgeRoomServiceFoodCourtShoppingMallSpaVRDeckTransportedHomePlanet_EarthHomePlanet_EuropaHomePlanet_Mars...Cabin_DCabin_ECabin_FCabin_GCabin_TDestination_55 Cancri eDestination_PSO J318.5-22Destination_TRAPPIST-1eVIP_0VIP_1
039.00.00.00.00.00.00FalseTrueFalse...FalseFalseFalseFalseFalseFalseFalseTrueTrueFalse
124.0109.09.025.0549.044.01TrueFalseFalse...FalseFalseTrueFalseFalseFalseFalseTrueTrueFalse
258.043.03576.00.06715.049.00FalseTrueFalse...FalseFalseFalseFalseFalseFalseFalseTrueFalseTrue
333.00.01283.0371.03329.0193.00FalseTrueFalse...FalseFalseFalseFalseFalseFalseFalseTrueTrueFalse
416.0303.070.0151.0565.02.01TrueFalseFalse...FalseFalseTrueFalseFalseFalseFalseTrueTrueFalse
\n", + "

5 rows × 25 columns

\n", + "
" + ], + "text/plain": [ + " Age RoomService FoodCourt ShoppingMall Spa VRDeck Transported \\\n", + "0 39.0 0.0 0.0 0.0 0.0 0.0 0 \n", + "1 24.0 109.0 9.0 25.0 549.0 44.0 1 \n", + "2 58.0 43.0 3576.0 0.0 6715.0 49.0 0 \n", + "3 33.0 0.0 1283.0 371.0 3329.0 193.0 0 \n", + "4 16.0 303.0 70.0 151.0 565.0 2.0 1 \n", + "\n", + " HomePlanet_Earth HomePlanet_Europa HomePlanet_Mars ... Cabin_D \\\n", + "0 False True False ... False \n", + "1 True False False ... False \n", + "2 False True False ... False \n", + "3 False True False ... False \n", + "4 True False False ... False \n", + "\n", + " Cabin_E Cabin_F Cabin_G Cabin_T Destination_55 Cancri e \\\n", + "0 False False False False False \n", + "1 False True False False False \n", + "2 False False False False False \n", + "3 False False False False False \n", + "4 False True False False False \n", + "\n", + " Destination_PSO J318.5-22 Destination_TRAPPIST-1e VIP_0 VIP_1 \n", + "0 False True True False \n", + "1 False True True False \n", + "2 False True False True \n", + "3 False True True False \n", + "4 False True True False \n", + "\n", + "[5 rows x 25 columns]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Veamos la muestra " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "df1=df[df[\"Transported\"] == 0] #false\n", + "df2=df[df[\"Transported\"] == 1] #true" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "sns.countplot(df, x=\"Transported\",hue= \"Transported\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "dividimos la muestra en train y test" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "X = df.drop('Transported', axis=1)\n", + "y = df['Transported']" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Set de entrenamiento: 5284 muestras\n", + "Set de prueba: 1322 muestras\n" + ] + } + ], + "source": [ + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n", + "\n", + "print(f\"Set de entrenamiento: {X_train.shape[0]} muestras\")\n", + "print(f\"Set de prueba: {X_test.shape[0]} muestras\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Normalizamos los datos" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
MinMaxScaler()
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.
" + ], + "text/plain": [ + "MinMaxScaler()" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "normalizer = MinMaxScaler()\n", + "\n", + "normalizer.fit(X_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "X_train_norm = normalizer.transform(X_train)\n", + "\n", + "X_test_norm = normalizer.transform(X_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "X_train_norm = pd.DataFrame(X_train_norm, columns = X_train.columns)\n", + "X_test_norm = pd.DataFrame(X_test_norm, columns = X_test.columns)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Now let's use the best model we got so far in order to see how it can improve when we fine tune it's hyperparameters." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Mejor el modelo de Random Forest" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "forest = RandomForestClassifier(n_estimators=100,\n", + " max_depth=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
RandomForestClassifier(max_depth=20)
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.
" + ], + "text/plain": [ + "RandomForestClassifier(max_depth=20)" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "forest.fit(X_train_norm, y_train)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Evaluate your model" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Informe de Clasificación:\n", + " precision recall f1-score support\n", + "\n", + " 0 0.80 0.81 0.80 653\n", + " 1 0.81 0.80 0.81 669\n", + "\n", + " accuracy 0.80 1322\n", + " macro avg 0.80 0.80 0.80 1322\n", + "weighted avg 0.80 0.80 0.80 1322\n", + "\n", + "Accuracy:\n", + "0.8048411497730711\n", + "Precision:\n", + "0.8127853881278538\n", + "Recall:\n", + "0.7982062780269058\n", + "F1-score:\n", + "0.8054298642533937\n", + "Confusion Matrix:\n", + "[[530 123]\n", + " [135 534]]\n" + ] + } + ], + "source": [ + "pred = forest.predict(X_test_norm)\n", + "new_accuracy = accuracy_score(y_test, pred)\n", + "\n", + "print(\"\\nInforme de Clasificación:\")\n", + "print(classification_report(y_test, pred))\n", + "\n", + "print(\"Accuracy:\")\n", + "print(new_accuracy)\n", + "\n", + "# precision\n", + "print(\"Precision:\")\n", + "print(precision_score(y_test,pred))\n", + " \n", + "# recall\n", + "print(\"Recall:\")\n", + "print(recall_score(y_test,pred))\n", + " \n", + "# F1-score\n", + "print(\"F1-score:\")\n", + "print(f1_score(y_test, pred))\n", + " \n", + "print(\"Confusion Matrix:\")\n", + "print(confusion_matrix(y_test, pred))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "el modelo esta en un 80.5%" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Grid/Random Search**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this lab we will use Grid Search." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Define hyperparameters to fine tune." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "grid = {\"n_estimators\": [50, 100, 200,500],\n", + " \"max_depth\":[10,30,50]}\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "forest = RandomForestClassifier()" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "model = GridSearchCV(estimator = forest, param_grid = grid, cv=5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Run Grid Search" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
GridSearchCV(cv=5, estimator=RandomForestClassifier(),\n",
+       "             param_grid={'max_depth': [10, 30, 50],\n",
+       "                         'n_estimators': [50, 100, 200, 500]})
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.
" + ], + "text/plain": [ + "GridSearchCV(cv=5, estimator=RandomForestClassifier(),\n", + " param_grid={'max_depth': [10, 30, 50],\n", + " 'n_estimators': [50, 100, 200, 500]})" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.fit(X_train_norm, y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'max_depth': 10, 'n_estimators': 200}" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.best_params_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Evaluate your model" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Informe de Clasificación:\n", + " precision recall f1-score support\n", + "\n", + " 0 0.80 0.81 0.81 653\n", + " 1 0.81 0.80 0.81 669\n", + "\n", + " accuracy 0.81 1322\n", + " macro avg 0.81 0.81 0.81 1322\n", + "weighted avg 0.81 0.81 0.81 1322\n", + "\n", + "Accuracy:\n", + "0.8063540090771558\n", + "Precision:\n", + "0.8143074581430746\n", + "Recall:\n", + "0.7997010463378177\n", + "F1-score:\n", + "0.8069381598793364\n", + "Confusion Matrix:\n", + "[[531 122]\n", + " [134 535]]\n" + ] + } + ], + "source": [ + "pred=model.predict(X_test_norm)\n", + "new_accuracy = accuracy_score(y_test, pred)\n", + "\n", + "print(\"\\nInforme de Clasificación:\")\n", + "print(classification_report(y_test, pred))\n", + "\n", + "print(\"Accuracy:\")\n", + "print(new_accuracy)\n", + "\n", + "# precision\n", + "print(\"Precision:\")\n", + "print(precision_score(y_test,pred))\n", + " \n", + "# recall\n", + "print(\"Recall:\")\n", + "print(recall_score(y_test,pred))\n", + " \n", + "# F1-score\n", + "print(\"F1-score:\")\n", + "print(f1_score(y_test, pred))\n", + " \n", + "print(\"Confusion Matrix:\")\n", + "print(confusion_matrix(y_test, pred))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Obtuvimos un 80,6% de accuracy lo que nos indica que el modelo esta bien ajustado y además la precisión es de un 81.4%, el recall es de un 79.2% y el F1-score es de un 80.2%." + ] } ], "metadata": { @@ -335,7 +4071,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.13.1" } }, "nbformat": 4,