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-09-03T20:38:09+00:00",
|
|
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
|
|
"language_code": "pl"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"# Zbuduj model klasyfikacyjny: Pyszne azjatyckie i indyjskie kuchnie\n"
|
|
],
|
|
"metadata": {
|
|
"id": "ItETB4tSFprR"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Wprowadzenie do klasyfikacji: Oczyszczanie, przygotowanie i wizualizacja danych\n",
|
|
"\n",
|
|
"W tych czterech lekcjach zgłębisz podstawowy aspekt klasycznego uczenia maszynowego - *klasyfikację*. Przeprowadzimy Cię przez różne algorytmy klasyfikacji, korzystając z zestawu danych dotyczących wszystkich wspaniałych kuchni Azji i Indii. Mamy nadzieję, że jesteś głodny!\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/pinch.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Świętuj kuchnie panazjatyckie w tych lekcjach! Obraz autorstwa Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"<!---->\n",
|
|
"\n",
|
|
"Klasyfikacja to forma [uczenia nadzorowanego](https://wikipedia.org/wiki/Supervised_learning), która ma wiele wspólnego z technikami regresji. W klasyfikacji trenujesz model, aby przewidywał, do jakiej `kategorii` należy dany element. Jeśli uczenie maszynowe polega na przewidywaniu wartości lub nazw rzeczy na podstawie zestawów danych, to klasyfikacja zazwyczaj dzieli się na dwie grupy: *klasyfikacja binarna* i *klasyfikacja wieloklasowa*.\n",
|
|
"\n",
|
|
"Pamiętaj:\n",
|
|
"\n",
|
|
"- **Regresja liniowa** pomagała przewidywać zależności między zmiennymi i dokonywać dokładnych prognoz, gdzie nowy punkt danych znajdzie się w odniesieniu do tej linii. Na przykład mogłeś przewidzieć wartości liczbowe, takie jak *jaka będzie cena dyni we wrześniu w porównaniu do grudnia*.\n",
|
|
"\n",
|
|
"- **Regresja logistyczna** pomagała odkrywać \"kategorie binarne\": przy tej cenie *czy dynia jest pomarańczowa czy nie-pomarańczowa*?\n",
|
|
"\n",
|
|
"Klasyfikacja wykorzystuje różne algorytmy do określenia innych sposobów przypisywania etykiety lub klasy punktowi danych. Pracujmy z tymi danymi o kuchniach, aby sprawdzić, czy na podstawie grupy składników możemy określić ich pochodzenie kulinarne.\n",
|
|
"\n",
|
|
"### [**Quiz przed lekcją**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/19/)\n",
|
|
"\n",
|
|
"### **Wprowadzenie**\n",
|
|
"\n",
|
|
"Klasyfikacja jest jednym z podstawowych działań badacza uczenia maszynowego i analityka danych. Od podstawowej klasyfikacji wartości binarnej (\"czy ten e-mail to spam czy nie?\"), po złożoną klasyfikację obrazów i segmentację za pomocą wizji komputerowej, zawsze warto umieć sortować dane na klasy i zadawać im pytania.\n",
|
|
"\n",
|
|
"Mówiąc o procesie w bardziej naukowy sposób, metoda klasyfikacji tworzy model predykcyjny, który pozwala mapować zależności między zmiennymi wejściowymi a zmiennymi wyjściowymi.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/binary-multiclass.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Problemy binarne vs. wieloklasowe dla algorytmów klasyfikacji. Infografika autorstwa Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"Zanim rozpoczniemy proces oczyszczania danych, ich wizualizacji i przygotowania do zadań ML, dowiedzmy się trochę o różnych sposobach, w jakie uczenie maszynowe może być wykorzystywane do klasyfikacji danych.\n",
|
|
"\n",
|
|
"Wywodząca się ze [statystyki](https://wikipedia.org/wiki/Statistical_classification) klasyfikacja w klasycznym uczeniu maszynowym wykorzystuje cechy, takie jak `palacz`, `waga` i `wiek`, aby określić *prawdopodobieństwo rozwoju X choroby*. Jako technika uczenia nadzorowanego, podobna do ćwiczeń regresji, które wykonywałeś wcześniej, Twoje dane są oznaczone etykietami, a algorytmy ML wykorzystują te etykiety do klasyfikacji i przewidywania klas (lub 'cech') zestawu danych oraz przypisywania ich do grupy lub wyniku.\n",
|
|
"\n",
|
|
"✅ Poświęć chwilę, aby wyobrazić sobie zestaw danych o kuchniach. Na jakie pytania mógłby odpowiedzieć model wieloklasowy? Na jakie pytania mógłby odpowiedzieć model binarny? Co jeśli chciałbyś określić, czy dana kuchnia prawdopodobnie używa kozieradki? A co jeśli chciałbyś sprawdzić, czy mając torbę pełną anyżu gwiazdkowego, karczochów, kalafiora i chrzanu, mógłbyś stworzyć typowe indyjskie danie?\n",
|
|
"\n",
|
|
"### **Witaj 'klasyfikatorze'**\n",
|
|
"\n",
|
|
"Pytanie, które chcemy zadać w odniesieniu do tego zestawu danych o kuchniach, jest w rzeczywistości pytaniem **wieloklasowym**, ponieważ mamy do czynienia z kilkoma potencjalnymi kuchniami narodowymi. Mając grupę składników, do której z tych wielu klas będą pasować dane?\n",
|
|
"\n",
|
|
"Tidymodels oferuje kilka różnych algorytmów do klasyfikacji danych, w zależności od rodzaju problemu, który chcesz rozwiązać. W kolejnych dwóch lekcjach poznasz kilka z tych algorytmów.\n",
|
|
"\n",
|
|
"#### **Wymagania wstępne**\n",
|
|
"\n",
|
|
"Do tej lekcji będziemy potrzebować następujących pakietów do oczyszczania, przygotowania i wizualizacji danych:\n",
|
|
"\n",
|
|
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) to [zbiór pakietów R](https://www.tidyverse.org/packages) zaprojektowany, aby uczynić analizę danych szybszą, łatwiejszą i bardziej przyjemną!\n",
|
|
"\n",
|
|
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) to [framework](https://www.tidymodels.org/packages/) składający się z pakietów do modelowania i uczenia maszynowego.\n",
|
|
"\n",
|
|
"- `DataExplorer`: [Pakiet DataExplorer](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html) ma na celu uproszczenie i automatyzację procesu eksploracji danych oraz generowania raportów.\n",
|
|
"\n",
|
|
"- `themis`: [Pakiet themis](https://themis.tidymodels.org/) oferuje dodatkowe kroki w przepisach do radzenia sobie z niezrównoważonymi danymi.\n",
|
|
"\n",
|
|
"Możesz je zainstalować za pomocą:\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"DataExplorer\", \"here\"))`\n",
|
|
"\n",
|
|
"Alternatywnie, poniższy skrypt sprawdza, czy masz wymagane pakiety do ukończenia tego modułu i instaluje je, jeśli ich brakuje.\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": [
|
|
"Później załadujemy te niesamowite pakiety i udostępnimy je w naszej bieżącej sesji R. (To tylko ilustracja, `pacman::p_load()` już to dla Ciebie zrobił)\n"
|
|
],
|
|
"metadata": {
|
|
"id": "YkKAxOJvGD4C"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Ćwiczenie - oczyszczanie i równoważenie danych\n",
|
|
"\n",
|
|
"Pierwszym zadaniem, zanim rozpoczniesz ten projekt, jest oczyszczenie i **zrównoważenie** danych, aby uzyskać lepsze wyniki.\n",
|
|
"\n",
|
|
"Poznajmy dane! 🕵️\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": [
|
|
"Interesujące! Wygląda na to, że pierwsza kolumna to rodzaj kolumny `id`. Dowiedzmy się trochę więcej o danych.\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": [
|
|
"Z wyników widzimy, że mamy `2448` wierszy, `385` kolumn i `0` brakujących wartości. Mamy również 1 dyskretną kolumnę, *cuisine*.\n",
|
|
"\n",
|
|
"## Ćwiczenie - poznawanie kuchni\n",
|
|
"\n",
|
|
"Teraz praca zaczyna robić się bardziej interesująca. Odkryjmy rozkład danych według kuchni.\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": [
|
|
"Istnieje skończona liczba kuchni, ale rozkład danych jest nierównomierny. Możesz to poprawić! Zanim to zrobisz, zbadaj trochę więcej.\n",
|
|
"\n",
|
|
"Następnie przypisz każdą kuchnię do jej własnego tibble i sprawdź, ile danych jest dostępnych (wiersze, kolumny) dla każdej kuchni.\n",
|
|
"\n",
|
|
"> [Tibble](https://tibble.tidyverse.org/) to nowoczesna ramka danych.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/dplyr_filter.jpg\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustracja autorstwa @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": [
|
|
"## **Ćwiczenie - Odkrywanie najpopularniejszych składników według kuchni za pomocą dplyr**\n",
|
|
"\n",
|
|
"Teraz możesz zagłębić się w dane i dowiedzieć się, jakie są typowe składniki dla poszczególnych kuchni. Powinieneś oczyścić dane z powtarzających się informacji, które powodują zamieszanie między kuchniami, więc przyjrzyjmy się temu problemowi.\n",
|
|
"\n",
|
|
"Utwórz funkcję `create_ingredient()` w R, która zwraca dataframe ze składnikami. Funkcja ta rozpocznie od usunięcia nieprzydatnej kolumny i posortuje składniki według ich liczby.\n",
|
|
"\n",
|
|
"Podstawowa struktura funkcji w R wygląda następująco:\n",
|
|
"\n",
|
|
"`myFunction <- function(arglist){`\n",
|
|
"\n",
|
|
"**`...`**\n",
|
|
"\n",
|
|
"**`return`**`(value)`\n",
|
|
"\n",
|
|
"`}`\n",
|
|
"\n",
|
|
"Przystępne wprowadzenie do funkcji w R znajdziesz [tutaj](https://skirmer.github.io/presentations/functions_with_r.html#1).\n",
|
|
"\n",
|
|
"Przejdźmy od razu do działania! Skorzystamy z [czasowników dplyr](https://dplyr.tidyverse.org/), które poznaliśmy w poprzednich lekcjach. Dla przypomnienia:\n",
|
|
"\n",
|
|
"- `dplyr::select()`: pomaga wybrać, które **kolumny** zachować lub wykluczyć.\n",
|
|
"\n",
|
|
"- `dplyr::pivot_longer()`: pomaga \"wydłużyć\" dane, zwiększając liczbę wierszy i zmniejszając liczbę kolumn.\n",
|
|
"\n",
|
|
"- `dplyr::group_by()` i `dplyr::summarise()`: pomagają znaleźć statystyki podsumowujące dla różnych grup i umieścić je w przejrzystej tabeli.\n",
|
|
"\n",
|
|
"- `dplyr::filter()`: tworzy podzbiór danych zawierający tylko wiersze spełniające Twoje warunki.\n",
|
|
"\n",
|
|
"- `dplyr::mutate()`: pomaga tworzyć lub modyfikować kolumny.\n",
|
|
"\n",
|
|
"Sprawdź ten [*artystyczny* tutorial learnr](https://allisonhorst.shinyapps.io/dplyr-learnr/#section-welcome) autorstwa Allison Horst, który wprowadza przydatne funkcje do przekształcania danych w dplyr *(część 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": [
|
|
"Teraz możemy użyć funkcji, aby uzyskać listę dziesięciu najpopularniejszych składników według kuchni. Wypróbujmy ją na `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": [
|
|
"W poprzedniej sekcji użyliśmy `geom_col()`, zobaczmy, jak można użyć `geom_bar`, aby tworzyć wykresy słupkowe. Użyj `?geom_bar` do dalszego czytania.\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": [
|
|
"Co z kuchnią chińską?\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": [
|
|
"Na podstawie wizualizacji danych możemy teraz usunąć najczęściej występujące składniki, które powodują zamieszanie między różnymi kuchniami, korzystając z `dplyr::select()`.\n",
|
|
"\n",
|
|
"Wszyscy uwielbiają ryż, czosnek i imbir!\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": [
|
|
"## Przetwarzanie danych za pomocą przepisów 👩🍳👨🍳 - Radzenie sobie z niezrównoważonymi danymi ⚖️\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/recipes.png\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustracja autorstwa @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"Ponieważ ta lekcja dotyczy kuchni, musimy umieścić `przepisy` w odpowiednim kontekście.\n",
|
|
"\n",
|
|
"Tidymodels oferuje kolejny świetny pakiet: `recipes` - pakiet do wstępnego przetwarzania danych.\n"
|
|
],
|
|
"metadata": {
|
|
"id": "kkFd-JxdIaL6"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"Spójrzmy jeszcze raz na rozkład naszych kuchni.\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": [
|
|
"Jak widać, liczba kuchni jest dość nierównomiernie rozłożona. Kuchnie koreańskie są prawie trzy razy liczniejsze niż kuchnie tajskie. Niezrównoważone dane często negatywnie wpływają na wydajność modelu. Pomyśl o klasyfikacji binarnej. Jeśli większość Twoich danych należy do jednej klasy, model uczenia maszynowego będzie częściej przewidywał tę klasę, po prostu dlatego, że ma więcej danych do analizy. Równoważenie danych eliminuje wszelkie nierównomierności i pomaga usunąć tę dysproporcję. Wiele modeli działa najlepiej, gdy liczba obserwacji jest równa, a zatem mają trudności z przetwarzaniem niezrównoważonych danych.\n",
|
|
"\n",
|
|
"Istnieją dwa główne sposoby radzenia sobie z niezrównoważonymi zbiorami danych:\n",
|
|
"\n",
|
|
"- dodawanie obserwacji do klasy mniejszościowej: `Over-sampling`, np. za pomocą algorytmu SMOTE\n",
|
|
"\n",
|
|
"- usuwanie obserwacji z klasy większościowej: `Under-sampling`\n",
|
|
"\n",
|
|
"Teraz pokażemy, jak radzić sobie z niezrównoważonymi zbiorami danych, korzystając z `recipe`. Recipe można traktować jako plan działania, który opisuje, jakie kroki należy zastosować do zbioru danych, aby przygotować go do analizy.\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": [
|
|
"Rozłóżmy kroki przetwarzania wstępnego.\n",
|
|
"\n",
|
|
"- Wywołanie `recipe()` z formułą informuje recepturę o *rolach* zmiennych, używając danych `df_select` jako odniesienia. Na przykład kolumna `cuisine` została przypisana do roli `outcome`, podczas gdy pozostałe kolumny zostały przypisane do roli `predictor`.\n",
|
|
"\n",
|
|
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) tworzy *specyfikację* kroku receptury, który syntetycznie generuje nowe przykłady dla klasy mniejszościowej, wykorzystując najbliższych sąsiadów tych przypadków.\n",
|
|
"\n",
|
|
"Teraz, jeśli chcielibyśmy zobaczyć dane po przetworzeniu wstępnym, musielibyśmy [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) i [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) naszą recepturę.\n",
|
|
"\n",
|
|
"`prep()`: szacuje wymagane parametry na podstawie zestawu treningowego, które później mogą być zastosowane do innych zestawów danych.\n",
|
|
"\n",
|
|
"`bake()`: bierze przygotowaną recepturę i stosuje operacje do dowolnego zestawu danych.\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": [
|
|
"Sprawdźmy teraz dystrybucję naszych kuchni i porównajmy ją z niezrównoważonymi danymi.\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": [
|
|
"Mniam! Dane są czyste, zrównoważone i bardzo smaczne 😋!\n",
|
|
"\n",
|
|
"> Zazwyczaj przepis jest używany jako wstępny procesor do modelowania, gdzie definiuje, jakie kroki należy zastosować do zestawu danych, aby przygotować go do modelowania. W takim przypadku zazwyczaj używa się `workflow()` (jak już widzieliśmy w poprzednich lekcjach) zamiast ręcznego szacowania przepisu.\n",
|
|
">\n",
|
|
"> W związku z tym, zazwyczaj nie musisz używać **`prep()`** i **`bake()`** przepisów, gdy korzystasz z tidymodels, ale są to przydatne funkcje, które warto mieć w swoim zestawie narzędzi, aby upewnić się, że przepisy działają zgodnie z oczekiwaniami, jak w naszym przypadku.\n",
|
|
">\n",
|
|
"> Gdy używasz **`bake()`** na przygotowanym przepisie z **`new_data = NULL`**, otrzymujesz dane, które dostarczyłeś podczas definiowania przepisu, ale po przejściu przez kroki wstępnego przetwarzania.\n",
|
|
"\n",
|
|
"Teraz zapiszmy kopię tych danych do wykorzystania w przyszłych lekcjach:\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": [
|
|
"Ten świeży plik CSV można teraz znaleźć w głównym folderze danych.\n",
|
|
"\n",
|
|
"**🚀Wyzwanie**\n",
|
|
"\n",
|
|
"Ten program nauczania zawiera kilka interesujących zbiorów danych. Przejrzyj foldery `data` i sprawdź, czy któryś z nich zawiera zbiory danych odpowiednie do klasyfikacji binarnej lub wieloklasowej. Jakie pytania zadałbyś w odniesieniu do tego zbioru danych?\n",
|
|
"\n",
|
|
"## [**Quiz po wykładzie**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/20/)\n",
|
|
"\n",
|
|
"## **Przegląd i samodzielna nauka**\n",
|
|
"\n",
|
|
"- Sprawdź [pakiet themis](https://github.com/tidymodels/themis). Jakie inne techniki możemy zastosować, aby poradzić sobie z niezrównoważonymi danymi?\n",
|
|
"\n",
|
|
"- Strona referencyjna modeli tidy [tutaj](https://www.tidymodels.org/start/).\n",
|
|
"\n",
|
|
"- H. Wickham i G. Grolemund, [*R for Data Science: Visualize, Model, Transform, Tidy, and Import Data*](https://r4ds.had.co.nz/).\n",
|
|
"\n",
|
|
"#### PODZIĘKOWANIA DLA:\n",
|
|
"\n",
|
|
"[`Allison Horst`](https://twitter.com/allison_horst/) za stworzenie niesamowitych ilustracji, które sprawiają, że R jest bardziej przyjazny i angażujący. Znajdź więcej ilustracji w jej [galerii](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) i [Jen Looper](https://www.twitter.com/jenlooper) za stworzenie oryginalnej wersji tego modułu w Pythonie ♥️\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
|
|
" width=\"600\"/>\n",
|
|
" <figcaption>Ilustracja autorstwa @allison_horst</figcaption>\n"
|
|
],
|
|
"metadata": {
|
|
"id": "WQs5621pMGwf"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Zastrzeżenie**: \nTen dokument został przetłumaczony za pomocą usługi tłumaczenia AI [Co-op Translator](https://github.com/Azure/co-op-translator). Chociaż dokładamy wszelkich starań, aby tłumaczenie było precyzyjne, prosimy pamiętać, że automatyczne tłumaczenia mogą zawierać błędy lub nieścisłości. Oryginalny dokument w jego rodzimym języku powinien być uznawany za źródło autorytatywne. W przypadku informacji o kluczowym znaczeniu zaleca się skorzystanie z profesjonalnego tłumaczenia przez człowieka. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z użycia tego tłumaczenia.\n"
|
|
]
|
|
}
|
|
]
|
|
} |