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.
723 lines
28 KiB
723 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-08-29T23:59:26+00:00",
|
|
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
|
|
"language_code": "br"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"# Construir um modelo de classificação: Deliciosas culinárias asiáticas e indianas\n"
|
|
],
|
|
"metadata": {
|
|
"id": "ItETB4tSFprR"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Introdução à classificação: Limpe, prepare e visualize seus dados\n",
|
|
"\n",
|
|
"Nestes quatro módulos, você explorará um dos focos fundamentais do aprendizado de máquina clássico - *classificação*. Vamos explorar o uso de vários algoritmos de classificação com um conjunto de dados sobre as brilhantes culinárias da Ásia e da Índia. Espero que você esteja com fome!\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/pinch.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Comemore as culinárias pan-asiáticas nestas lições! Imagem de Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!---->\n",
|
|
"\n",
|
|
"Classificação é uma forma de [aprendizado supervisionado](https://wikipedia.org/wiki/Supervised_learning) que tem muito em comum com técnicas de regressão. Na classificação, você treina um modelo para prever a qual `categoria` um item pertence. Se o aprendizado de máquina é sobre prever valores ou nomes para coisas usando conjuntos de dados, então a classificação geralmente se divide em dois grupos: *classificação binária* e *classificação multiclasses*.\n",
|
|
"\n",
|
|
"Lembre-se:\n",
|
|
"\n",
|
|
"- **Regressão linear** ajudou você a prever relações entre variáveis e fazer previsões precisas sobre onde um novo ponto de dados se encaixaria em relação a essa linha. Por exemplo, você poderia prever valores numéricos como *qual seria o preço de uma abóbora em setembro vs. dezembro*.\n",
|
|
"\n",
|
|
"- **Regressão logística** ajudou você a descobrir \"categorias binárias\": neste ponto de preço, *essa abóbora é laranja ou não-laranja*?\n",
|
|
"\n",
|
|
"A classificação utiliza vários algoritmos para determinar outras formas de identificar o rótulo ou a classe de um ponto de dados. Vamos trabalhar com esses dados de culinária para ver se, ao observar um grupo de ingredientes, conseguimos determinar sua origem culinária.\n",
|
|
"\n",
|
|
"### [**Questionário pré-aula**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/19/)\n",
|
|
"\n",
|
|
"### **Introdução**\n",
|
|
"\n",
|
|
"A classificação é uma das atividades fundamentais do pesquisador de aprendizado de máquina e do cientista de dados. Desde a classificação básica de um valor binário (\"este e-mail é spam ou não?\") até a classificação e segmentação complexa de imagens usando visão computacional, é sempre útil ser capaz de organizar dados em classes e fazer perguntas sobre eles.\n",
|
|
"\n",
|
|
"Para descrever o processo de forma mais científica, seu método de classificação cria um modelo preditivo que permite mapear a relação entre variáveis de entrada e variáveis de saída.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/binary-multiclass.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Problemas binários vs. multiclasses para algoritmos de classificação. Infográfico por Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"Antes de começar o processo de limpeza dos dados, visualizá-los e prepará-los para nossas tarefas de aprendizado de máquina, vamos aprender um pouco sobre as várias maneiras pelas quais o aprendizado de máquina pode ser usado para classificar dados.\n",
|
|
"\n",
|
|
"Derivada da [estatística](https://wikipedia.org/wiki/Statistical_classification), a classificação usando aprendizado de máquina clássico utiliza características, como `fumante`, `peso` e `idade`, para determinar a *probabilidade de desenvolver X doença*. Como uma técnica de aprendizado supervisionado semelhante aos exercícios de regressão que você realizou anteriormente, seus dados são rotulados e os algoritmos de aprendizado de máquina usam esses rótulos para classificar e prever classes (ou 'características') de um conjunto de dados e atribuí-las a um grupo ou resultado.\n",
|
|
"\n",
|
|
"✅ Tire um momento para imaginar um conjunto de dados sobre culinárias. O que um modelo multiclasses seria capaz de responder? O que um modelo binário seria capaz de responder? E se você quisesse determinar se uma determinada culinária provavelmente usa feno-grego? E se você quisesse ver se, dado um presente de uma sacola de compras cheia de anis-estrelado, alcachofras, couve-flor e raiz-forte, você poderia criar um prato típico indiano?\n",
|
|
"\n",
|
|
"### **Olá 'classificador'**\n",
|
|
"\n",
|
|
"A pergunta que queremos fazer sobre este conjunto de dados de culinária é, na verdade, uma questão **multiclasses**, já que temos várias possíveis culinárias nacionais para trabalhar. Dado um lote de ingredientes, a qual dessas muitas classes os dados se encaixam?\n",
|
|
"\n",
|
|
"O Tidymodels oferece vários algoritmos diferentes para classificar dados, dependendo do tipo de problema que você deseja resolver. Nas próximas duas lições, você aprenderá sobre alguns desses algoritmos.\n",
|
|
"\n",
|
|
"#### **Pré-requisito**\n",
|
|
"\n",
|
|
"Para esta lição, precisaremos dos seguintes pacotes para limpar, preparar e visualizar nossos dados:\n",
|
|
"\n",
|
|
"- `tidyverse`: O [tidyverse](https://www.tidyverse.org/) é uma [coleção de pacotes R](https://www.tidyverse.org/packages) projetada para tornar a ciência de dados mais rápida, fácil e divertida!\n",
|
|
"\n",
|
|
"- `tidymodels`: O [tidymodels](https://www.tidymodels.org/) é uma [coleção de pacotes](https://www.tidymodels.org/packages/) para modelagem e aprendizado de máquina.\n",
|
|
"\n",
|
|
"- `DataExplorer`: O [pacote DataExplorer](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html) foi criado para simplificar e automatizar o processo de análise exploratória de dados (EDA) e a geração de relatórios.\n",
|
|
"\n",
|
|
"- `themis`: O [pacote themis](https://themis.tidymodels.org/) fornece etapas extras de receitas para lidar com dados desbalanceados.\n",
|
|
"\n",
|
|
"Você pode instalá-los com:\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"DataExplorer\", \"here\"))`\n",
|
|
"\n",
|
|
"Alternativamente, o script abaixo verifica se você possui os pacotes necessários para completar este módulo e os instala para você caso estejam ausentes.\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": [
|
|
"Vamos carregar esses pacotes incríveis mais tarde e torná-los disponíveis na nossa sessão atual do R. (Isso é apenas para ilustração, `pacman::p_load()` já fez isso por você)\n"
|
|
],
|
|
"metadata": {
|
|
"id": "YkKAxOJvGD4C"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Exercício - limpar e balancear seus dados\n",
|
|
"\n",
|
|
"A primeira tarefa, antes de começar este projeto, é limpar e **balancear** seus dados para obter melhores resultados.\n",
|
|
"\n",
|
|
"Vamos conhecer os dados! 🕵️\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": [
|
|
"Interessante! Pelo que parece, a primeira coluna é um tipo de coluna `id`. Vamos obter um pouco mais de informações sobre os dados.\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 do resultado, podemos ver imediatamente que temos `2448` linhas, `385` colunas e `0` valores ausentes. Também temos 1 coluna discreta, *cuisine*.\n",
|
|
"\n",
|
|
"## Exercício - aprendendo sobre culinárias\n",
|
|
"\n",
|
|
"Agora o trabalho começa a ficar mais interessante. Vamos descobrir a distribuição dos dados por tipo de culinária.\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": [
|
|
"Existem um número finito de culinárias, mas a distribuição dos dados é desigual. Você pode corrigir isso! Antes de fazer isso, explore um pouco mais.\n",
|
|
"\n",
|
|
"Em seguida, vamos atribuir cada culinária ao seu próprio tibble e descobrir quantos dados estão disponíveis (linhas, colunas) por culinária.\n",
|
|
"\n",
|
|
"> Um [tibble](https://tibble.tidyverse.org/) é uma versão moderna de um data frame.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/dplyr_filter.jpg\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustração 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": [
|
|
"## **Exercício - Descobrindo os principais ingredientes por culinária usando dplyr**\n",
|
|
"\n",
|
|
"Agora você pode explorar mais profundamente os dados e descobrir quais são os ingredientes típicos de cada culinária. É importante limpar dados recorrentes que criam confusão entre as culinárias, então vamos aprender sobre esse problema.\n",
|
|
"\n",
|
|
"Crie uma função `create_ingredient()` em R que retorne um dataframe de ingredientes. Essa função começará eliminando uma coluna pouco útil e organizará os ingredientes por sua contagem.\n",
|
|
"\n",
|
|
"A estrutura básica de uma função em R é:\n",
|
|
"\n",
|
|
"`myFunction <- function(arglist){`\n",
|
|
"\n",
|
|
"**`...`**\n",
|
|
"\n",
|
|
"**`return`**`(value)`\n",
|
|
"\n",
|
|
"`}`\n",
|
|
"\n",
|
|
"Uma introdução prática às funções em R pode ser encontrada [aqui](https://skirmer.github.io/presentations/functions_with_r.html#1).\n",
|
|
"\n",
|
|
"Vamos direto ao ponto! Faremos uso dos [verbos do dplyr](https://dplyr.tidyverse.org/) que aprendemos em nossas lições anteriores. Para relembrar:\n",
|
|
"\n",
|
|
"- `dplyr::select()`: ajuda você a escolher quais **colunas** manter ou excluir.\n",
|
|
"\n",
|
|
"- `dplyr::pivot_longer()`: ajuda a \"alongar\" os dados, aumentando o número de linhas e diminuindo o número de colunas.\n",
|
|
"\n",
|
|
"- `dplyr::group_by()` e `dplyr::summarise()`: ajudam você a encontrar estatísticas resumidas para diferentes grupos e colocá-las em uma tabela organizada.\n",
|
|
"\n",
|
|
"- `dplyr::filter()`: cria um subconjunto dos dados contendo apenas as linhas que satisfazem suas condições.\n",
|
|
"\n",
|
|
"- `dplyr::mutate()`: ajuda você a criar ou modificar colunas.\n",
|
|
"\n",
|
|
"Confira este [tutorial *artístico* do learnr](https://allisonhorst.shinyapps.io/dplyr-learnr/#section-welcome) de Allison Horst, que apresenta algumas funções úteis de manipulação de dados no dplyr *(parte do 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": [
|
|
"Agora podemos usar a função para ter uma ideia dos dez ingredientes mais populares por culinária. Vamos testá-la com `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": [
|
|
"Na seção anterior, usamos `geom_col()`, vamos ver como você pode usar `geom_bar` também, para criar gráficos de barras. Use `?geom_bar` para leitura adicional.\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": [
|
|
"E quanto às culinárias chinesas?\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": [],
|
|
"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 das visualizações de dados, agora podemos remover os ingredientes mais comuns que geram confusão entre diferentes culinárias, usando `dplyr::select()`.\n",
|
|
"\n",
|
|
"Todo mundo adora arroz, alho e gengibre!\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": [
|
|
"## Pré-processamento de dados usando recipes 👩🍳👨🍳 - Lidando com dados desbalanceados ⚖️\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/recipes.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Arte por @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"Dado que esta lição é sobre culinárias, precisamos colocar `recipes` em contexto.\n",
|
|
"\n",
|
|
"Tidymodels oferece mais um pacote interessante: `recipes` - um pacote para pré-processamento de dados.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "kkFd-JxdIaL6"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Vamos dar uma olhada novamente na distribuição das nossas culinárias.\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 você pode ver, há uma distribuição bastante desigual no número de culinárias. Culinárias coreanas são quase 3 vezes mais numerosas que as culinárias tailandesas. Dados desequilibrados frequentemente têm efeitos negativos no desempenho do modelo. Pense em uma classificação binária. Se a maior parte dos seus dados pertence a uma classe, um modelo de aprendizado de máquina vai prever essa classe com mais frequência, simplesmente porque há mais dados para ela. Balancear os dados corrige qualquer desequilíbrio e ajuda a remover essa disparidade. Muitos modelos apresentam melhor desempenho quando o número de observações é igual e, por isso, tendem a ter dificuldades com dados desequilibrados.\n",
|
|
"\n",
|
|
"Existem basicamente duas maneiras de lidar com conjuntos de dados desequilibrados:\n",
|
|
"\n",
|
|
"- adicionar observações à classe minoritária: `Over-sampling`, por exemplo, usando um algoritmo SMOTE\n",
|
|
"\n",
|
|
"- remover observações da classe majoritária: `Under-sampling`\n",
|
|
"\n",
|
|
"Agora vamos demonstrar como lidar com conjuntos de dados desequilibrados usando uma `receita`. Uma receita pode ser vista como um plano que descreve quais etapas devem ser aplicadas a um conjunto de dados para prepará-lo para análise.\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": [
|
|
"Vamos detalhar nossas etapas de pré-processamento.\n",
|
|
"\n",
|
|
"- A chamada para `recipe()` com uma fórmula informa à receita os *papéis* das variáveis usando os dados de `df_select` como referência. Por exemplo, a coluna `cuisine` foi atribuída ao papel de `outcome`, enquanto o restante das colunas foi atribuído ao papel de `predictor`.\n",
|
|
"\n",
|
|
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) cria uma *especificação* de uma etapa da receita que gera sinteticamente novos exemplos da classe minoritária usando os vizinhos mais próximos desses casos.\n",
|
|
"\n",
|
|
"Agora, se quisermos ver os dados pré-processados, precisamos [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) e [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) nossa receita.\n",
|
|
"\n",
|
|
"`prep()`: estima os parâmetros necessários a partir de um conjunto de treinamento que podem ser aplicados posteriormente a outros conjuntos de dados.\n",
|
|
"\n",
|
|
"`bake()`: aplica uma receita preparada às operações em qualquer conjunto de dados.\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": [
|
|
"Vamos agora verificar a distribuição de nossas culinárias e compará-las com os dados 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! Os dados estão limpos, balanceados e muito deliciosos 😋!\n",
|
|
"\n",
|
|
"> Normalmente, uma receita é usada como um pré-processador para modelagem, onde define quais etapas devem ser aplicadas a um conjunto de dados para prepará-lo para a modelagem. Nesse caso, um `workflow()` é tipicamente usado (como já vimos em nossas aulas anteriores) em vez de estimar manualmente uma receita.\n",
|
|
">\n",
|
|
"> Assim, você geralmente não precisa usar **`prep()`** e **`bake()`** em receitas quando utiliza o tidymodels, mas essas são funções úteis para ter em sua caixa de ferramentas para confirmar que as receitas estão fazendo o que você espera, como no nosso caso.\n",
|
|
">\n",
|
|
"> Quando você usa **`bake()`** em uma receita preparada com **`new_data = NULL`**, você obtém de volta os dados que forneceu ao definir a receita, mas já processados pelas etapas de pré-processamento.\n",
|
|
"\n",
|
|
"Agora vamos salvar uma cópia desses dados para uso em aulas futuras:\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 novo CSV agora pode ser encontrado na pasta raiz de dados.\n",
|
|
"\n",
|
|
"**🚀Desafio**\n",
|
|
"\n",
|
|
"Este currículo contém vários conjuntos de dados interessantes. Explore as pastas `data` e veja se alguma contém conjuntos de dados que seriam apropriados para classificação binária ou multi-classes. Que perguntas você faria sobre este conjunto de dados?\n",
|
|
"\n",
|
|
"## [**Quiz pós-aula**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/20/)\n",
|
|
"\n",
|
|
"## **Revisão e Autoestudo**\n",
|
|
"\n",
|
|
"- Confira o [pacote themis](https://github.com/tidymodels/themis). Quais outras técnicas poderíamos usar para lidar com dados desbalanceados?\n",
|
|
"\n",
|
|
"- Site de referência dos modelos Tidy: [Tidy models](https://www.tidymodels.org/start/).\n",
|
|
"\n",
|
|
"- H. Wickham e G. Grolemund, [*R for Data Science: Visualize, Model, Transform, Tidy, and Import Data*](https://r4ds.had.co.nz/).\n",
|
|
"\n",
|
|
"#### AGRADECIMENTOS A:\n",
|
|
"\n",
|
|
"[`Allison Horst`](https://twitter.com/allison_horst/) por criar as ilustrações incríveis que tornam o R mais acolhedor e envolvente. Encontre mais ilustrações na sua [galeria](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) e [Jen Looper](https://www.twitter.com/jenlooper) por criarem a versão original em Python deste módulo ♥️\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Arte por @allison_horst</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "WQs5621pMGwf"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Aviso Legal**: \nEste documento foi traduzido utilizando o serviço de tradução por IA [Co-op Translator](https://github.com/Azure/co-op-translator). Embora nos esforcemos para garantir a precisão, esteja ciente de que traduções automatizadas podem conter erros ou imprecisões. O documento original em seu idioma nativo deve ser considerado a fonte autoritativa. Para informações críticas, recomenda-se a tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações equivocadas decorrentes do uso desta tradução.\n"
|
|
]
|
|
}
|
|
]
|
|
} |