{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "**Nota:** Aquest quadern està dissenyat per a **Google Colab**.\n",
        "\n",
        "Si veieu el logotip de Colab <span style='vertical-align:bottom;'><img src='https://colab.research.google.com/img/colab_favicon_256px.png' width='40' alt='Colab logo'></span> a la cantonada superior esquerra, ja ho teniu tot a punt! Si us plau, **continueu**.\n",
        "\n",
        "Si no veieu el logotip (per exemple, si esteu a GitHub), feu clic al botó de sota per obrir-lo a l'entorn correcte:\n",
        "\n",
        "[![Obrir a Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mparrott-at-wiris/aimodelshare/blob/master/notebooks/justice_and_equity_advance_notebook_ca.ipynb)"
      ],
      "metadata": {
        "id": "pjnUTfUOGMX3"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "# **Repte Avançat de Justícia i Equitat: Construir i Enviar Models Personalitzats**\n",
        "\n",
        "Benvinguts a la **Via Avançada** del Repte de Justícia d'Ètica en Joc (Ethics at Play).\n",
        "\n",
        "**A qui va dirigit?**\n",
        "Aquest quadern està dissenyat per a participants amb experiència en Python (per exemple, Scikit-Learn, TensorFlow, PyTorch). En lloc d'utilitzar les aplicacions ludificades, construireu, entrenareu i enviareu els vostres propis models d'aprenentatge automàtic directament a la classificació de la competició.\n",
        "\n",
        "**L'Objectiu:**\n",
        "Entrenar un model per predir el risc de reincidència (la probabilitat de tornar a delinquir) utilitzant el conjunt de dades COMPAS, equilibrant la precisió i l'equitat."
      ],
      "metadata": {
        "id": "intro_advanced"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 🚀 **Guia d'Inici Ràpid**\n",
        "\n",
        "Per participar en el repte, completeu aquests 5 passos:\n",
        "\n",
        "1.  **Instal·lar Llibreries:** Executeu la cel·la de configuració per instal·lar `aimodelshare`.\n",
        "2.  **Obtenir les Dades:** Executeu la cel·la de càrrega de dades per recuperar les dades d'entrenament i prova pre-dividides.\n",
        "3.  **Entrenar el Vostre Model:** Utilitzeu l'exemple de Pipeline de Scikit-Learn proporcionat o escriviu el vostre propi codi d'entrenament personalitzat.\n",
        "4.  **Connectar:** Enllaceu aquest quadern a la Classificació del Repte de Justícia.\n",
        "5.  **Enviar:** Envieu les vostres prediccions a la classificació per veure la vostra puntuació.\n",
        "\n",
        "**Preparats? Feu clic al botó de reproducció ▶ a la primera cel·la de sota per començar.**"
      ],
      "metadata": {
        "id": "quick_start_guide"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "---\n",
        "# **Pas 1: Instal·lació**\n",
        "\n",
        "Hem d'instal·lar la llibreria `aimodelshare` per connectar-nos al backend de la competició."
      ],
      "metadata": {
        "id": "step1_md"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Instal·lar la llibreria aimodelshare\n",
        "print(\"Instal·lant les llibreries necessàries...\")\n",
        "!pip install aimodelshare --upgrade -q --no-warn-script-location > /dev/null 2>&1\n",
        "print(\"✅ Instal·lació completada!\")"
      ],
      "metadata": {
        "id": "step1_code"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "---\n",
        "# **Pas 2: Carregar Dades**\n",
        "\n",
        "Carregarem les dades d'entrenament i prova directament des de les URL oficials de la competició.\n",
        "\n",
        "* **X_train:** Característiques per a l'entrenament.\n",
        "* **y_train:** Etiquetes objectiu (s'ha produït reincidència?) per a l'entrenament.\n",
        "* **X_test:** Característiques per a la prova (generareu prediccions sobre això)."
      ],
      "metadata": {
        "id": "step2_md"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import pandas as pd\n",
        "\n",
        "# 1. Carregar Dades des de les URL\n",
        "X_train = pd.read_csv(\"https://raw.githubusercontent.com/AIModelShare/aimodelshare_tutorials/refs/heads/main/datasets/ethicsatplay/X_train.csv\")\n",
        "X_test = pd.read_csv(\"https://raw.githubusercontent.com/AIModelShare/aimodelshare_tutorials/refs/heads/main/datasets/ethicsatplay/X_test.csv\")\n",
        "y_train_labels = pd.read_csv(\"https://raw.githubusercontent.com/AIModelShare/aimodelshare_tutorials/refs/heads/main/datasets/ethicsatplay/y_train.csv\")\n",
        "\n",
        "# Assegurar que y_train és una sèrie 1D (necessari per a sklearn)\n",
        "y_train = y_train_labels.squeeze()\n",
        "\n",
        "# 2. Definir Llistes de Característiques per al Pipeline\n",
        "# Aquestes llistes coincideixen amb les columnes presents a X_train i X_test\n",
        "ALL_NUMERIC_COLS = [\"juv_fel_count\", \"juv_misd_count\", \"juv_other_count\", \"days_b_screening_arrest\", \"age\", \"length_of_stay\", \"priors_count\"]\n",
        "ALL_CATEGORICAL_COLS = [\"race\", \"sex\", \"c_charge_degree\", \"c_charge_desc\"]\n",
        "\n",
        "print(\"✅ Dades carregades correctament!\")\n",
        "print(f\"Forma de les dades d'entrenament: {X_train.shape}\")\n",
        "print(f\"Forma de les dades de prova: {X_test.shape}\")\n",
        "print(\"\\nPrimeres 5 files de les dades d'entrenament:\")\n",
        "X_train.head()"
      ],
      "metadata": {
        "id": "step2_code"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "---\n",
        "# **Pas 3: Entrenar el Model amb la Llibreria Preferida (Sklearn, Tensorflow, Pytorch, etc.)**\n",
        "\n",
        "Utilitzarem un **Pipeline de Scikit-Learn** per agilitzar el preprocessament i el modelatge.\n",
        "\n",
        "Aquest pipeline:\n",
        "1.  **Imputar Valors Perduts** (Omplir els NaNs amb la mitjana per als números, el més freqüent per a les categories).\n",
        "2.  **Codificar One-Hot** les columnes categòriques (Raça, Sexe, Grau del Càrrec, Descripció del Càrrec).\n",
        "3.  **Escalar** les columnes numèriques (Edat, Antecedents, Durada de l'Estada, etc.).\n",
        "4.  **Entrenar** un classificador de Regressió Logística."
      ],
      "metadata": {
        "id": "step3_md"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from sklearn.pipeline import Pipeline\n",
        "from sklearn.compose import ColumnTransformer\n",
        "from sklearn.preprocessing import OneHotEncoder, StandardScaler\n",
        "from sklearn.impute import SimpleImputer\n",
        "from sklearn.linear_model import LogisticRegression\n",
        "\n",
        "# 1. Definir grups de característiques utilitzant constants del Pas 2\n",
        "# Les característiques numèriques s'imputaran i escalaran\n",
        "numeric_features = ALL_NUMERIC_COLS\n",
        "\n",
        "# Les característiques categòriques s'imputaran i es codificaran amb One-Hot\n",
        "categorical_features = ALL_CATEGORICAL_COLS\n",
        "\n",
        "# 2. Definir Transformadors amb Imputació\n",
        "# Numèric: Imputar valors perduts amb la mitjana, després escalar\n",
        "numeric_transformer = Pipeline(steps=[\n",
        "    ('imputer', SimpleImputer(strategy='median')),\n",
        "    ('scaler', StandardScaler())\n",
        "])\n",
        "\n",
        "# Categòric: Imputar valors perduts amb el valor més freqüent, després codificar amb One-Hot\n",
        "categorical_transformer = Pipeline(steps=[\n",
        "    ('imputer', SimpleImputer(strategy='most_frequent')),\n",
        "    ('encoder', OneHotEncoder(handle_unknown='ignore'))\n",
        "])\n",
        "\n",
        "# 3. Crear Preprocessador utilitzant els transformadors\n",
        "preprocessor = ColumnTransformer(\n",
        "    transformers=[\n",
        "        ('num', numeric_transformer, numeric_features),\n",
        "        ('cat', categorical_transformer, categorical_features)\n",
        "    ])\n",
        "\n",
        "# 4. Crear Pipeline (Preprocessador + Model)\n",
        "# Podeu substituir LogisticRegression per qualsevol altre model de sklearn (per exemple, RandomForestClassifier)\n",
        "pipeline = Pipeline(steps=[\n",
        "    ('preprocessor', preprocessor),\n",
        "    ('classifier', LogisticRegression(max_iter=1000))\n",
        "])\n",
        "\n",
        "# 5. Entrenar el pipeline\n",
        "pipeline.fit(X_train, y_train)\n",
        "\n",
        "# 6. Generar prediccions al conjunt de prova\n",
        "predictions = pipeline.predict(X_test)\n",
        "\n",
        "print(f\"✅ Model Entrenat! Prediccions generades per a {len(predictions)} mostres.\")\n",
        "print(\"Procediu al següent pas per enviar les vostres prediccions a la classificació.\")"
      ],
      "metadata": {
        "id": "step3_code"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "---\n",
        "# **Pas 4: Connectar a la Classificació**\n",
        "\n",
        "Aquest pas connecta el vostre quadern al backend específic per al Repte de Justícia i Equitat.\n",
        "\n",
        "*Nota: Se us demanarà que introduïu un nom d'usuari i una contrasenya. Si no en teniu, haureu de crear-ne un a [modelshare.ai](https://www.modelshare.ai)"
      ],
      "metadata": {
        "id": "step4_md"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from aimodelshare.aws import set_credentials\n",
        "from aimodelshare.playground import Competition\n",
        "import os\n",
        "\n",
        "import warnings\n",
        "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
        "\n",
        "\n",
        "# L'URL específic del Model Playground per al Repte de Justícia\n",
        "my_playground_url = \"https://cf3wdpkg0d.execute-api.us-east-1.amazonaws.com/prod/m\"\n",
        "\n",
        "# Establiu les vostres credencials (apareixerà una finestra emergent)\n",
        "set_credentials(apiurl=my_playground_url)\n",
        "\n",
        "# Genereu el vostre testimoni d'accés a la sessió\n",
        "token=os.getenv(\"AWS_TOKEN\")\n",
        "\n",
        "# Connectar a la competició\n",
        "playground = Competition(my_playground_url)"
      ],
      "metadata": {
        "id": "step4_code"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "---\n",
        "# **Pas 5: Enviar i Comprovar Resultats**\n",
        "\n",
        "Envieu les vostres prediccions a la classificació."
      ],
      "metadata": {
        "id": "step5_md"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 1. Envieu les vostres prediccions\n",
        "# Nota: Passem None per al model i el preprocessador perquè només enviem prediccions per a l'avaluació\n",
        "playground.submit_model(\n",
        "    model=None,\n",
        "    preprocessor=None,\n",
        "    prediction_submission=predictions, token=token,\n",
        "    input_dict={\n",
        "        \"Team\": \"Els Cercadors d'Equitat\", # Canvieu el nom de l'equip manualment si cal.\n",
        "        \"description\": \"Regressió Logística amb Pipeline de Sklearn\",\n",
        "        \"tags\": \"sklearn, logistic_regression, advanced_pathway, pipeline\"\n",
        "    }\n",
        ")\n",
        "\n",
        "print(\"✅ Prediccions enviades correctament!\")\n",
        "\n",
        "# 2. Comprovar la classificació\n",
        "print(\"Carregant classificació...\")\n",
        "leaderboard = playground.get_leaderboard()\n",
        "playground.stylize_leaderboard(leaderboard)"
      ],
      "metadata": {
        "id": "step5_code"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}
