diff --git a/lab-ensemble.ipynb b/lab-ensemble.ipynb index 5c5b3c7..83397f7 100644 --- a/lab-ensemble.ipynb +++ b/lab-ensemble.ipynb @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 304, "metadata": {}, "outputs": [], "source": [ @@ -43,7 +43,29 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 305, + "metadata": {}, + "outputs": [], + "source": [ + "spaceship = pd.read_csv(\"https://raw.githubusercontent.com/data-bootcamp-v4/data/main/spaceship_titanic.csv\")\n", + "spaceship.shape\n", + "\n", + "spaceship.dropna(inplace=True)\n", + "spaceship.reset_index(inplace=True, drop=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now perform the same as before:\n", + "- Feature Scaling\n", + "- Feature Selection\n" + ] + }, + { + "cell_type": "code", + "execution_count": 306, "metadata": {}, "outputs": [ { @@ -67,200 +89,1734 @@ " \n", " \n", " \n", - " PassengerId\n", - " HomePlanet\n", - " CryoSleep\n", - " Cabin\n", - " Destination\n", " Age\n", - " VIP\n", " RoomService\n", " FoodCourt\n", " ShoppingMall\n", " Spa\n", " VRDeck\n", - " Name\n", " Transported\n", " \n", " \n", " \n", " \n", + " Age\n", + " 1.000000\n", + " 0.074783\n", + " 0.135844\n", + " 0.042314\n", + " 0.123820\n", + " 0.105031\n", + " -0.082553\n", + " \n", + " \n", + " RoomService\n", + " 0.074783\n", + " 1.000000\n", + " -0.013614\n", + " 0.060478\n", + " 0.012472\n", + " -0.026002\n", + " -0.247291\n", + " \n", + " \n", + " FoodCourt\n", + " 0.135844\n", + " -0.013614\n", + " 1.000000\n", + " -0.012320\n", + " 0.215995\n", + " 0.216997\n", + " 0.055025\n", + " \n", + " \n", + " ShoppingMall\n", + " 0.042314\n", + " 0.060478\n", + " -0.012320\n", + " 1.000000\n", + " 0.022168\n", + " 0.000383\n", + " 0.011602\n", + " \n", + " \n", + " Spa\n", + " 0.123820\n", + " 0.012472\n", + " 0.215995\n", + " 0.022168\n", + " 1.000000\n", + " 0.149447\n", + " -0.219854\n", + " \n", + " \n", + " VRDeck\n", + " 0.105031\n", + " -0.026002\n", + " 0.216997\n", + " 0.000383\n", + " 0.149447\n", + " 1.000000\n", + " -0.207950\n", + " \n", + " \n", + " Transported\n", + " -0.082553\n", + " -0.247291\n", + " 0.055025\n", + " 0.011602\n", + " -0.219854\n", + " -0.207950\n", + " 1.000000\n", + " \n", + " \n", + "\n", + "" + ], + "text/plain": [ + " Age RoomService FoodCourt ShoppingMall Spa \\\n", + "Age 1.000000 0.074783 0.135844 0.042314 0.123820 \n", + "RoomService 0.074783 1.000000 -0.013614 0.060478 0.012472 \n", + "FoodCourt 0.135844 -0.013614 1.000000 -0.012320 0.215995 \n", + "ShoppingMall 0.042314 0.060478 -0.012320 1.000000 0.022168 \n", + "Spa 0.123820 0.012472 0.215995 0.022168 1.000000 \n", + "VRDeck 0.105031 -0.026002 0.216997 0.000383 0.149447 \n", + "Transported -0.082553 -0.247291 0.055025 0.011602 -0.219854 \n", + "\n", + " VRDeck Transported \n", + "Age 0.105031 -0.082553 \n", + "RoomService -0.026002 -0.247291 \n", + "FoodCourt 0.216997 0.055025 \n", + "ShoppingMall 0.000383 0.011602 \n", + "Spa 0.149447 -0.219854 \n", + "VRDeck 1.000000 -0.207950 \n", + "Transported -0.207950 1.000000 " + ] + }, + "execution_count": 306, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 1. Feature selection\n", + "\n", + "spaceship.select_dtypes(include=['number', 'bool']).corr()" + ] + }, + { + "cell_type": "code", + "execution_count": 307, + "metadata": {}, + "outputs": [], + "source": [ + "#your code here\n", + "\n", + "features = spaceship.select_dtypes(include='number') # Mejor manual\n", + "\n", + "target = spaceship['Transported'] # Estamos haciendo una clasificación\n" + ] + }, + { + "cell_type": "code", + "execution_count": 308, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", - " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", - " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", - " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", - " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", - " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", " \n", " \n", "
AgeRoomServiceFoodCourtShoppingMallSpaVRDeck
00001_01EuropaFalseB/0/PTRAPPIST-1e39.0False0.00.00.00.00.0Maham OfracculyFalse
10002_01EarthFalseF/0/STRAPPIST-1e24.0False109.09.025.0549.044.0Juanna VinesTrue
20003_01EuropaFalseA/0/STRAPPIST-1e58.0True43.03576.00.06715.049.0Altark SusentFalse
30003_02EuropaFalseA/0/STRAPPIST-1e33.0False0.01283.0371.03329.0193.0Solam SusentFalse
40004_01EarthFalseF/1/STRAPPIST-1e16.0False303.070.0151.0565.02.0Willy SantantinesTrue
\n", "
" ], "text/plain": [ - " PassengerId HomePlanet CryoSleep Cabin Destination Age VIP \\\n", - "0 0001_01 Europa False B/0/P TRAPPIST-1e 39.0 False \n", - "1 0002_01 Earth False F/0/S TRAPPIST-1e 24.0 False \n", - "2 0003_01 Europa False A/0/S TRAPPIST-1e 58.0 True \n", - "3 0003_02 Europa False A/0/S TRAPPIST-1e 33.0 False \n", - "4 0004_01 Earth False F/1/S TRAPPIST-1e 16.0 False \n", - "\n", - " RoomService FoodCourt ShoppingMall Spa VRDeck Name \\\n", - "0 0.0 0.0 0.0 0.0 0.0 Maham Ofracculy \n", - "1 109.0 9.0 25.0 549.0 44.0 Juanna Vines \n", - "2 43.0 3576.0 0.0 6715.0 49.0 Altark Susent \n", - "3 0.0 1283.0 371.0 3329.0 193.0 Solam Susent \n", - "4 303.0 70.0 151.0 565.0 2.0 Willy Santantines \n", - "\n", - " Transported \n", - "0 False \n", - "1 True \n", - "2 False \n", - "3 False \n", - "4 True " + " Age RoomService FoodCourt ShoppingMall Spa VRDeck\n", + "0 39.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\n", + "2 58.0 43.0 3576.0 0.0 6715.0 49.0\n", + "3 33.0 0.0 1283.0 371.0 3329.0 193.0\n", + "4 16.0 303.0 70.0 151.0 565.0 2.0" ] }, - "execution_count": 2, + "execution_count": 308, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "spaceship = pd.read_csv(\"https://raw.githubusercontent.com/data-bootcamp-v4/data/main/spaceship_titanic.csv\")\n", - "spaceship.head()" + "features.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now perform the same as before:\n", - "- Feature Scaling\n", - "- Feature Selection\n" + "**Perform Train Test Split**" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 309, "metadata": {}, "outputs": [], "source": [ - "#your code here" + "#your code here\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.20, random_state=42) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**Perform Train Test Split**" + "**Model Selection** - now you will try to apply different ensemble methods in order to get a better model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Bagging and Pasting" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 310, "metadata": {}, "outputs": [], "source": [ - "#your code here" + "from sklearn.ensemble import BaggingClassifier\n", + "from sklearn.tree import DecisionTreeClassifier\n", + "\n", + "bagging_clf = BaggingClassifier(DecisionTreeClassifier(max_depth=20),\n", + " n_estimators=100, # 100 arboles\n", + " max_samples=1000 # Del 80% del X_train va a coger paquetes de 1000\n", + " )\n" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 311, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
BaggingClassifier(estimator=DecisionTreeClassifier(max_depth=20),\n",
+       "                  max_samples=1000, n_estimators=100)
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": [ + "BaggingClassifier(estimator=DecisionTreeClassifier(max_depth=20),\n", + " max_samples=1000, n_estimators=100)" + ] + }, + "execution_count": 311, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bagging_clf.fit(X_train, y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 312, "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " False 0.83 0.74 0.78 653\n", + " True 0.77 0.85 0.81 669\n", + "\n", + " accuracy 0.80 1322\n", + " macro avg 0.80 0.79 0.79 1322\n", + "weighted avg 0.80 0.80 0.79 1322\n", + "\n" + ] + } + ], "source": [ - "**Model Selection** - now you will try to apply different ensemble methods in order to get a better model" + "from sklearn.metrics import classification_report\n", + "\n", + "# Make predictions\n", + "y_pred = bagging_clf.predict(X_test)\n", + "\n", + "# Generate the classification report\n", + "report = classification_report(y_test, y_pred)\n", + "print(report)" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 313, "metadata": {}, + "outputs": [], "source": [ - "- Bagging and Pasting" + "# 2. Repetición con Normalization\n", + "\n", + "from sklearn.preprocessing import MinMaxScaler\n", + "\n", + "normalizer = MinMaxScaler()\n", + "\n", + "X_train_norm = normalizer.fit_transform(X_train) \n", + "\n", + "X_test_norm = normalizer.transform(X_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 314, + "metadata": {}, + "outputs": [], + "source": [ + "X_train_norm = pd.DataFrame(X_train_norm, columns = X_train.columns) # Vuelvo a dar formato de df\n", + "X_test_norm = pd.DataFrame(X_test_norm, columns = X_test.columns)" + ] + }, + { + "cell_type": "code", + "execution_count": 315, + "metadata": {}, + "outputs": [], + "source": [ + "bagging_clf_norm = BaggingClassifier(DecisionTreeClassifier(max_depth=20),\n", + " n_estimators=100, \n", + " bootstrap=True, # Esto es para que sea bagging o pasting (no es obligatorio especificar) \n", + " max_samples=1000 # Toma 1000 muestras para cada uno (si pusiera 0.X cogeria el X0% de las muestras) \n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 316, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
BaggingClassifier(estimator=DecisionTreeClassifier(max_depth=20),\n",
+       "                  max_samples=1000, n_estimators=100)
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": [ + "BaggingClassifier(estimator=DecisionTreeClassifier(max_depth=20),\n", + " max_samples=1000, n_estimators=100)" + ] + }, + "execution_count": 316, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bagging_clf_norm.fit(X_train_norm, y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 317, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " False 0.83 0.74 0.78 653\n", + " True 0.77 0.85 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" + ] + } + ], + "source": [ + "# Make predictions\n", + "y_pred_norm = bagging_clf_norm.predict(X_test_norm)\n", + "\n", + "# Generate the classification report\n", + "report = classification_report(y_test, y_pred_norm)\n", + "print(report)" + ] + }, + { + "cell_type": "code", + "execution_count": 318, + "metadata": {}, + "outputs": [], + "source": [ + "# 3. Repetición con Scaling\n", + "from sklearn.preprocessing import StandardScaler\n", + "\n", + "scaler = StandardScaler() \n", + "X_train_scaling = scaler.fit_transform(X_train)\n", + "X_train_scaling = pd.DataFrame(X_train_scaling, columns = X_train.columns)\n", + "\n", + "X_test_scaling = scaler.transform(X_test)\n", + "X_test_scaling = pd.DataFrame(X_test_scaling, columns = X_test.columns)" + ] + }, + { + "cell_type": "code", + "execution_count": 319, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
BaggingClassifier(estimator=DecisionTreeClassifier(max_depth=20),\n",
+       "                  max_samples=1000, n_estimators=100)
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": [ + "BaggingClassifier(estimator=DecisionTreeClassifier(max_depth=20),\n", + " max_samples=1000, n_estimators=100)" + ] + }, + "execution_count": 319, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bagging_clf_scaling = BaggingClassifier(DecisionTreeClassifier(max_depth=20),\n", + " n_estimators=100, \n", + " max_samples=1000 \n", + " )\n", + "\n", + "bagging_clf_scaling.fit(X_train_scaling, y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 320, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " False 0.83 0.74 0.78 653\n", + " True 0.77 0.85 0.81 669\n", + "\n", + " accuracy 0.80 1322\n", + " macro avg 0.80 0.80 0.79 1322\n", + "weighted avg 0.80 0.80 0.80 1322\n", + "\n" + ] + } + ], + "source": [ + "# Make predictions\n", + "y_pred_scaling = bagging_clf_scaling.predict(X_test_scaling)\n", + "\n", + "# Generate the classification report\n", + "report = classification_report(y_test, y_pred_scaling)\n", + "print(report)" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 321, "metadata": {}, "outputs": [], "source": [ - "#your code here" + "### EN VISTA DE LAS 3 FORMAS DE REALIZAR ESTA PREDICCIÓN, LA MEJOR MANERA, ATENDIENDO AL f1-score (POR UNA LIGERA DIFERENCIA) ES LA NORMALIZACIÓN" ] }, { @@ -272,11 +1828,46 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 322, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " False 0.83 0.74 0.78 653\n", + " True 0.77 0.85 0.81 669\n", + "\n", + " accuracy 0.79 1322\n", + " macro avg 0.80 0.79 0.79 1322\n", + "weighted avg 0.80 0.79 0.79 1322\n", + "\n", + "Accuracy: 0.7934947049924357\n" + ] + } + ], "source": [ - "#your code here" + "#your code here\n", + "# Import necessary libraries\n", + "from sklearn.ensemble import RandomForestClassifier\n", + "from sklearn.metrics import root_mean_squared_error, mean_absolute_error, r2_score\n", + "from sklearn.metrics import classification_report, accuracy_score\n", + "# Create and train the Random Forest regressor\n", + "\n", + "rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)\n", + "rf_classifier.fit(X_train_norm, y_train)\n", + "\n", + "# Make predictions\n", + "y_pred_norm = rf_classifier.predict(X_test_norm)\n", + "\n", + "# Evaluate the model\n", + "report = classification_report(y_test, y_pred_norm) \n", + "print(report)\n", + "\n", + "accuracy = accuracy_score(y_test, y_pred_norm)\n", + "print(f\"Accuracy: {accuracy}\")\n" ] }, { @@ -288,49 +1879,201 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 323, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " False 0.83 0.74 0.78 653\n", + " True 0.77 0.85 0.81 669\n", + "\n", + " accuracy 0.79 1322\n", + " macro avg 0.80 0.79 0.79 1322\n", + "weighted avg 0.80 0.79 0.79 1322\n", + "\n" + ] + } + ], "source": [ - "#your code here" + "#your code here\n", + "from sklearn.ensemble import BaggingRegressor, RandomForestRegressor, GradientBoostingClassifier\n", + "\n", + "gb_clas = GradientBoostingClassifier(max_depth=20,\n", + " n_estimators=100)\n", + "\n", + "gb_clas.fit(X_train_norm, y_train)\n", + "\n", + "pred_gb_norm = gb_clas.predict(X_test_norm)\n", + "\n", + "report = classification_report(y_test, y_pred_norm) \n", + "print(report)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "- Adaptive Boosting" + "- Adaptive Boosting (AdaBoost)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 324, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Anaconda\\Lib\\site-packages\\sklearn\\ensemble\\_weight_boosting.py:519: FutureWarning: The SAMME.R algorithm (the default) is deprecated and will be removed in 1.6. Use the SAMME algorithm to circumvent this warning.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " False 0.83 0.74 0.78 653\n", + " True 0.77 0.85 0.81 669\n", + "\n", + " accuracy 0.79 1322\n", + " macro avg 0.80 0.79 0.79 1322\n", + "weighted avg 0.80 0.79 0.79 1322\n", + "\n" + ] + } + ], "source": [ - "#your code here" + "#your code here\n", + "from sklearn.tree import DecisionTreeClassifier\n", + "from sklearn.ensemble import AdaBoostClassifier\n", + "\n", + "ada_clas = AdaBoostClassifier(DecisionTreeClassifier(max_depth=20),\n", + " n_estimators=200)\n", + "\n", + "ada_clas.fit(X_train_norm, y_train)\n", + "\n", + "report = classification_report(y_test, y_pred_norm) \n", + "print(report)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Which model is the best and why?" + "## Which model is the best and why?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The best model is bagging with scaling (very close to the others) because its f1-score is 0.80, and for the rest 0.79" + ] + }, + { + "cell_type": "code", + "execution_count": 325, + "metadata": {}, + "outputs": [], + "source": [ + "# Una vez que tenemos el mejor modelo, podriamos predecir los resultados de la Spaceship.\n", + "\n", + "predictions = bagging_clf_norm.predict(features)\n", + "\n", + "\n", + "predictions = pd.DataFrame(predictions, columns=['Resuls_predicted'])" + ] + }, + { + "cell_type": "code", + "execution_count": 326, + "metadata": {}, + "outputs": [], + "source": [ + "spaceship[\"predictions\"] = predictions " + ] + }, + { + "cell_type": "code", + "execution_count": 327, + "metadata": {}, + "outputs": [], + "source": [ + "spaceship[\"Resta\"] = spaceship[\"Transported\"].astype(int) - spaceship[\"predictions\"].astype(int)" + ] + }, + { + "cell_type": "code", + "execution_count": 328, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.7275204359673024" + ] + }, + "execution_count": 328, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spaceship[\"Resta\"].value_counts()[0] / spaceship[\"Resta\"].value_counts().sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 329, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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rKxS3/dvf/tbmcZZWFioPn36KD09XWvWrFHdunXPG5ubm6utW7fqrrvuUsWKFc32wMBA9ezZ0yV29erVstlsuu+++3T69GnziIiIUPPmzT264+fzzz+XpGILfW+++WY1btxYn332mUt7RESEbr75Zpe266+/Xvv37/fYmFq0aCF/f38NGjRIb7zxRqmmqaQzvw86depUrDLUv39//f7778UqNX+etpLOPIckjz4LgD+QkOCyY7PZ9MADD2jJkiWaPXu2rrnmGt16660lxm7ZskUxMTGSzuws+eqrr7R161aNHz9ekpSXl1fq+9aoUaNM4xwyZIiSkpL03nvvqUWLFheMzc7OVlFRkSIiIoqdO7ftyJEjMgxD4eHh8vPzczlSUlKKTaP8WWhoqCpXrqyMjIxSPcOvv/4qqeRnj4yMNM+fFRISUizObreX6efsTv369fXpp58qLCxMw4YNU/369VW/fn298sorF7zu119/Pe9znD3/Z+c+y9n1Np58FgB/YJcNLkv9+/fXhAkTNHv2bD377LPnjVu2bJn8/Py0evVql8rDypUry3zPsrwLZNKkSZo3b54WLlxoJkQXUq1aNdlsNmVmZhY7d25baGiobDabvvzyyxIXpZbUdpaPj486deqk//znPzp48OB5t8WedfYv5cOHDxeLPXTokEJDQy94fVmc/fXJz893eYaSEqxbb71Vt956qwoLC7Vt2zZNnz5dCQkJCg8P1z333FNi/yEhITp8+HCx9kOHDkmSR58FQNlRIcFlqWbNmho7dqx69uypfv36nTfOZrPJ19dXPj4+ZlteXp4WL15cLNZT/5KfP3++nn76aT3zzDOlfqdJQECAbr75Zi1fvlwnT54023/77Td9+OGHLrGxsbEyDEM///yzbrzxxmJHs2bNLnivcePGyTAMDRw4sMRFoAUFBeY9b7vtNkkyF6WetXXrVqWnp6tTp06ler7SOLuraceOHS7t5z7/n/n4+CgqKkqvvfaaJGn79u3nje3UqZPWrVtnJiBnvfnmm6pcufJlt30buNJQIcFla/LkyW5jevTooZdeekl9+/bVoEGD9Ouvv+qFF14osYrQrFkzLVu2TO+8846uvvpqVaxY0e1f7udKTk7WkCFDdMstt6hLly5KSUlxOX+hv/T+9a9/qVu3bua7QAoLCzVlyhQFBAS4vDn1lltu0aBB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+vXrZ9xxxx3m582bNxshISFG7969jYkTJxp+fn5GVlaWef6zzz4zgoKCjJMnT7r0U79+fWPOnDmGYRhGdHS0MWTIEJfzUVFRRvPmzUu874kTJwy73W7MnTu3xDHOmTPHCAwMNH799dcSz0+cONGl78jISOPZZ591ibnpppuMoUOHGoZhGBkZGYYkY968eeb5Xbt2GZKM9PT0Eu8B4K+NCglwEaxevVpVqlRRxYoVFR0drXbt2mn69OmSpLp166p69epmbGpqqnJychQSEmKu3ahSpYoyMjL0ww8/SJLS09MVHR3tco9zP/9Zenq68vPz1alTpxLPp6WlqWXLlgoODnb7LCdOnNChQ4d0yy23uLTfcsstSk9Pd2n7886bGjVqSJKysrLc3gPAXw+LWoGLoGPHjpo1a5b8/PwUGRnpsnA1ICDAJbaoqEg1atTQF198UayfqlWrluv+lSpV+p/Ol8Rms7l8NgyjWNufn/PsufNNAwH4a6NCAlwEAQEBatCggerWret2F80NN9ygzMxM+fr6qkGDBi5HaGioJKlx48ZKSUlxue7cz3/WsGFDVapUqcStu9KZSkZaWpq5RuVCgoKCFBkZqY0bN7q0b9q0SY0bN3Z7PQCUhIQEuMR07txZ0dHR6tWrlz7++GPt27dPmzZt0j//+U9t27ZNkvTII49owYIFWrBggb777jtNnDhRu3btOm+fFStW1OOPP67HHntMb775pn744QelpKRo/vz5kqR//OMfioiIUK9evfTVV1/pxx9/1Pvvv3/eXTFjx47VlClT9M4772jPnj164oknlJaWpkceecTzPxAAfwlM2QCXGJvNpjVr1mj8+PF68MEHdfToUUVERKhdu3bmrpg+ffrohx9+0OOPP66TJ0/qb3/7mx5++GF9/PHH5+33qaeekq+vryZMmKBDhw6pRo0aGjJkiCTJ399fn3zyiUaPHq3bb79dp0+fVpMmTfTaa6+V2NfIkSN14sQJjR49WllZWWrSpIlWrVqlhg0bev4HAuAvwWYYhuHtQQAAgL82pmwAAIDXkZAAAACvIyEBAABeR0ICAAC8joQEAAB4HQkJAADwOhISAADgdSQkAADA60hIAACA15GQAAAAryMhAQAAXkdCAgAAvO7/Ab4fT9w/hd2bAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.metrics import confusion_matrix\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "cm = confusion_matrix(spaceship[\"Transported\"], spaceship[\"predictions\"])\n", + "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')\n", + "plt.xlabel('Predicción')\n", + "plt.ylabel('Real')\n", + "plt.title('Matriz de Confusión')\n", + "plt.show()\n", + "\n", + "\n", + "# ESTO ES MUY ÚTIL PERO SOLO EN CLASIFICACIÓN" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 330, "metadata": {}, "outputs": [], "source": [ - "#comment here" + "# La razón de que que el f1-score sea 0.80 pero tenga un % de aciertos de apenas el 50% es porque " ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "base", "language": "python", "name": "python3" }, @@ -344,7 +2087,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.12.4" } }, "nbformat": 4,