You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
725 lines
28 KiB
725 lines
28 KiB
{
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2,
|
|
"metadata": {
|
|
"colab": {
|
|
"name": "lesson_10-R.ipynb",
|
|
"provenance": [],
|
|
"collapsed_sections": []
|
|
},
|
|
"kernelspec": {
|
|
"name": "ir",
|
|
"display_name": "R"
|
|
},
|
|
"language_info": {
|
|
"name": "R"
|
|
},
|
|
"coopTranslator": {
|
|
"original_hash": "2621e24705e8100893c9bf84e0fc8aef",
|
|
"translation_date": "2025-09-04T02:47:42+00:00",
|
|
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
|
|
"language_code": "es"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"# Construir un modelo de clasificación: Deliciosas cocinas asiáticas e indias\n"
|
|
],
|
|
"metadata": {
|
|
"id": "ItETB4tSFprR"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Introducción a la clasificación: Limpia, prepara y visualiza tus datos\n",
|
|
"\n",
|
|
"En estas cuatro lecciones, explorarás un enfoque fundamental del aprendizaje automático clásico: la *clasificación*. Recorreremos el uso de varios algoritmos de clasificación con un conjunto de datos sobre las brillantes cocinas de Asia e India. ¡Espero que tengas hambre!\n",
|
|
"\n",
|
|
"<p>\n",
|
|
" <img src=\"../../images/pinch.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>¡Celebra las cocinas panasiáticas en estas lecciones! Imagen de Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!---->\n",
|
|
"\n",
|
|
"La clasificación es una forma de [aprendizaje supervisado](https://wikipedia.org/wiki/Supervised_learning) que tiene mucho en común con las técnicas de regresión. En la clasificación, entrenas un modelo para predecir a qué `categoría` pertenece un elemento. Si el aprendizaje automático se trata de predecir valores o nombres de cosas utilizando conjuntos de datos, entonces la clasificación generalmente se divide en dos grupos: *clasificación binaria* y *clasificación multiclase*.\n",
|
|
"\n",
|
|
"Recuerda:\n",
|
|
"\n",
|
|
"- **Regresión lineal** te ayudó a predecir relaciones entre variables y hacer predicciones precisas sobre dónde caería un nuevo punto de datos en relación con esa línea. Por ejemplo, podrías predecir valores numéricos como *el precio de una calabaza en septiembre frente a diciembre*.\n",
|
|
"\n",
|
|
"- **Regresión logística** te ayudó a descubrir \"categorías binarias\": a este precio, *¿es esta calabaza naranja o no naranja*?\n",
|
|
"\n",
|
|
"La clasificación utiliza varios algoritmos para determinar otras formas de identificar la etiqueta o clase de un punto de datos. Trabajemos con estos datos de cocina para ver si, al observar un grupo de ingredientes, podemos determinar su cocina de origen.\n",
|
|
"\n",
|
|
"### [**Cuestionario previo a la lección**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/19/)\n",
|
|
"\n",
|
|
"### **Introducción**\n",
|
|
"\n",
|
|
"La clasificación es una de las actividades fundamentales del investigador de aprendizaje automático y del científico de datos. Desde la clasificación básica de un valor binario (\"¿es este correo electrónico spam o no?\"), hasta la clasificación y segmentación compleja de imágenes utilizando visión por computadora, siempre es útil poder clasificar datos en categorías y hacer preguntas sobre ellos.\n",
|
|
"\n",
|
|
"Para expresar el proceso de una manera más científica, tu método de clasificación crea un modelo predictivo que te permite mapear la relación entre las variables de entrada y las variables de salida.\n",
|
|
"\n",
|
|
"<p>\n",
|
|
" <img src=\"../../images/binary-multiclass.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Problemas binarios vs. multiclase para que los algoritmos de clasificación manejen. Infografía de Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"Antes de comenzar el proceso de limpiar nuestros datos, visualizarlos y prepararlos para nuestras tareas de aprendizaje automático, aprendamos un poco sobre las diversas formas en que el aprendizaje automático puede ser utilizado para clasificar datos.\n",
|
|
"\n",
|
|
"Derivada de la [estadística](https://wikipedia.org/wiki/Statistical_classification), la clasificación utilizando aprendizaje automático clásico emplea características como `fumador`, `peso` y `edad` para determinar la *probabilidad de desarrollar X enfermedad*. Como técnica de aprendizaje supervisado similar a los ejercicios de regresión que realizaste anteriormente, tus datos están etiquetados y los algoritmos de aprendizaje automático utilizan esas etiquetas para clasificar y predecir clases (o 'características') de un conjunto de datos y asignarlas a un grupo o resultado.\n",
|
|
"\n",
|
|
"✅ Tómate un momento para imaginar un conjunto de datos sobre cocinas. ¿Qué podría responder un modelo multiclase? ¿Qué podría responder un modelo binario? ¿Qué pasaría si quisieras determinar si una cocina dada es probable que use fenogreco? ¿Y si quisieras ver si, dado un regalo de una bolsa de supermercado llena de anís estrellado, alcachofas, coliflor y rábano picante, podrías crear un plato típico indio?\n",
|
|
"\n",
|
|
"### **Hola 'clasificador'**\n",
|
|
"\n",
|
|
"La pregunta que queremos hacerle a este conjunto de datos de cocina es en realidad una **pregunta multiclase**, ya que tenemos varias cocinas nacionales potenciales con las que trabajar. Dado un lote de ingredientes, ¿a cuál de estas muchas clases se ajustarán los datos?\n",
|
|
"\n",
|
|
"Tidymodels ofrece varios algoritmos diferentes para clasificar datos, dependiendo del tipo de problema que quieras resolver. En las próximas dos lecciones, aprenderás sobre varios de estos algoritmos.\n",
|
|
"\n",
|
|
"#### **Requisitos previos**\n",
|
|
"\n",
|
|
"Para esta lección, necesitaremos los siguientes paquetes para limpiar, preparar y visualizar nuestros datos:\n",
|
|
"\n",
|
|
"- `tidyverse`: El [tidyverse](https://www.tidyverse.org/) es una [colección de paquetes de R](https://www.tidyverse.org/packages) diseñada para hacer la ciencia de datos más rápida, fácil y divertida.\n",
|
|
"\n",
|
|
"- `tidymodels`: El marco [tidymodels](https://www.tidymodels.org/) es una [colección de paquetes](https://www.tidymodels.org/packages/) para modelado y aprendizaje automático.\n",
|
|
"\n",
|
|
"- `DataExplorer`: El paquete [DataExplorer](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html) está diseñado para simplificar y automatizar el proceso de EDA y la generación de informes.\n",
|
|
"\n",
|
|
"- `themis`: El paquete [themis](https://themis.tidymodels.org/) proporciona pasos adicionales de recetas para tratar con datos desbalanceados.\n",
|
|
"\n",
|
|
"Puedes instalarlos con:\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"DataExplorer\", \"here\"))`\n",
|
|
"\n",
|
|
"Alternativamente, el siguiente script verifica si tienes los paquetes necesarios para completar este módulo y los instala por ti en caso de que falten.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "ri5bQxZ-Fz_0"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\r\n",
|
|
"\r\n",
|
|
"pacman::p_load(tidyverse, tidymodels, DataExplorer, themis, here)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "KIPxa4elGAPI"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Luego cargaremos estos paquetes increíbles y los pondremos a disposición en nuestra sesión actual de R. (Esto es solo para ilustración, `pacman::p_load()` ya hizo eso por ti)\n"
|
|
],
|
|
"metadata": {
|
|
"id": "YkKAxOJvGD4C"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Ejercicio - limpia y equilibra tus datos\n",
|
|
"\n",
|
|
"La primera tarea, antes de comenzar este proyecto, es limpiar y **equilibrar** tus datos para obtener mejores resultados.\n",
|
|
"\n",
|
|
"¡Conozcamos los datos! 🕵️\n"
|
|
],
|
|
"metadata": {
|
|
"id": "PFkQDlk0GN5O"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Import data\r\n",
|
|
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/4-Classification/data/cuisines.csv\")\r\n",
|
|
"\r\n",
|
|
"# View the first 5 rows\r\n",
|
|
"df %>% \r\n",
|
|
" slice_head(n = 5)\r\n"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "Qccw7okxGT0S"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"¡Interesante! Por lo que parece, la primera columna es una especie de columna de `id`. Vamos a obtener un poco más de información sobre los datos.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "XrWnlgSrGVmR"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Basic information about the data\r\n",
|
|
"df %>%\r\n",
|
|
" introduce()\r\n",
|
|
"\r\n",
|
|
"# Visualize basic information above\r\n",
|
|
"df %>% \r\n",
|
|
" plot_intro(ggtheme = theme_light())"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "4UcGmxRxGieA"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"A partir del resultado, podemos ver inmediatamente que tenemos `2448` filas y `385` columnas y `0` valores faltantes. También tenemos 1 columna discreta, *cuisine*.\n",
|
|
"\n",
|
|
"## Ejercicio - aprendiendo sobre las cocinas\n",
|
|
"\n",
|
|
"Ahora el trabajo comienza a ponerse más interesante. Vamos a descubrir la distribución de los datos, por tipo de cocina.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "AaPubl__GmH5"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Count observations per cuisine\r\n",
|
|
"df %>% \r\n",
|
|
" count(cuisine) %>% \r\n",
|
|
" arrange(n)\r\n",
|
|
"\r\n",
|
|
"# Plot the distribution\r\n",
|
|
"theme_set(theme_light())\r\n",
|
|
"df %>% \r\n",
|
|
" count(cuisine) %>% \r\n",
|
|
" ggplot(mapping = aes(x = n, y = reorder(cuisine, -n))) +\r\n",
|
|
" geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n",
|
|
" ylab(\"cuisine\")"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "FRsBVy5eGrrv"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Hay un número finito de cocinas, pero la distribución de los datos es desigual. ¡Puedes arreglar eso! Antes de hacerlo, explora un poco más.\n",
|
|
"\n",
|
|
"A continuación, asignemos cada cocina a su propio tibble y averigüemos cuántos datos están disponibles (filas, columnas) por cocina.\n",
|
|
"\n",
|
|
"> Un [tibble](https://tibble.tidyverse.org/) es un marco de datos moderno.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/dplyr_filter.jpg\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustración por @allison_horst</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "vVvyDb1kG2in"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Create individual tibble for the cuisines\r\n",
|
|
"thai_df <- df %>% \r\n",
|
|
" filter(cuisine == \"thai\")\r\n",
|
|
"japanese_df <- df %>% \r\n",
|
|
" filter(cuisine == \"japanese\")\r\n",
|
|
"chinese_df <- df %>% \r\n",
|
|
" filter(cuisine == \"chinese\")\r\n",
|
|
"indian_df <- df %>% \r\n",
|
|
" filter(cuisine == \"indian\")\r\n",
|
|
"korean_df <- df %>% \r\n",
|
|
" filter(cuisine == \"korean\")\r\n",
|
|
"\r\n",
|
|
"\r\n",
|
|
"# Find out how much data is available per cuisine\r\n",
|
|
"cat(\" thai df:\", dim(thai_df), \"\\n\",\r\n",
|
|
" \"japanese df:\", dim(japanese_df), \"\\n\",\r\n",
|
|
" \"chinese_df:\", dim(chinese_df), \"\\n\",\r\n",
|
|
" \"indian_df:\", dim(indian_df), \"\\n\",\r\n",
|
|
" \"korean_df:\", dim(korean_df))"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "0TvXUxD3G8Bk"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## **Ejercicio - Descubriendo los ingredientes principales por cocina usando dplyr**\n",
|
|
"\n",
|
|
"Ahora puedes profundizar en los datos y aprender cuáles son los ingredientes típicos de cada cocina. Deberías eliminar datos recurrentes que generan confusión entre las cocinas, así que vamos a aprender sobre este problema.\n",
|
|
"\n",
|
|
"Crea una función `create_ingredient()` en R que devuelva un dataframe de ingredientes. Esta función comenzará eliminando una columna poco útil y clasificará los ingredientes según su frecuencia.\n",
|
|
"\n",
|
|
"La estructura básica de una función en R es:\n",
|
|
"\n",
|
|
"`myFunction <- function(arglist){`\n",
|
|
"\n",
|
|
"**`...`**\n",
|
|
"\n",
|
|
"**`return`**`(value)`\n",
|
|
"\n",
|
|
"`}`\n",
|
|
"\n",
|
|
"Una introducción ordenada a las funciones en R se puede encontrar [aquí](https://skirmer.github.io/presentations/functions_with_r.html#1).\n",
|
|
"\n",
|
|
"¡Vamos directo al grano! Usaremos los [verbos de dplyr](https://dplyr.tidyverse.org/) que hemos estado aprendiendo en nuestras lecciones anteriores. Como recordatorio:\n",
|
|
"\n",
|
|
"- `dplyr::select()`: te ayuda a elegir qué **columnas** mantener o excluir.\n",
|
|
"\n",
|
|
"- `dplyr::pivot_longer()`: te ayuda a \"alargar\" los datos, aumentando el número de filas y disminuyendo el número de columnas.\n",
|
|
"\n",
|
|
"- `dplyr::group_by()` y `dplyr::summarise()`: te ayudan a encontrar estadísticas resumidas para diferentes grupos y a colocarlas en una tabla ordenada.\n",
|
|
"\n",
|
|
"- `dplyr::filter()`: crea un subconjunto de los datos que solo contiene las filas que cumplen tus condiciones.\n",
|
|
"\n",
|
|
"- `dplyr::mutate()`: te ayuda a crear o modificar columnas.\n",
|
|
"\n",
|
|
"Consulta este [tutorial interactivo lleno de *arte*](https://allisonhorst.shinyapps.io/dplyr-learnr/#section-welcome) de Allison Horst, que introduce algunas funciones útiles para manipulación de datos en dplyr *(parte del Tidyverse)*.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "K3RF5bSCHC76"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Creates a functions that returns the top ingredients by class\r\n",
|
|
"\r\n",
|
|
"create_ingredient <- function(df){\r\n",
|
|
" \r\n",
|
|
" # Drop the id column which is the first colum\r\n",
|
|
" ingredient_df = df %>% select(-1) %>% \r\n",
|
|
" # Transpose data to a long format\r\n",
|
|
" pivot_longer(!cuisine, names_to = \"ingredients\", values_to = \"count\") %>% \r\n",
|
|
" # Find the top most ingredients for a particular cuisine\r\n",
|
|
" group_by(ingredients) %>% \r\n",
|
|
" summarise(n_instances = sum(count)) %>% \r\n",
|
|
" filter(n_instances != 0) %>% \r\n",
|
|
" # Arrange by descending order\r\n",
|
|
" arrange(desc(n_instances)) %>% \r\n",
|
|
" mutate(ingredients = factor(ingredients) %>% fct_inorder())\r\n",
|
|
" \r\n",
|
|
" \r\n",
|
|
" return(ingredient_df)\r\n",
|
|
"} # End of function"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "uB_0JR82HTPa"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Ahora podemos usar la función para hacernos una idea de los diez ingredientes más populares por cocina. Probémosla con `thai_df`.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "h9794WF8HWmc"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Call create_ingredient and display popular ingredients\r\n",
|
|
"thai_ingredient_df <- create_ingredient(df = thai_df)\r\n",
|
|
"\r\n",
|
|
"thai_ingredient_df %>% \r\n",
|
|
" slice_head(n = 10)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "agQ-1HrcHaEA"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"En la sección anterior, utilizamos `geom_col()`, veamos cómo también puedes usar `geom_bar` para crear gráficos de barras. Usa `?geom_bar` para leer más.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "kHu9ffGjHdcX"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Make a bar chart for popular thai cuisines\r\n",
|
|
"thai_ingredient_df %>% \r\n",
|
|
" slice_head(n = 10) %>% \r\n",
|
|
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
|
|
" geom_bar(stat = \"identity\", width = 0.5, fill = \"steelblue\") +\r\n",
|
|
" xlab(\"\") + ylab(\"\")"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "fb3Bx_3DHj6e"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [],
|
|
"metadata": {
|
|
"id": "RHP_xgdkHnvM"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Get popular ingredients for Japanese cuisines and make bar chart\r\n",
|
|
"create_ingredient(df = japanese_df) %>% \r\n",
|
|
" slice_head(n = 10) %>%\r\n",
|
|
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
|
|
" geom_bar(stat = \"identity\", width = 0.5, fill = \"darkorange\", alpha = 0.8) +\r\n",
|
|
" xlab(\"\") + ylab(\"\")\r\n"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "019v8F0XHrRU"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"¿Qué hay de las cocinas chinas?\n"
|
|
],
|
|
"metadata": {
|
|
"id": "iIGM7vO8Hu3v"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Get popular ingredients for Chinese cuisines and make bar chart\r\n",
|
|
"create_ingredient(df = chinese_df) %>% \r\n",
|
|
" slice_head(n = 10) %>%\r\n",
|
|
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
|
|
" geom_bar(stat = \"identity\", width = 0.5, fill = \"cyan4\", alpha = 0.8) +\r\n",
|
|
" xlab(\"\") + ylab(\"\")"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "lHd9_gd2HyzU"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [],
|
|
"metadata": {
|
|
"id": "ir8qyQbNH1c7"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Get popular ingredients for Indian cuisines and make bar chart\r\n",
|
|
"create_ingredient(df = indian_df) %>% \r\n",
|
|
" slice_head(n = 10) %>%\r\n",
|
|
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
|
|
" geom_bar(stat = \"identity\", width = 0.5, fill = \"#041E42FF\", alpha = 0.8) +\r\n",
|
|
" xlab(\"\") + ylab(\"\")"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "ApukQtKjH5FO"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Finalmente, grafica los ingredientes coreanos.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "qv30cwY1H-FM"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Get popular ingredients for Korean cuisines and make bar chart\r\n",
|
|
"create_ingredient(df = korean_df) %>% \r\n",
|
|
" slice_head(n = 10) %>%\r\n",
|
|
" ggplot(aes(x = n_instances, y = ingredients)) +\r\n",
|
|
" geom_bar(stat = \"identity\", width = 0.5, fill = \"#852419FF\", alpha = 0.8) +\r\n",
|
|
" xlab(\"\") + ylab(\"\")"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "lumgk9cHIBie"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"A partir de las visualizaciones de datos, ahora podemos eliminar los ingredientes más comunes que generan confusión entre cocinas distintas, utilizando `dplyr::select()`.\n",
|
|
"\n",
|
|
"¡A todos les encantan el arroz, el ajo y el jengibre!\n"
|
|
],
|
|
"metadata": {
|
|
"id": "iO4veMXuIEta"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Drop id column, rice, garlic and ginger from our original data set\r\n",
|
|
"df_select <- df %>% \r\n",
|
|
" select(-c(1, rice, garlic, ginger))\r\n",
|
|
"\r\n",
|
|
"# Display new data set\r\n",
|
|
"df_select %>% \r\n",
|
|
" slice_head(n = 5)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "iHJPiG6rIUcK"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Preprocesando datos usando recetas 👩🍳👨🍳 - Tratando con datos desbalanceados ⚖️\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/recipes.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustración por @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"Dado que esta lección trata sobre gastronomía, tenemos que poner las `recetas` en contexto.\n",
|
|
"\n",
|
|
"Tidymodels ofrece otro paquete interesante: `recipes`, un paquete para preprocesar datos.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "kkFd-JxdIaL6"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Echemos un vistazo nuevamente a la distribución de nuestras cocinas.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "6l2ubtTPJAhY"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Distribution of cuisines\r\n",
|
|
"old_label_count <- df_select %>% \r\n",
|
|
" count(cuisine) %>% \r\n",
|
|
" arrange(desc(n))\r\n",
|
|
"\r\n",
|
|
"old_label_count"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "1e-E9cb7JDVi"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Como puedes ver, hay una distribución bastante desigual en el número de cocinas. Las cocinas coreanas son casi 3 veces más que las tailandesas. Los datos desequilibrados a menudo tienen efectos negativos en el rendimiento del modelo. Piensa en una clasificación binaria. Si la mayor parte de tus datos pertenece a una clase, un modelo de ML va a predecir esa clase con más frecuencia, simplemente porque hay más datos de esa clase. Balancear los datos corrige cualquier sesgo y ayuda a eliminar este desequilibrio. Muchos modelos funcionan mejor cuando el número de observaciones es igual y, por lo tanto, tienden a tener dificultades con datos desequilibrados.\n",
|
|
"\n",
|
|
"Existen principalmente dos formas de manejar conjuntos de datos desequilibrados:\n",
|
|
"\n",
|
|
"- agregar observaciones a la clase minoritaria: `Over-sampling`, por ejemplo, usando un algoritmo SMOTE\n",
|
|
"\n",
|
|
"- eliminar observaciones de la clase mayoritaria: `Under-sampling`\n",
|
|
"\n",
|
|
"Ahora vamos a demostrar cómo manejar conjuntos de datos desequilibrados usando una `recipe`. Una recipe puede considerarse como un plano que describe qué pasos deben aplicarse a un conjunto de datos para prepararlo para el análisis de datos.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "soAw6826JKx9"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Load themis package for dealing with imbalanced data\r\n",
|
|
"library(themis)\r\n",
|
|
"\r\n",
|
|
"# Create a recipe for preprocessing data\r\n",
|
|
"cuisines_recipe <- recipe(cuisine ~ ., data = df_select) %>% \r\n",
|
|
" step_smote(cuisine)\r\n",
|
|
"\r\n",
|
|
"cuisines_recipe"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "HS41brUIJVJy"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Desglosamos los pasos de preprocesamiento.\n",
|
|
"\n",
|
|
"- La llamada a `recipe()` con una fórmula indica a la receta los *roles* de las variables utilizando los datos de `df_select` como referencia. Por ejemplo, la columna `cuisine` ha sido asignada con un rol de `outcome`, mientras que el resto de las columnas han sido asignadas con un rol de `predictor`.\n",
|
|
"\n",
|
|
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) crea una *especificación* de un paso de receta que genera sintéticamente nuevos ejemplos de la clase minoritaria utilizando los vecinos más cercanos de estos casos.\n",
|
|
"\n",
|
|
"Ahora, si quisiéramos ver los datos preprocesados, tendríamos que [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) y [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) nuestra receta.\n",
|
|
"\n",
|
|
"`prep()`: estima los parámetros necesarios a partir de un conjunto de entrenamiento que luego pueden aplicarse a otros conjuntos de datos.\n",
|
|
"\n",
|
|
"`bake()`: toma una receta preparada y aplica las operaciones a cualquier conjunto de datos.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "Yb-7t7XcJaC8"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Prep and bake the recipe\r\n",
|
|
"preprocessed_df <- cuisines_recipe %>% \r\n",
|
|
" prep() %>% \r\n",
|
|
" bake(new_data = NULL) %>% \r\n",
|
|
" relocate(cuisine)\r\n",
|
|
"\r\n",
|
|
"# Display data\r\n",
|
|
"preprocessed_df %>% \r\n",
|
|
" slice_head(n = 5)\r\n",
|
|
"\r\n",
|
|
"# Quick summary stats\r\n",
|
|
"preprocessed_df %>% \r\n",
|
|
" introduce()"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "9QhSgdpxJl44"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Ahora revisemos la distribución de nuestras cocinas y comparemos con los datos desequilibrados.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "dmidELh_LdV7"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Distribution of cuisines\r\n",
|
|
"new_label_count <- preprocessed_df %>% \r\n",
|
|
" count(cuisine) %>% \r\n",
|
|
" arrange(desc(n))\r\n",
|
|
"\r\n",
|
|
"list(new_label_count = new_label_count,\r\n",
|
|
" old_label_count = old_label_count)"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "aSh23klBLwDz"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"¡Yum! Los datos están limpios, equilibrados y muy deliciosos 😋!\n",
|
|
"\n",
|
|
"> Normalmente, una receta se utiliza como un preprocesador para el modelado, donde define qué pasos deben aplicarse a un conjunto de datos para prepararlo para el modelado. En ese caso, típicamente se usa un `workflow()` (como ya hemos visto en nuestras lecciones anteriores) en lugar de estimar manualmente una receta.\n",
|
|
">\n",
|
|
"> Por lo tanto, normalmente no necesitas **`prep()`** y **`bake()`** recetas cuando usas tidymodels, pero son funciones útiles para tener en tu kit de herramientas y confirmar que las recetas están haciendo lo que esperas, como en nuestro caso.\n",
|
|
">\n",
|
|
"> Cuando usas **`bake()`** en una receta preparada con **`new_data = NULL`**, obtienes de vuelta los datos que proporcionaste al definir la receta, pero habiendo pasado por los pasos de preprocesamiento.\n",
|
|
"\n",
|
|
"Ahora guardemos una copia de estos datos para usar en futuras lecciones:\n"
|
|
],
|
|
"metadata": {
|
|
"id": "HEu80HZ8L7ae"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"source": [
|
|
"# Save preprocessed data\r\n",
|
|
"write_csv(preprocessed_df, \"../../../data/cleaned_cuisines_R.csv\")"
|
|
],
|
|
"outputs": [],
|
|
"metadata": {
|
|
"id": "cBmCbIgrMOI6"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Este nuevo archivo CSV ahora se encuentra en la carpeta raíz de datos.\n",
|
|
"\n",
|
|
"**🚀Desafío**\n",
|
|
"\n",
|
|
"Este plan de estudios contiene varios conjuntos de datos interesantes. Explora las carpetas `data` y verifica si alguna contiene conjuntos de datos que sean apropiados para clasificación binaria o multiclase. ¿Qué preguntas harías sobre este conjunto de datos?\n",
|
|
"\n",
|
|
"## [**Cuestionario posterior a la lección**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/20/)\n",
|
|
"\n",
|
|
"## **Revisión y Autoestudio**\n",
|
|
"\n",
|
|
"- Revisa [el paquete themis](https://github.com/tidymodels/themis). ¿Qué otras técnicas podríamos usar para manejar datos desbalanceados?\n",
|
|
"\n",
|
|
"- Sitio de referencia de modelos Tidy: [Tidy models](https://www.tidymodels.org/start/).\n",
|
|
"\n",
|
|
"- H. Wickham y G. Grolemund, [*R for Data Science: Visualize, Model, Transform, Tidy, and Import Data*](https://r4ds.had.co.nz/).\n",
|
|
"\n",
|
|
"#### GRACIAS A:\n",
|
|
"\n",
|
|
"[`Allison Horst`](https://twitter.com/allison_horst/) por crear las increíbles ilustraciones que hacen que R sea más accesible y atractivo. Encuentra más ilustraciones en su [galería](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
|
|
"\n",
|
|
"[Cassie Breviu](https://www.twitter.com/cassieview) y [Jen Looper](https://www.twitter.com/jenlooper) por crear la versión original en Python de este módulo ♥️\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustración por @allison_horst</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "WQs5621pMGwf"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Descargo de responsabilidad**: \nEste documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.\n"
|
|
]
|
|
}
|
|
]
|
|
} |