{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## សង់ម៉ូឌែល logistic regression - មេរៀនទី 4\n", "\n", "![Logistic vs. linear regression infographic](../../../../../../translated_images/km/linear-vs-logistic.ba180bf95e7ee667.webp)\n", "\n", "#### **[សំណួរពិភាក្សា មុនមេរៀន](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### បម្រែបម្រួល\n", "\n", "នៅក្នុងមេរៀនចុងក្រោយនេះ ពាក់ព័ន្ធនឹង Regression វិធីសាស្រ្ត ML មូលដ្ឋាន *ជា classic* មួយ យើងនឹងពិចារណាត្រឹម Logistic Regression។ អ្នកនឹងប្រើវិធីនេះ ដើម្បីរកឃើញលំនាំក្នុងការព្យាករណ៍ប្រភេទពីរជារូបធាតុ។ តើភីតកន្ត្រៃនេះជាឆកូឡាទរឬទេ? តើជំងឺនេះអាចឆ្លងទៅបានរឺទេ? តើអតិថិជននេះនឹងជ្រើសរើសផលិតផលនេះ រឺទេ?\n", "\n", "ក្នុងមេរៀននេះ អ្នកនឹងរៀនពី៖\n", "\n", "- វិធីសាស្រ្តសម្រាប់ logistic regression\n", "\n", "✅ ពង្រឹងការយល់ដឹងអំពីការដំណើរការជាមួយ regression ប្រភេទនេះក្នុង [មូឌុលសិក្សានេះ](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n", "\n", "## ប្រភេទខ្លឹមសារ\n", "\n", "បន្ទាប់ពីបានធ្វើការងារជាមួយទិន្នន័យដំបង pumpkin ហើយ ឥឡូវនេះយើងសម្រេចចិត្តបានថា មានប្រភេទពីរមួយដែលយើងអាចប្រើបានគឺ៖ `Color`។\n", "\n", "តោះបង្កើតម៉ូឌែល logistic regression ដើម្បីព្យាករណ៍ថា នៅពេលមានអថេរមួយចំនួន *ប pumpkin មួយនឹងមានពណ៌អ្វី* (ទឹកដោះគោ orange 🎃 រឺសဖြူ 👻)។\n", "\n", "> ហេតុអ្វីយើងពិភាក្សាអំពីចំណាត់ថ្នាក់ពីរនៅក្នុងមេរៀនដែលជាការប្រមូលផ្តុំ regression? ដោយសារតែភាពងាយស្រួលផ្នែកភាសា ប្រភេទ logistic regression គឺ [ជាវិធីសាស្រ្តចំណាត់ថ្នាក់](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression) មួយ ដែលអាស្រ័យលើរៀបរាប់តាមខ្សែ។ រៀនពីវិធីផ្សេងទៀតក្នុងការចាត់ថ្នាក់ទិន្នន័យនៅក្នុងក្រុមមេរៀនបន្ទាប់។\n", "\n", "សម្រាប់មេរៀននេះ យើងត្រូវការពាក្យបណ្ណៈដូចខាងក្រោម៖\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/) គឺ [បណ្ណាល័យ R មួយ](https://www.tidyverse.org/packages) ដែលបានរចនាឡើងដើម្បីអោយផ្នែកវិទ្យាសាស្រ្តទិន្នន័យមានល្បឿនលឿនឡើង សាមញ្ញ និងមានភាពរីករាយ!\n", "\n", "- `tidymodels`: ជា [ស៊ុមបណ្ណាល័យ](https://www.tidymodels.org/packages/) សម្រាប់ម៉ូឌែល និងការសិក្សាម៉ាស៊ីន។\n", "\n", "- `janitor`: [janitor package](https://github.com/sfirke/janitor) ផ្តល់ឧបករណ៍តូចៗសម្រាប់ពិនិត្យ និងសំអាតទិន្នន័យដែលខូច។\n", "\n", "- `ggbeeswarm`: [ggbeeswarm package](https://github.com/eclarke/ggbeeswarm) ផ្តល់វិធីសាស្រ្តបង្កើតកំណត់ត្រាបែប beeswarm ដោយប្រើ ggplot2។\n", "\n", "អ្នកអាចដំឡើងវាទាំងនេះដោយ៖\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "ជម្រើសមួយទៀត ស្គ្រីបខាងក្រោមនេះពិនិត្យថា តើអ្នកមានបណ្ណាល័យដែលចាំបាច់ដើម្បីបញ្ចប់មូឌុលនេះហើយទេ ហើយវានឹងដំឡើងបណ្ណាល័យក្នុងករណីវាពិបាកឃើញ។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n", "\n", "pacman::p_load(tidyverse, tidymodels, janitor, ggbeeswarm)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **កំណត់សំណួរ**\n", "\n", "សម្រាប់គោលបំណងរបស់យើង យើងនឹងបញ្ចេញវាឲ្យជាជម្រើសពីរមាន: 'ពណ៌ស' ឬ 'មិនពណ៌ស'។ ក៏មានប្រភេទ 'ដែលមានរបារ' នៅក្នុងទិន្នន័យរបស់យើង ប៉ុន្តែមានករណីតិចប៉ុណ្ណោះ ដូច្នេះយើងមិនប្រើវាទេ។ វារលាយបាត់បង់បើយើងលុបតម្លៃទទេចេញពីទិន្នន័យ។\n", "\n", "> 🎃 ព័ត៌មានរីករាយ ម្តងពីម្តង យើងហៅពិដានពណ៌សថា 'ពិដានព្រាហ្ម', ព្រាហ្មមិនងាយស្រូបរមាំង ដូច្នេះវាមិនពេញនិយមដូចពិដានពណ៌ទឹកក្រូចទេ ប៉ុន្តែវាមើលទៅត្រជាក់! ដូច្នេះយើងអាចកែសម្រួលសំណួររបស់យើងថា៖ 'ព្រាហ្ម' ឬ 'មិនព្រាហ្ម' ក៏បាន។ 👻\n", "\n", "## **អំពីការវិលត្រឡប់លូជីស្ទិច**\n", "\n", "ការវិលត្រឡប់លូជីស្ទិចខុសពីការវិលត្រឡប់បន្ទាត់ ដែលអ្នកបានរៀនពីមុន លើកលែងមានប្រែប្រួលសំខាន់ខ្លះ។\n", "\n", "#### **ចាត់ថ្នាក់ពីរជម្រើស**\n", "\n", "ការវិលត្រឡប់លូជីស្ទិចមិនមានលក្ខណៈដូចការវិលត្រឡប់បន្ទាត់ទេ។ វាជាការព្យាករណ៍អំពី `ចំណាត់ការទ្វេចមحدد` (\"ពណ៌ទឹកក្រូចឬមិនមែនពណ៌ទឹកក្រូច\") ខណៈដែលអាចព្យាករណ៍បានជាមួយ `តម្លៃបន្តបន្ទាប់` នៅក្នុងការវិលត្រឡប់បន្ទាត់ ដូចជាករណីផ្អែកលើប្រភពដើមនៃពិដាន និងពេលវេលាកាប់ដាំ *តម្លៃរបស់វានឹងកើនឡើងប៉េកលើកមុន*។\n", "\n", "![Infographic by Dasani Madipalli](../../../../../../translated_images/km/pumpkin-classifier.562771f104ad5436.webp)\n", "\n", "### ចំណាត់ថ្នាក់ផ្សេងៗ\n", "\n", "មានប្រភេទការវិលត្រឡប់លូជីស្ទិចផ្សេងទៀត រួមមានលក្ខណៈពហុបុព្វ និងអ័រដីនាល:\n", "\n", "- **ពហុបុព្វ** ដែលមានចំណាត់ថ្នាក់ច្រើនជាងមួយ - \"ពណ៌ទឹកក្រូច ពណ៌ស និងដែលមានរបារ\"។\n", "\n", "- **អ័រដីនាល** ដែលមានចំណាត់ថ្នាក់តាមលំដាប់ ដែលមានប្រយោជន៍បើចង់តម្រៀបលទ្ធផលយ៉ាង​មាន​ទ្រឹស្តី ដូចជាពិដានរបស់យើងដែលតម្រៀបតាមទំហំដាច់ដោយឡែក (តូចខ្នាតតូចមធ្យមធំធំដល់ធំបំផុត)។\n", "\n", "![Multinomial vs ordinal regression](../../../../../../translated_images/km/multinomial-vs-ordinal.36701b4850e37d86.webp)\n", "\n", "#### **អថេរមិនចាំបាច់ត្រូវត្រូវគ្នា**\n", "\n", "ចងចាំថាការវិលត្រឡប់បន្ទាត់ដំណើរការល្អជាមួយអថេរដែលមានទំនាក់ទំនងល្អបន្ថែមទៀត? ការវិលត្រឡប់លូជីស្ទិចវិញគឺផ្ទុយគ្នា - អថេរកុំពុំចាំបាច់ត្រូវគ្នាទេ។ នេះសមនឹងទិន្នន័យនេះដែលមានទំនាក់ទំនងខ្សោយបន្តិច។\n", "\n", "#### **អ្នកត្រូវការទិន្នន័យស្អាតច្រើន**\n", "\n", "ការវិលត្រឡប់លូជីស្ទិចនឹងផ្តល់លទ្ធផលមានភាពត្រឹមត្រូវប្រសើរជាងនេះបើអ្នកប្រើទិន្នន័យច្រើន។ ទិន្នន័យតូចរបស់យើងមិនល្អសម្រាប់បំណងនេះទេ ដូច្នេះសូមចងចាំរឿងនេះ។\n", "\n", "✅ សូមគិតថាទិន្នន័យប្រភេទណាដែលសមស្របសម្រាប់ការវិលត្រឡប់លូជីស្ទិច\n", "\n", "## កម្រិតហាត់ - រៀបចំទិន្នន័យ\n", "\n", "ចាប់ផ្តើម ជម្រះទិន្នន័យអោយបានស្អាតបន្តិច ដោយលុបតម្លៃទទេ និងជ្រើសរើសកូឡុំនៅខ្លះប៉ុណ្ណា៖\n", "\n", "1. បញ្ចូលកូដដូចខាងក្រោម៖\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Load the core tidyverse packages\n", "library(tidyverse)\n", "\n", "# Import the data and clean column names\n", "pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\") %>% \n", " clean_names()\n", "\n", "# Select desired columns\n", "pumpkins_select <- pumpkins %>% \n", " select(c(city_name, package, variety, origin, item_size, color)) \n", "\n", "# Drop rows containing missing values and encode color as factor (category)\n", "pumpkins_select <- pumpkins_select %>% \n", " drop_na() %>% \n", " mutate(color = factor(color))\n", "\n", "# View the first few rows\n", "pumpkins_select %>% \n", " slice_head(n = 5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "អ្នកអាចតែងតែស្ទាក់មើល dataframe ថ្មីរបស់អ្នកបានជានិច្ច ដោយប្រើកម្មវិធី [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) ដូចខាងក្រោម៖\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ចង់​បញ្ជាក់​ថា​យើង​នឹង​ធ្វើ​បញ្ហាកំណត់ចំណាត់ថ្នាក់​ដោយ​ប្រើ​ទិន្នន័យ​បីណារី​ពិតប្រាកដៈ\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Subset distinct observations in outcome column\n", "pumpkins_select %>% \n", " distinct(color)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ការមើលឃើញ - ផ្ទាំងប្រភេទ\n", "ឥឡូវនេះអ្នកបានបញ្ចូលទិន្នន័យម្ទេសម្តងទៀតហើយបានសម្អាតវាដើម្បីរក្សាទុកឈុតទិន្នន័យដែលមានអថេរច្រើនមួយចំនួន រួមមានពណ៌។ យើងចង់បង្ហាញទិន្នន័យនេះក្នុងសៀវភៅកំណត់ត្រាដោយប្រើបណ្ណាលិខិត ggplot។\n", "\n", "បណ្ណាលិខិត ggplot ផ្តល់ជម្រើសដ៏ល្អសម្រាប់ការមើលឃើញទិន្នន័យរបស់អ្នក។ ឧទាហរណ៍ អ្នកអាចប្រៀបធៀបទឹកប្រាក់ចែកចាយនៃទិន្នន័យសម្រាប់ Variety និង Color នីមួយៗក្នុងផ្ទាំងប្រភេទ។\n", "\n", "1. បង្កើតផ្ទាំងដូចនេះដោយប្រើមុខងារ geombar ដោយប្រើទិន្នន័យម្ទេសរបស់យើង ហើយកំណត់ការកំណត់ពណ៌សម្រាប់ប្រភេទម្ទេសនីមួយៗ (ទឹកក្រូច ឬ ស):\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "# Specify colors for each value of the hue variable\n", "palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n", "\n", "# Create the bar plot\n", "ggplot(pumpkins_select, aes(y = variety, fill = color)) +\n", " geom_bar(position = \"dodge\") +\n", " scale_fill_manual(values = palette) +\n", " labs(y = \"Variety\", fill = \"Color\") +\n", " theme_minimal()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ដោយសង្កេតទិន្នន័យ អ្នកអាចឃើញថាតើទិន្នន័យពណ៌ទាក់ទងដូចម្តេចទៅនឹងប្រភេទ។ \n", "\n", "✅ នៅពេលមានគំនូសតាងប្រភេទនេះ តើអ្នកអាចរំពឹងទុកការស្វែងរកដែលមានអត្ថន័យអ្វីខ្លះ?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ការប្រមូលទិន្នន័យមុនកម្រិត៖ ការកូដលក្ខណៈពិសេស\n", "\n", "ឃ្លាំងទិន្នន័យទុក្ខប៉ូលប៊ីរបស់យើងមានតម្លៃខ្សែអក្សរសម្រាប់ជួរឈរទាំងអស់របស់វា។ ការធ្វើការជាមួយទិន្នន័យប្រភេទបញ្ជីគឺងាយស្រួលសម្រាប់មនុស្ស ប៉ុន្តែមិនសម្រាប់ម៉ាស៊ីនទេ។ អាល់ហ្គរីធម៍ការសិក្សាម៉ាស៊ីនដំណើរការល្អជាមួយលេខ។ ដូច្នេះហើយការកូដខ្លឹមសារជាជំហានសំខាន់ខ្លាំងក្នុងដំណាក់កាលការប្រមូលទិន្នន័យមុនកម្រិត ពីព្រោះវាអាចផ្លាស់ប្ដូរទិន្នន័យប្រភេទបញ្ជីទៅជាទិន្នន័យលេខបាន ដោយគ្មានការបាត់បង់ព័ត៌មានណាមួយឡើយ។ ការកូដល្អនាំឲ្យបង្កើតម៉ូដែលល្អបាន។\n", "\n", "សម្រាប់ការកូដលក្ខណៈពិសេស មានអ្នកកូដពីរប្រភេទសំខាន់ៗ៖\n", "\n", "1. អ្នកកូដលំដាប់៖ វាសមស្របសម្រាប់អថេរលំដាប់ ដែលជាអថេរបញ្ជីដែលទិន្នន័យរបស់ពួកវាមានលំដាប់ត្រឹមត្រូវ ដូចជា ជួរឈរ `item_size` ក្នុងឃ្លាំងទិន្នន័យរបស់យើង។ វាបង្កើតការផ្គូផ្គង ដែលប្រភេទនីមួយៗត្រូវបានតំណាងដោយលេខ ដែលជាលំដាប់នៃប្រភេទនៅក្នុងជួរឈរ។\n", "\n", "2. អ្នកកូដប្រភេទបញ្ជី៖ វាសមស្របសម្រាប់អថេរការដែលគ្មានលំដាប់ត្រឹមត្រូវ ដែលជាអថេរបញ្ជីដែលទិន្នន័យរបស់ពួកវាមិនមានលំដាប់ត្រឹមត្រូវ ដូចជាលក្ខណៈទាំងអស់ដែលខុសពី `item_size` នៅក្នុងឃ្លាំងទិន្នន័យរបស់យើង។ វាជាការកូដមួយ-កំឡុង (one-hot encoding) មានន័យថាប្រភេទនីមួយៗត្រូវបានតំណាងដោយជួរឈរកូដពីរ (binary column): អថេរកូដមានតម្លៃស្មើ 1 ប្រសិនបើទុក្ខប៉ូលប៊ីផ принадлежности ដល់ Variety នោះ និង 0 បើមិនទេ។\n", "\n", "Tidymodels ផ្តល់ជូនកញ្ចប់មួយទៀតដែលល្អ៖ [recipes](https://recipes.tidymodels.org/) - ជាកញ្ចប់សម្រាប់ការប្រមូលទិន្នន័យមុនកម្រិត។ យើងនឹងកំណត់ `recipe` ដែលបញ្ជាក់ថាជួរឈរព្យាករ (predictor columns) ទាំងអស់គួរត្រូវបានកូដទៅជាសំណុំលេខគត់, `prep` វាដើម្បីពិនិត្យគណនាភាគរយនិងស្ថិតិដែលត្រូវការដោយប្រតិទានណាមួយ ហើយចុងក្រោយ `bake` ដើម្បីអនុវត្តគណនាដល់ទិន្នន័យថ្មី។\n", "\n", "> ជាធម្មតា recipes ត្រូវបានប្រើជាឧបករណ៍ពិនិត្យមុនសម្រាប់ម៉ូដែល ដែលវាដាក់បញ្ជីថាតើជំហានអ្វីគួរត្រូវអនុវត្តទៅលើឃ្លាំងទិន្នន័យដើម្បីទទួលបានវាសម្រាប់ម៉ូដែល។ ក្នុងករណីនេះ វា **សូមផ្ដល់អនុសាសន៍យ៉ាងខ្លាំង** អោយអ្នកប្រើជា `workflow()` មួយជំនួសការប៉ាន់ស្មាន recipe ដោយដៃប្រើ prep និង bake។ យើងនឹងឃើញរឿងទាំងនេះឲ្យបានច្បាស់ក្នុងរយៈពេលឆាប់ៗនេះ។\n", ">\n", "> ទោះយ៉ាងណាក៏ដោយ សព្វថ្ងៃយើងកំពុងប្រើ recipes + prep + bake ដើម្បីបញ្ជាក់ថាជំហានអ្វីគួរត្រូវអនុវត្តទៅលើឃ្លាំងទិន្នន័យ ដើម្បីទទួលបានវាសម្រាប់វិភាគទិន្នន័យ ហើយបន្ទាប់មកយកទិន្នន័យដែលបានប្រមូលទិន្នន័យមុនជាមួយជំហានអនុវត្តទាំងនោះ។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Preprocess and extract data to allow some data analysis\n", "baked_pumpkins <- recipe(color ~ ., data = pumpkins_select) %>%\n", " # Define ordering for item_size column\n", " step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n", " # Convert factors to numbers using the order defined above (Ordinal encoding)\n", " step_integer(item_size, zero_based = F) %>%\n", " # Encode all other predictors using one hot encoding\n", " step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE) %>%\n", " prep(data = pumpkin_select) %>%\n", " bake(new_data = NULL)\n", "\n", "# Display the first few rows of preprocessed data\n", "baked_pumpkins %>% \n", " slice_head(n = 5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ តើអត្ថប្រយោជន៍នៃការប្រើប្រាស់អ្នកបំលែងលេខរៀងសម្រាប់ជួរឈរជំនាន់ទំហំទំនិញមានអ្វីខ្លះ?\n", "\n", "### វិភាគទំនាក់ទំនងរវាងអថេរ\n", "\n", "ឥឡូវនេះដែលយើងបានដោះស្រាយទិន្នន័យរបស់យើងហើយ អាចវិភាគទំនាក់ទំនងរវាងលក្ខណៈពិសេស និងស្លាក ដើម្បីយល់ពីរបៀបដែលម៉ូដែលនឹងអាចទាយស្លាកបានល្អប៉ុណ្ណា ទៅតាមលក្ខណៈពិសេស។ វិធីធំៗសម្រាប់ធ្វើវិភាគប្រភេទនេះគឺការគូរបង្ហាញទិន្នន័យ។ \n", "យើងនឹងប្រើមុខងារ ggplot geom_boxplot_ ម្តងទៀត ដើម្បីបង្ហាញទំនាក់ទំនងរវាងទំហំទំនិញ ជម្លោះ និងពណ៌ក្នុងតារាងប្រភេទ។ ដើម្បីគូរទិន្នន័យបានល្អជាងមុន យើងនឹងប្រើជួរឈរទំហំទំនិញដែលបានបំលែងលេខរៀង ហើយជួរឈរជម្លោះដែលមិនបានបំលែង។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Define the color palette\n", "palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n", "\n", "# We need the encoded Item Size column to use it as the x-axis values in the plot\n", "pumpkins_select_plot<-pumpkins_select\n", "pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n", "\n", "# Create the grouped box plot\n", "ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n", " geom_boxplot() +\n", " facet_grid(variety ~ ., scales = \"free_x\") +\n", " scale_fill_manual(values = palette) +\n", " labs(x = \"Item Size\", y = \"\") +\n", " theme_minimal() +\n", " theme(strip.text = element_text(size = 12)) +\n", " theme(axis.text.x = element_text(size = 10)) +\n", " theme(axis.title.x = element_text(size = 12)) +\n", " theme(axis.title.y = element_blank()) +\n", " theme(legend.position = \"bottom\") +\n", " guides(fill = guide_legend(title = \"Color\")) +\n", " theme(panel.spacing = unit(0.5, \"lines\"))+\n", " theme(strip.text.y = element_text(size = 4, hjust = 0)) \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ប្រើ plots រួមមួយ\n", "\n", "ព្រោះពណ៌ជា​ប្រភេទពីររបៀប (ស និង មិនស) វាត្រូវការពី '[វិធីជាច្រើនពិសេស](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf)' ដើម្បី​បង្ហាញភាព។\n", "\n", "សាកល្បង `swarm plot` ដើម្បីបង្ហាញចំណាត់ថ្នាក់នៃពណ៌ដោយទាក់ទងទៅនឹង item_size។\n", "\n", "យើងនឹងប្រើ [កញ្ចប់ ggbeeswarm](https://github.com/eclarke/ggbeeswarm) ដែលផ្តល់វិធីសាស្រ្តបង្កើត plots រចនាប័ទ្ម beeswarm ដោយប្រើ ggplot2។ Plots beeswarm ជាវិធីមួយនៃការបញ្ចាំងចំណុចដែលធម្មតានឹងគ្នាហើយធ្វើឲ្យវាធ្លាក់នៅជាមួយគ្នានៅជិតៗគ្នាមិនឲ្យគ្នាហែលឆ្ងាយ។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Create beeswarm plots of color and item_size\n", "baked_pumpkins %>% \n", " mutate(color = factor(color)) %>% \n", " ggplot(mapping = aes(x = color, y = item_size, color = color)) +\n", " geom_quasirandom() +\n", " scale_color_brewer(palette = \"Dark2\", direction = -1) +\n", " theme(legend.position = \"none\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ឥឡូវនេះឥឡូវនេះយើងមានគំនិតអំពីទំនាក់ទំនងរវាងប្រភេទទំនាស់ពីរក្រុមនៃពណ៌ និងក្រុមធំទូលាយនៃទំហំ មកសូមស្វែងយល់អំពី logistic regression ដើម្បីកំណត់ពណ៌ស្មេចដែលអាចមានបាន។\n", "\n", "## សង់ម៉ូដែលរបស់អ្នក\n", "\n", "ជ្រើសរើសអថេរដែលអ្នកចង់ប្រើនៅក្នុងម៉ូដែលចាត់ថ្នាក់របស់អ្នក ហើយបំបែកទិន្នន័យទៅជាសំណុំបណ្ដុះបណ្ដាល និងសំណុំសាកល្បង។ [rsample](https://rsample.tidymodels.org/), គឺជាកញ្ចប់ក្នុង Tidymodels, ផ្តល់ឱ្យនូវមូលដ្ឋានគ្រឹះសម្រាប់ការបំបែកទិន្នន័យ និងការបង្កើតសំណុំឡើងវិញបានយ៉ាងមានប្រសិទ្ធភាព។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Split data into 80% for training and 20% for testing\n", "set.seed(2056)\n", "pumpkins_split <- pumpkins_select %>% \n", " initial_split(prop = 0.8)\n", "\n", "# Extract the data in each split\n", "pumpkins_train <- training(pumpkins_split)\n", "pumpkins_test <- testing(pumpkins_split)\n", "\n", "# Print out the first 5 rows of the training set\n", "pumpkins_train %>% \n", " slice_head(n = 5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "🙌 ឥឡូវនេះ យើងបានត្រៀមខ្លួនរួចរាល់ក្នុងការបណ្តុះម៉ូឌែលដោយតម្រឹមលក្ខណៈបណ្តុះបណ្តាលទៅកាន់ស្លាកបណ្តុះបណ្តាល (ពណ៌) ។\n", "\n", "យើងនឹងចាប់ផ្តើមដោយបង្កើតវត្ថុវិធីដែលបញ្ជាក់ពីជំហានកំណត់មុនដែលគួរត្រូវបានអនុវត្តលើទិន្នន័យរបស់យើងដើម្បីធ្វើឲ្យវាប្រៀបប្រដាប់សម្រាប់ការដំណើរការ ម៉ូឌែល គឺ៖ ការរុំបញ្ចូលអថេរក្រុមជាគុណភាពទៅជាសំណុំចំនួនគត់។ ដូចជា `baked_pumpkins` យើងបង្កើតវត្ថុវិធី `pumpkins_recipe` ប៉ុន្តែ​មិនធ្វើការ `prep` និង `bake` មែនទែន ព្រោះវានឹងត្រូវបានបញ្ចូលក្នុងលំហូរ ការចុះបញ្ជី អ្នកនឹងមើលឃើញវាក្នុងជំហានមួយចំនួនបន្ទាប់ពីនេះ។\n", "\n", "មានវិធីជាច្រើនក្នុងការបញ្ជាក់ម៉ូឌែល logistic regression ក្នុង Tidymodels។ សូមមើល `?logistic_reg()` សម្រាប់ពេលនេះ យើងនឹងបញ្ជាក់ម៉ូឌែល logistic regression តាមរយៈម៉ូទ័រ `stats::glm()` ដែលជាគំរូលំនាំដើម។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Create a recipe that specifies preprocessing steps for modelling\n", "pumpkins_recipe <- recipe(color ~ ., data = pumpkins_train) %>% \n", " step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n", " step_integer(item_size, zero_based = F) %>% \n", " step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE)\n", "\n", "# Create a logistic model specification\n", "log_reg <- logistic_reg() %>% \n", " set_engine(\"glm\") %>% \n", " set_mode(\"classification\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ឥឡូវនេះ យើងមានរូបមន្តមួយ និងការបញ្ជាក់ម៉ូដែលមួយហើយ យើងត្រូវការស្វែងរកវិធីមួយដើម្បីបញ្ចូលពួកវាទាំងពីរចូលក្នុងវត្ថុមួយដែលនឹងរៀបចំទិន្នន័យជាមុន (prep+bake នៅពីក្រោយឆាក), ដាក់ម៉ូដែលលើទិន្នន័យដែលបានរៀបចំ និងក៏អនុញ្ញាតឱ្យមានសកម្មភាពបន្ទាប់ម៉ាផង។\n", "\n", "នៅក្នុង Tidymodels វត្ថុងាយស្រួលនេះហៅថា [`workflow`](https://workflows.tidymodels.org/) ហើយវាធ្វើការរក្សាទុកធាតុម៉ូដែលរបស់អ្នកយ៉ាងងាយស្រួល។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Bundle modelling components in a workflow\n", "log_reg_wf <- workflow() %>% \n", " add_recipe(pumpkins_recipe) %>% \n", " add_model(log_reg)\n", "\n", "# Print out the workflow\n", "log_reg_wf\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "បន្ទាប់ពីបាន *បញ្ជាក់* workflow មួយ model អាចត្រូវបាន `បណ្តុះបណ្តាល` ដោយប្រើមុខងារ [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html)។ workflow នឹងវាយតម្លៃមុខងារ recipe និង preprocess ទិន្នន័យមុនការបណ្តុះបណ្តាល ដូច្នេះយើងមិនចាំបាច់ត្រូវធ្វើដៃដោយប្រើ prep និង bake ទេ។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Train the model\n", "wf_fit <- log_reg_wf %>% \n", " fit(data = pumpkins_train)\n", "\n", "# Print the trained workflow\n", "wf_fit\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ការបង្ហាញម៉ូដែលបោះផ្សាយអំពីសមាមាត្រដែលបានរៀនក្នុងអំឡុងពេលបណ្តុះបណ្តាល។\n", "\n", "ឥឡូវនេះយើងបានបណ្តុះបណ្តាលម៉ូដែលដោយប្រើទិន្នន័យបណ្តុះបណ្តាលហើយ យើងអាចធ្វើការទស្សន៍ទាយលើទិន្នន័យសាកល្បងដោយប្រើ [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html)។ បង្វៀងចាប់ផ្តើមដោយប្រើម៉ូដែលនេះដើម្បីទស្សន៍ទាយស្លាកសញ្ញាសម្រាប់សំណុំសាកល្បងរបស់យើង និងប្រភាពសម្រាប់រាល់ស្លាក។ នៅពេលដែលប្រភាពច្រើនជាង 0.5 ការទស្សន៍ទាយថ្នាក់គឺជា `WHITE` ប្រសិនបើមិនដូច្នោះទេ គឺ `ORANGE`។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Make predictions for color and corresponding probabilities\n", "results <- pumpkins_test %>% select(color) %>% \n", " bind_cols(wf_fit %>% \n", " predict(new_data = pumpkins_test)) %>%\n", " bind_cols(wf_fit %>%\n", " predict(new_data = pumpkins_test, type = \"prob\"))\n", "\n", "# Compare predictions\n", "results %>% \n", " slice_head(n = 10)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ឆ្លើយបានល្អណាស់! នេះផ្តល់ការយល់ដឹងបន្ថែមពីរបៀបដែល logistic regression ធ្វើការ។\n", "\n", "### ការយល់ដឹងកាន់តែប្រសើរ តាមរយៈមាទ្រីកខុសគ្នា\n", "\n", "ការប្រៀបធៀបទាំងអស់នៃការព្យាករណ៍ជាមួយតម្លៃ \"ពិត\" ក្នុងការពិតមិនមែនជាវិធីមានប្រសិទ្ធភាពសម្រាប់កំណត់ថាតើម៉ូដែលព្យាករណ៍បានល្អប៉ុណ្ណា។ គ្រប់គ្រាន់ហើយ Tidymodels មានជំនាញបន្ថែមមួយចំនួន៖ [`yardstick`](https://yardstick.tidymodels.org/) - ជាប៉ាកេជ្យដែលប្រើសម្រាប់វាស់ប្រសិទ្ធភាពនៃម៉ូដែលប្រើគ្រឿងសម្រួលសមត្ថភាព។\n", "\n", "គ្រឿងសម្រួលសមត្ថភាពមួយដែលទាក់ទងនឹងបញ្ហាការបែងចែកគឺ [`confusion matrix`](https://wikipedia.org/wiki/Confusion_matrix)។ មាទ្រីកខុសគ្នា​នេះពិពណ៌នាថាតើម៉ូដែលបែងចែកមានសមត្ថភាពល្អយ៉ាងដូចម្តេច។ មាទ្រីកខុសគ្នាដាក់បញ្ជីចំនួនឧទាហរណ៍នីមួយៗក្នុងថ្នាក់មួយត្រូវបានបែងចែកបានត្រឹមត្រូវដោយម៉ូដែលប៉ុន្មាន។ ក្នុងករណីរបស់យើង វានឹងបង្ហាញអ្នកថា តើមានប៊ឺរមាសពណ៌ទឹកដោះគោប៉ុន្មានដែលបានបែងចែកថាជា​ប៊ឺរមាសពណ៌ទឹកដោះគោ និងប៊ឺរស មួយពណ៌សប៉ុន្មានដែលបានបាំងចែកថាជាប៊ឺរស ពណ៌ស; មាទ្រីកខុសគ្នាក៏បង្ហាញអ្នកថា ប៊ឺរដែលបានបែងចែកទៅក្នុងប្រភេទដែលមិនត្រឹមត្រូវប៉ុណ្ណា។\n", "\n", "មុខងារ [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) ពី yardstick គណនាការប្រមូលផ្ដុំគ្នានៃថ្នាក់ដែលបានសង្កេត និងថ្នាក់ដែលបានព្យាករណ៍។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Confusion matrix for prediction results\n", "conf_mat(data = results, truth = color, estimate = .pred_class)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "អនុវត្តន៍សន្ទស្សន៍ច្របូកច្របល់។ គំរូរបស់យើងត្រូវបានស្នើឲ្យចាត់ថ្នាក់កន្ទុយកំណាត់មួយចំនួនចេញជាប្រភេទពីរប៊ីណារី គឺ ប្រភេទ `ស` និងប្រភេទ `មិនស`\n", "\n", "- ប្រសិនបើគំរូរបស់អ្នកទាយថាកន្ទុយកំណាត់គឺស ហើយវាគឺជាប្រភេទ 'ស' ក្នុងការពិត ខ្លួនយើងហៅវាថា `ពិតវិជ្ជមាន` ដែលបង្ហាញដោយលេខខាងឆ្វេងលើ។\n", "\n", "- ប្រសិនបើគំរូរបស់អ្នកទាយថាកន្ទុយកំណាត់គឺមិនស ហើយវាគឺជាប្រភេទ 'ស' ក្នុងការពិត ខ្លួនយើងហៅវាថា `មិនពិតអវិជ្ជមាន` ដែលបង្ហាញដោយលេខខាងឆ្វេងខាងក្រោម។\n", "\n", "- ប្រសិនបើគំរូរបស់អ្នកទាយថាកន្ទុយកំណាត់គឺស ហើយវាគឺជាប្រភេទ 'មិនស' ក្នុងការពិត ខ្លួនយើងហៅវាថា `មិនពិតវិជ្ជមាន` ដែលបង្ហាញដោយលេខខាងស្ដាំលើ។\n", "\n", "- ប្រសិនបើគំរូរបស់អ្នកទាយថាកន្ទុយកំណាត់គឺមិនស ហើយវាគឺជាប្រភេទ 'មិនស' ក្នុងការពិត ខ្លួនយើងហៅវាថា `ពិតអវិជ្ជមាន` ដែលបង្ហាញដោយលេខខាងស្ដាំខាងក្រោម។\n", "\n", "| Truth |\n", "|:-----:|\n", "\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **Predicted** | ស | ទឹកក្រូច |\n", "| ស | TP | FP |\n", "| ទឹកក្រូច | FN | TN |\n", "\n", "ដូចដែលអ្នកអាចគិតថាវាគឺល្អប្រសើរជាងក្នុងការមានចំនួននៅក្នុង true positives និង true negatives ធំបំផុត និងមាន false positives និង false negatives តិចបំផុត ដែលបង្ហាញថាគំរូមានការអនុវត្តល្អជាង។\n", "\n", "សន្ទស្សន៍ច្របូកច្របល់មានប្រយោជន៍ព្រោះវាបង្កើតទៅរកមាត្រដ្ឋានផ្សេងទៀតដែលអាចជួយយើងប៉ាន់ប្រាក់បានល្អប្រសើរជាងអំពីការអនុវត្តន៍នៃគំរូចាត់ថ្នាក់។ មកមើលខ្លះៗពីវា៖\n", "\n", "🎓 Precision: `TP/(TP + FP)` កំណត់ថាជាភាគរយនៃការទាយថាជាវិជ្ជមានដែលពិតជាវិជ្ជមាន។ ក៏ត្រូវ​បានហៅថា [positive predictive value](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\")\n", "\n", "🎓 Recall: `TP/(TP + FN)` កំណត់ថាជាភាគរយនៃលទ្ធផលវិជ្ជមានក្នុងចំណោមចំនួននៃគំរូដែលពិតជាវិជ្ជមាន។ ក៏ត្រូវបានគេស្គាល់ថា `sensitivity`។\n", "\n", "🎓 Specificity: `TN/(TN + FP)` កំណត់ថាជាភាគរយនៃលទ្ធផលអវិជ្ជមានក្នុងចំណោមចំនួននៃគំរូដែលពិតជាអវិជ្ជមាន។\n", "\n", "🎓 Accuracy: `TP + TN/(TP + TN + FP + FN)` ភាគរយនៃស្លាកដែលបានទាយបានត្រឹមត្រូវសម្រាប់គំរូមួយ។\n", "\n", "🎓 F Measure: ជាមធ្យមគតិដូនទម្ងន់រវាង precision និង recall ដែលល្អបំផុតគឺ 1 ហើយអាក្រក់បំផុតគឺ 0។\n", "\n", "មកគណនាមាត្រដ្ឋានទាំងនេះគ្នាដូរ!\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Combine metric functions and calculate them all at once\n", "eval_metrics <- metric_set(ppv, recall, spec, f_meas, accuracy)\n", "eval_metrics(data = results, truth = color, estimate = .pred_class)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ការមើលឃើញឆ្លងបន្ទាត់ ROC នៃម៉ូដែលនេះ\n", "\n", "មកធ្វើការមើលឃើញមួយទៀតដើម្បីឃើញអ្វីដែលហៅថា [`ROC curve`](https://en.wikipedia.org/wiki/Receiver_operating_characteristic):\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Make a roc_curve\n", "results %>% \n", " roc_curve(color, .pred_ORANGE) %>% \n", " autoplot()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ROC curves តែងត្រូវបានប្រើសម្រាប់ទទួលបានទិដ្ឋភាពនៃលទ្ធផលនៃម៉ាស៊ីនចាត់ថ្នាក់មួយដោយពិចារណាពីចំណុចពិតវិជ្ជមានប្រៀបធៀបនឹងចំណុចមិនពិតវិជ្ជមាន។ ROC curves ជាទូទៅមានអត្រាចំណុចវិជ្ជមានពិត / ការពិសោធន៍លើ Y axis និងអត្រាចំណុចវិជ្ជមានមិនពិត / 1-ភាពជាក់លាក់លើ X axis។ ដូចនេះ, ពហុភាពរបស់ខ្សែនិងកន្លែងរវាងបន្ទាត់កណ្តាលនិងខ្សែកោងមានសារៈសំខាន់: អ្នកចង់បានខ្សែកោងដែលឡើងខ្ពស់លឿនហើយឆ្លងកាត់បន្ទាត់។ ក្នុងករណីរបស់យើងមានចំណុចវិជ្ជមានមិនពិតមុនសិន រួចបន្ទាត់ឡើងខ្ពស់ហើយឆ្លងកាត់យ៉ាងត្រឹមត្រូវ។\n", "\n", "ចុងក្រោយនេះ មកប្រើ `yardstick::roc_auc()` ដើម្បីគណនាតំបន់ក្រោមខ្សែកោងពិត។ មួយវិធីក្នុងការពន្យល់ AUC គឺជាភាពមាននៅក្នុងម៉ូដែលថាលំដាប់នៃឧទាហរណ៍វិជ្ជមានចៃដន្យខ្ពស់ជាងឧទាហរណ៍អវិជ្ជមានចៃដន្យ។\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Calculate area under curve\n", "results %>% \n", " roc_auc(color, .pred_ORANGE)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "លទ្ធផលស្ថិតនៅជុំវិញ `0.975`។ ដោយសារតែ AUC មានជួរពី 0 ដល់ 1 អ្នកចង់បានពិន្ទុធំ មកព្រោះម៉ូដែលដែលត្រឹមត្រូវ ១០០% ក្នុងការទុក្ខលំបាករបស់វានឹងមាន AUC ស្មើ 1; ក្នុងករណីនេះ ម៉ូដែលគឺ *ល្អណាស់*។\n", "\n", "នៅមេរៀនក្នុងអនាគតអំពីការបែងចែក ប្រភេទ អ្នកនឹងរៀនពីរបៀបធ្វើឲ្យពិន្ទុរបស់ម៉ូដែលរបស់អ្នកប្រសើរឡើង (ដូចជាការដោះស្រាយទិន្នន័យមិនស្មើគ្នានៅក្នុងករណីនេះ)។\n", "\n", "## 🚀 បញ្ញាកchallenge\n", "\n", "មានច្រើនអ្វីដែលត្រូវរំលេចទៀតទាក់ទងនឹង logistic regression! ប៉ុន្តែ វិធីល្អបំផុតក្នុងការរៀនគឺការសាកល្បង។ រកឃើញឧបករណ៍ទិន្នន័យមួយដែលសមស្របសម្រាប់ការវិភាគប្រភេទនេះ ហើយសង់ម៉ូដែលជាមួយវា។ តើអ្នកបានរៀនអ្វីខ្លះ? គំនិត៖ ព្យាយាមប្រើ [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) សម្រាប់ឧបករណ៍ទិន្នន័យដែលគួរឱ្យចាប់អារម្មណ៍។\n", "\n", "## ការត្រួតពិនិត្យ & ការសិក្សាឯករាជ្យ\n", "\n", "អានទំព័រដើមពីរបីនៃ [ឯកសារនេះពី Stanford](https://web.stanford.edu/~jurafsky/slp3/5.pdf) អំពីការប្រើប្រាស់ជាក់ស្តែងរបស់ logistic regression។ គិតអំពីភារកិច្ចដែលសមស្របសម្រាប់ប្រភេទ regression តែមួយ ឬមួយផ្សេងទៀតដែលយើងបានសិក្សាពីមុនដល់ពេលនេះ។ តើអ្វីជា វិធីល្អបំផុត?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n\n\n**ការបដិសេធ**: \nឯកសារនេះត្រូវបានបកប្រែដោយប្រើសេវាបកប្រែ AI [Co-op Translator](https://github.com/Azure/co-op-translator)។ ខណៈពេលយើងខិតខំសម្រាប់ភាពត្រឹមត្រូវ សូមយកចិត្តទុកដាក់ថាការបកប្រែដោយស្វ័យប្រវត្តិអាចមានកំហុសឬភាពមិនត្រឹមត្រូវ។ ឯកសារដើមជាភាសាផ្ទាល់ជាគោលដៅផ្លូវការដែលគួរត្រូវបានយកចិត្តទុកដាក់។ សម្រាប់ព័ត៌មានសំខាន់ណាស់ គួរត្រូវបានបកប្រែដោយអ្នកជំនាញមនុស្សវិជ្ជាជីវៈ។ យើងមិនទទួលខុសត្រូវចំពោះការយល់ច្រឡំឬការបកប្រែខុសដែលកើតឡើងពីការប្រើប្រាស់ការបកប្រែនេះនោះទេ។\n\n" ] } ], "metadata": { "anaconda-cloud": "", "kernelspec": { "display_name": "R", "langauge": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "3.4.1" } }, "nbformat": 4, "nbformat_minor": 1 }