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.
ML-For-Beginners/translations/vi/4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb

721 lines
31 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-06T15:02:12+00:00",
"source_file": "4-Classification/1-Introduction/solution/R/lesson_10-R.ipynb",
"language_code": "vi"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "ItETB4tSFprR"
}
},
{
"cell_type": "markdown",
"source": [
"## Giới thiệu về phân loại: Làm sạch, chuẩn bị và trực quan hóa dữ liệu của bạn\n",
"\n",
"Trong bốn bài học này, bạn sẽ khám phá một trọng tâm cơ bản của học máy cổ điển - *phân loại*. Chúng ta sẽ cùng nhau sử dụng các thuật toán phân loại khác nhau với một tập dữ liệu về các món ăn tuyệt vời của châu Á và Ấn Độ. Hy vọng bạn đang đói!\n",
"\n",
"<p >\n",
" <img src=\"../../images/pinch.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Hãy cùng khám phá các món ăn châu Á trong những bài học này! Hình ảnh bởi Jen Looper</figcaption>\n",
"\n",
"\n",
"<!--![Hãy cùng khám phá các món ăn châu Á trong những bài học này! Hình ảnh bởi Jen Looper](../../../../../../4-Classification/1-Introduction/solution/R/images/pinch.png)-->\n",
"\n",
"Phân loại là một dạng [học có giám sát](https://wikipedia.org/wiki/Supervised_learning) có nhiều điểm tương đồng với các kỹ thuật hồi quy. Trong phân loại, bạn huấn luyện một mô hình để dự đoán một `danh mục` mà một mục thuộc về. Nếu học máy là về việc dự đoán giá trị hoặc tên của các đối tượng bằng cách sử dụng tập dữ liệu, thì phân loại thường chia thành hai nhóm: *phân loại nhị phân* và *phân loại đa lớp*.\n",
"\n",
"Hãy nhớ:\n",
"\n",
"- **Hồi quy tuyến tính** giúp bạn dự đoán mối quan hệ giữa các biến và đưa ra dự đoán chính xác về vị trí mà một điểm dữ liệu mới sẽ nằm trong mối quan hệ với đường đó. Ví dụ, bạn có thể dự đoán giá trị số như *giá của một quả bí ngô vào tháng 9 so với tháng 12*.\n",
"\n",
"- **Hồi quy logistic** giúp bạn khám phá \"danh mục nhị phân\": ở mức giá này, *quả bí ngô này có màu cam hay không màu cam*?\n",
"\n",
"Phân loại sử dụng các thuật toán khác nhau để xác định các cách khác nhau nhằm xác định nhãn hoặc lớp của một điểm dữ liệu. Hãy làm việc với dữ liệu về món ăn này để xem liệu, bằng cách quan sát một nhóm nguyên liệu, chúng ta có thể xác định nguồn gốc của món ăn đó hay không.\n",
"\n",
"### [**Câu hỏi trước bài giảng**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/19/)\n",
"\n",
"### **Giới thiệu**\n",
"\n",
"Phân loại là một trong những hoạt động cơ bản của nhà nghiên cứu học máy và nhà khoa học dữ liệu. Từ việc phân loại cơ bản một giá trị nhị phân (\"email này có phải là spam hay không?\"), đến phân loại hình ảnh phức tạp và phân đoạn bằng cách sử dụng thị giác máy tính, việc có thể phân loại dữ liệu thành các lớp và đặt câu hỏi về nó luôn hữu ích.\n",
"\n",
"Nói theo cách khoa học hơn, phương pháp phân loại của bạn tạo ra một mô hình dự đoán cho phép bạn ánh xạ mối quan hệ giữa các biến đầu vào và biến đầu ra.\n",
"\n",
"<p >\n",
" <img src=\"../../images/binary-multiclass.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Vấn đề nhị phân và đa lớp mà các thuật toán phân loại cần xử lý. Đồ họa thông tin bởi Jen Looper</figcaption>\n",
"\n",
"\n",
"\n",
"Trước khi bắt đầu quá trình làm sạch dữ liệu, trực quan hóa nó và chuẩn bị cho các nhiệm vụ học máy, hãy tìm hiểu một chút về các cách khác nhau mà học máy có thể được sử dụng để phân loại dữ liệu.\n",
"\n",
"Xuất phát từ [thống kê](https://wikipedia.org/wiki/Statistical_classification), phân loại sử dụng học máy cổ điển dựa vào các đặc điểm như `người hút thuốc`, `cân nặng`, và `tuổi` để xác định *khả năng phát triển bệnh X*. Là một kỹ thuật học có giám sát tương tự như các bài tập hồi quy bạn đã thực hiện trước đó, dữ liệu của bạn được gắn nhãn và các thuật toán học máy sử dụng các nhãn đó để phân loại và dự đoán các lớp (hoặc 'đặc điểm') của một tập dữ liệu và gán chúng vào một nhóm hoặc kết quả.\n",
"\n",
"✅ Hãy dành một chút thời gian để tưởng tượng một tập dữ liệu về các món ăn. Một mô hình phân loại đa lớp có thể trả lời điều gì? Một mô hình phân loại nhị phân có thể trả lời điều gì? Nếu bạn muốn xác định liệu một món ăn cụ thể có khả năng sử dụng cỏ cà ri hay không thì sao? Nếu bạn muốn xem liệu, với một túi quà gồm hồi, atisô, súp lơ, và cải ngựa, bạn có thể tạo ra một món ăn Ấn Độ điển hình hay không?\n",
"\n",
"### **Xin chào 'bộ phân loại'**\n",
"\n",
"Câu hỏi mà chúng ta muốn đặt ra với tập dữ liệu về món ăn này thực sự là một câu hỏi **đa lớp**, vì chúng ta có nhiều món ăn quốc gia tiềm năng để làm việc. Với một nhóm nguyên liệu, dữ liệu sẽ phù hợp với lớp nào trong số nhiều lớp này?\n",
"\n",
"Tidymodels cung cấp một số thuật toán khác nhau để sử dụng nhằm phân loại dữ liệu, tùy thuộc vào loại vấn đề bạn muốn giải quyết. Trong hai bài học tiếp theo, bạn sẽ tìm hiểu về một số thuật toán này.\n",
"\n",
"#### **Yêu cầu trước**\n",
"\n",
"Để bài học này, chúng ta sẽ cần các gói sau để làm sạch, chuẩn bị và trực quan hóa dữ liệu:\n",
"\n",
"- `tidyverse`: [tidyverse](https://www.tidyverse.org/) là một [bộ sưu tập các gói R](https://www.tidyverse.org/packages) được thiết kế để làm cho khoa học dữ liệu nhanh hơn, dễ dàng hơn và thú vị hơn!\n",
"\n",
"- `tidymodels`: [tidymodels](https://www.tidymodels.org/) là một [khung làm việc](https://www.tidymodels.org/packages/) gồm các gói dành cho mô hình hóa và học máy.\n",
"\n",
"- `DataExplorer`: [Gói DataExplorer](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html) được thiết kế để đơn giản hóa và tự động hóa quá trình EDA và tạo báo cáo.\n",
"\n",
"- `themis`: [Gói themis](https://themis.tidymodels.org/) cung cấp các bước bổ sung trong công thức để xử lý dữ liệu không cân bằng.\n",
"\n",
"Bạn có thể cài đặt chúng bằng lệnh:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"DataExplorer\", \"here\"))`\n",
"\n",
"Ngoài ra, đoạn mã dưới đây sẽ kiểm tra xem bạn đã có các gói cần thiết để hoàn thành module này chưa và cài đặt chúng nếu chúng bị thiếu.\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": [
"Chúng ta sẽ tải các gói tuyệt vời này sau và làm cho chúng khả dụng trong phiên làm việc R hiện tại của chúng ta. (Đây chỉ là để minh họa, `pacman::p_load()` đã làm điều đó cho bạn)\n"
],
"metadata": {
"id": "YkKAxOJvGD4C"
}
},
{
"cell_type": "markdown",
"source": [
"## Bài tập - làm sạch và cân bằng dữ liệu của bạn\n",
"\n",
"Nhiệm vụ đầu tiên trước khi bắt đầu dự án này là làm sạch và **cân bằng** dữ liệu của bạn để đạt được kết quả tốt hơn.\n",
"\n",
"Hãy cùng khám phá dữ liệu nào! 🕵️\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": [
"Thú vị! Nhìn qua thì cột đầu tiên là một loại cột `id`. Hãy tìm hiểu thêm một chút thông tin về dữ liệu.\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": [
"Từ kết quả, chúng ta có thể thấy ngay rằng chúng ta có `2448` hàng và `385` cột và `0` giá trị bị thiếu. Chúng ta cũng có 1 cột rời rạc, *cuisine*.\n",
"\n",
"## Bài tập - tìm hiểu về các loại ẩm thực\n",
"\n",
"Bây giờ công việc bắt đầu trở nên thú vị hơn. Hãy khám phá sự phân bố dữ liệu theo từng loại ẩm thực.\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": [
"Có một số lượng hữu hạn các nền ẩm thực, nhưng phân bố dữ liệu lại không đồng đều. Bạn có thể khắc phục điều đó! Trước khi làm vậy, hãy khám phá thêm một chút.\n",
"\n",
"Tiếp theo, hãy gán mỗi nền ẩm thực vào một tibble riêng và tìm hiểu xem có bao nhiêu dữ liệu (số hàng, số cột) cho từng nền ẩm thực.\n",
"\n",
"> Một [tibble](https://tibble.tidyverse.org/) là một dạng khung dữ liệu hiện đại.\n",
"\n",
"<p >\n",
" <img src=\"../../images/dplyr_filter.jpg\"\n",
" width=\"600\"/>\n",
" <figcaption>Tác phẩm nghệ thuật của @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": [
"## **Bài tập - Khám phá các nguyên liệu hàng đầu theo từng loại ẩm thực bằng dplyr**\n",
"\n",
"Bây giờ bạn có thể đi sâu vào dữ liệu và tìm hiểu những nguyên liệu đặc trưng cho từng loại ẩm thực. Bạn nên loại bỏ dữ liệu lặp lại gây nhầm lẫn giữa các loại ẩm thực, vì vậy hãy cùng tìm hiểu vấn đề này.\n",
"\n",
"Hãy tạo một hàm `create_ingredient()` trong R để trả về một dataframe nguyên liệu. Hàm này sẽ bắt đầu bằng cách loại bỏ một cột không hữu ích và sắp xếp các nguyên liệu theo số lượng của chúng.\n",
"\n",
"Cấu trúc cơ bản của một hàm trong R là:\n",
"\n",
"`myFunction <- function(arglist){`\n",
"\n",
"**`...`**\n",
"\n",
"**`return`**`(value)`\n",
"\n",
"`}`\n",
"\n",
"Một giới thiệu ngắn gọn về hàm trong R có thể được tìm thấy [tại đây](https://skirmer.github.io/presentations/functions_with_r.html#1).\n",
"\n",
"Hãy bắt đầu ngay thôi! Chúng ta sẽ sử dụng các [động từ dplyr](https://dplyr.tidyverse.org/) mà chúng ta đã học trong các bài học trước. Tóm tắt lại:\n",
"\n",
"- `dplyr::select()`: giúp bạn chọn những **cột** cần giữ lại hoặc loại bỏ.\n",
"\n",
"- `dplyr::pivot_longer()`: giúp bạn \"kéo dài\" dữ liệu, tăng số lượng hàng và giảm số lượng cột.\n",
"\n",
"- `dplyr::group_by()` và `dplyr::summarise()`: giúp bạn tìm các thống kê tóm tắt cho các nhóm khác nhau và đưa chúng vào một bảng gọn gàng.\n",
"\n",
"- `dplyr::filter()`: tạo một tập hợp con của dữ liệu chỉ chứa các hàng thỏa mãn điều kiện của bạn.\n",
"\n",
"- `dplyr::mutate()`: giúp bạn tạo hoặc chỉnh sửa các cột.\n",
"\n",
"Hãy xem hướng dẫn [*nghệ thuật*](https://allisonhorst.shinyapps.io/dplyr-learnr/#section-welcome) của Allison Horst, giới thiệu một số hàm xử lý dữ liệu hữu ích trong dplyr *(một phần của 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": [
"Bây giờ chúng ta có thể sử dụng hàm để có cái nhìn tổng quan về mười nguyên liệu phổ biến nhất theo từng loại ẩm thực. Hãy thử nghiệm với `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": [
"Trong phần trước, chúng ta đã sử dụng `geom_col()`, hãy xem cách bạn có thể sử dụng `geom_bar` để tạo biểu đồ cột. Sử dụng `?geom_bar` để đọc thêm.\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": [
"Còn về các món ăn Trung Quốc thì sao?\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": [
"Từ các biểu đồ trực quan, giờ đây chúng ta có thể loại bỏ những nguyên liệu phổ biến nhất gây nhầm lẫn giữa các nền ẩm thực khác nhau, sử dụng `dplyr::select()`.\n",
"\n",
"Ai cũng yêu thích gạo, tỏi và gừng!\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": [
"## Xử lý dữ liệu bằng recipes 👩‍🍳👨‍🍳 - Đối phó với dữ liệu không cân bằng ⚖️\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"600\"/>\n",
" <figcaption>Tác phẩm nghệ thuật của @allison_horst</figcaption>\n",
"\n",
"Vì bài học này liên quan đến ẩm thực, chúng ta cần đặt `recipes` vào ngữ cảnh.\n",
"\n",
"Tidymodels cung cấp thêm một gói tiện ích khác: `recipes` - một gói dùng để tiền xử lý dữ liệu.\n"
],
"metadata": {
"id": "kkFd-JxdIaL6"
}
},
{
"cell_type": "markdown",
"source": [
"Hãy cùng xem lại sự phân bố của các món ăn của chúng ta.\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": [
"Như bạn có thể thấy, số lượng các món ăn không được phân bố đồng đều. Các món ăn Hàn Quốc gần gấp 3 lần các món ăn Thái. Dữ liệu không cân bằng thường có ảnh hưởng tiêu cực đến hiệu suất của mô hình. Hãy nghĩ về một bài toán phân loại nhị phân. Nếu phần lớn dữ liệu của bạn thuộc về một lớp, mô hình học máy sẽ dự đoán lớp đó thường xuyên hơn, chỉ vì có nhiều dữ liệu hơn cho lớp đó. Việc cân bằng dữ liệu sẽ điều chỉnh bất kỳ sự lệch lạc nào và giúp loại bỏ sự mất cân bằng này. Nhiều mô hình hoạt động tốt nhất khi số lượng quan sát là bằng nhau và do đó thường gặp khó khăn với dữ liệu không cân bằng.\n",
"\n",
"Có hai cách chính để xử lý các tập dữ liệu không cân bằng:\n",
"\n",
"- thêm các quan sát vào lớp thiểu số: `Over-sampling`, ví dụ sử dụng thuật toán SMOTE\n",
"\n",
"- loại bỏ các quan sát từ lớp đa số: `Under-sampling`\n",
"\n",
"Bây giờ chúng ta sẽ minh họa cách xử lý các tập dữ liệu không cân bằng bằng cách sử dụng một `recipe`. Recipe có thể được xem như một bản thiết kế mô tả các bước cần thực hiện trên một tập dữ liệu để chuẩn bị cho việc phân tích dữ liệu.\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": [
"Hãy cùng phân tích các bước tiền xử lý.\n",
"\n",
"- Lệnh gọi `recipe()` với một công thức cho phép recipe xác định *vai trò* của các biến bằng cách sử dụng dữ liệu `df_select` làm tham chiếu. Ví dụ, cột `cuisine` được gán vai trò `outcome`, trong khi các cột còn lại được gán vai trò `predictor`.\n",
"\n",
"- [`step_smote(cuisine)`](https://themis.tidymodels.org/reference/step_smote.html) tạo ra một *đặc tả* cho một bước trong recipe, bước này sẽ tạo ra các ví dụ mới cho lớp thiểu số một cách tổng hợp bằng cách sử dụng các điểm lân cận gần nhất của các trường hợp này.\n",
"\n",
"Bây giờ, nếu chúng ta muốn xem dữ liệu đã được tiền xử lý, chúng ta cần [**`prep()`**](https://recipes.tidymodels.org/reference/prep.html) và [**`bake()`**](https://recipes.tidymodels.org/reference/bake.html) recipe của mình.\n",
"\n",
"`prep()`: ước tính các tham số cần thiết từ tập huấn luyện để sau đó có thể áp dụng cho các tập dữ liệu khác.\n",
"\n",
"`bake()`: sử dụng một recipe đã được chuẩn bị và áp dụng các thao tác lên bất kỳ tập dữ liệu nào.\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": [
"Bây giờ hãy kiểm tra phân bố của các món ăn và so sánh chúng với dữ liệu mất cân bằng.\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! Dữ liệu thật sạch sẽ, cân bằng và rất ngon miệng 😋!\n",
"\n",
"> Thông thường, một công thức thường được sử dụng như một bộ tiền xử lý cho việc mô hình hóa, nơi nó xác định các bước cần áp dụng cho một tập dữ liệu để chuẩn bị cho việc mô hình hóa. Trong trường hợp đó, một `workflow()` thường được sử dụng (như chúng ta đã thấy trong các bài học trước) thay vì tự tay ước tính một công thức.\n",
">\n",
"> Vì vậy, bạn thường không cần phải **`prep()`** và **`bake()`** công thức khi sử dụng tidymodels, nhưng chúng là những hàm hữu ích để kiểm tra rằng công thức đang hoạt động đúng như mong đợi, giống như trong trường hợp của chúng ta.\n",
">\n",
"> Khi bạn **`bake()`** một công thức đã được chuẩn bị với **`new_data = NULL`**, bạn sẽ nhận lại dữ liệu mà bạn đã cung cấp khi định nghĩa công thức, nhưng đã trải qua các bước tiền xử lý.\n",
"\n",
"Bây giờ hãy lưu một bản sao của dữ liệu này để sử dụng trong các bài học sau:\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": [
"Tệp CSV mới này hiện có thể được tìm thấy trong thư mục dữ liệu gốc.\n",
"\n",
"**🚀Thử thách**\n",
"\n",
"Chương trình học này chứa một số bộ dữ liệu thú vị. Hãy khám phá các thư mục `data` và xem liệu có bộ dữ liệu nào phù hợp cho phân loại nhị phân hoặc đa lớp không? Bạn sẽ đặt câu hỏi gì với bộ dữ liệu này?\n",
"\n",
"## [**Câu hỏi sau bài giảng**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/20/)\n",
"\n",
"## **Ôn tập & Tự học**\n",
"\n",
"- Xem qua [gói themis](https://github.com/tidymodels/themis). Có những kỹ thuật nào khác mà chúng ta có thể sử dụng để xử lý dữ liệu mất cân bằng?\n",
"\n",
"- Trang web tham khảo [Tidy models](https://www.tidymodels.org/start/).\n",
"\n",
"- H. Wickham và G. Grolemund, [*R for Data Science: Visualize, Model, Transform, Tidy, and Import Data*](https://r4ds.had.co.nz/).\n",
"\n",
"#### CẢM ƠN ĐẾN:\n",
"\n",
"[`Allison Horst`](https://twitter.com/allison_horst/) vì đã tạo ra những hình minh họa tuyệt vời giúp R trở nên thân thiện và hấp dẫn hơn. Tìm thêm hình minh họa tại [bộ sưu tập của cô ấy](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) và [Jen Looper](https://www.twitter.com/jenlooper) vì đã tạo ra phiên bản Python gốc của module này ♥️\n",
"\n",
"<p >\n",
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
" width=\"600\"/>\n",
" <figcaption>Tác phẩm nghệ thuật của @allison_horst</figcaption>\n"
],
"metadata": {
"id": "WQs5621pMGwf"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Tuyên bố miễn trừ trách nhiệm**: \nTài liệu này đã được dịch bằng dịch vụ dịch thuật AI [Co-op Translator](https://github.com/Azure/co-op-translator). Mặc dù chúng tôi cố gắng đảm bảo độ chính xác, xin lưu ý rằng các bản dịch tự động có thể chứa lỗi hoặc sự không chính xác. Tài liệu gốc bằng ngôn ngữ bản địa nên được coi là nguồn tham khảo chính thức. Đối với các thông tin quan trọng, chúng tôi khuyến nghị sử dụng dịch vụ dịch thuật chuyên nghiệp từ con người. Chúng tôi không chịu trách nhiệm cho bất kỳ sự hiểu lầm hoặc diễn giải sai nào phát sinh từ việc sử dụng bản dịch này.\n"
]
}
]
}