{ "nbformat": 4, "nbformat_minor": 2, "metadata": { "colab": { "name": "lesson_1-R.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true }, "kernelspec": { "name": "ir", "display_name": "R" }, "language_info": { "name": "R" }, "coopTranslator": { "original_hash": "c18d3bd0bd8ae3878597e89dcd1fa5c1", "translation_date": "2025-09-06T13:44:22+00:00", "source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb", "language_code": "th" } }, "cells": [ { "cell_type": "markdown", "source": [], "metadata": { "id": "YJUHCXqK57yz" } }, { "cell_type": "markdown", "source": [ "## บทนำสู่การวิเคราะห์การถดถอย - บทเรียนที่ 1\n", "\n", "#### ทำความเข้าใจในมุมมอง\n", "\n", "✅ มีวิธีการวิเคราะห์การถดถอยหลายประเภท และการเลือกใช้วิธีใดขึ้นอยู่กับคำตอบที่คุณต้องการ หากคุณต้องการทำนายความสูงที่เป็นไปได้ของบุคคลในช่วงอายุหนึ่ง คุณจะใช้ `linear regression` เพราะคุณกำลังมองหาค่า **ตัวเลข** หากคุณสนใจที่จะค้นหาว่าประเภทของอาหารควรถือว่าเป็นมังสวิรัติหรือไม่ คุณกำลังมองหาการ **จัดหมวดหมู่** ดังนั้นคุณจะใช้ `logistic regression` คุณจะได้เรียนรู้เพิ่มเติมเกี่ยวกับ logistic regression ในภายหลัง ลองคิดถึงคำถามบางข้อที่คุณสามารถถามจากข้อมูล และวิธีการใดที่เหมาะสมที่สุด\n", "\n", "ในส่วนนี้ คุณจะได้ทำงานกับ [ชุดข้อมูลขนาดเล็กเกี่ยวกับโรคเบาหวาน](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html) ลองจินตนาการว่าคุณต้องการทดสอบการรักษาสำหรับผู้ป่วยโรคเบาหวาน โมเดล Machine Learning อาจช่วยคุณระบุว่าผู้ป่วยคนใดจะตอบสนองต่อการรักษาได้ดีกว่า โดยอิงจากการผสมผสานของตัวแปรต่าง ๆ แม้แต่โมเดลการถดถอยที่พื้นฐานที่สุด เมื่อถูกนำเสนอในรูปแบบภาพ อาจแสดงข้อมูลเกี่ยวกับตัวแปรที่ช่วยให้คุณจัดการทดลองทางคลินิกในเชิงทฤษฎีได้อย่างมีประสิทธิภาพ\n", "\n", "เมื่อกล่าวเช่นนั้น มาเริ่มต้นงานนี้กันเลย!\n", "\n", "

\n", " \n", "

ผลงานศิลปะโดย @allison_horst
\n", "\n", "\n" ], "metadata": { "id": "LWNNzfqd6feZ" } }, { "cell_type": "markdown", "source": [ "## 1. การเตรียมเครื่องมือของเรา\n", "\n", "สำหรับงานนี้ เราจะต้องใช้แพ็กเกจดังต่อไปนี้:\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/) คือ [ชุดของแพ็กเกจใน R](https://www.tidyverse.org/packages) ที่ออกแบบมาเพื่อทำให้การวิเคราะห์ข้อมูลรวดเร็วขึ้น ง่ายขึ้น และสนุกมากขึ้น!\n", "\n", "- `tidymodels`: [tidymodels](https://www.tidymodels.org/) เป็นกรอบการทำงานที่เป็น [ชุดของแพ็กเกจ](https://www.tidymodels.org/packages/) สำหรับการสร้างโมเดลและการเรียนรู้ของเครื่อง\n", "\n", "คุณสามารถติดตั้งแพ็กเกจเหล่านี้ได้ด้วยคำสั่ง:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\"))`\n", "\n", "สคริปต์ด้านล่างจะตรวจสอบว่าคุณมีแพ็กเกจที่จำเป็นสำหรับการทำโมดูลนี้หรือไม่ และจะติดตั้งให้ในกรณีที่บางแพ็กเกจขาดหายไป\n" ], "metadata": { "id": "FIo2YhO26wI9" } }, { "cell_type": "code", "execution_count": 2, "source": [ "suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n", "pacman::p_load(tidyverse, tidymodels)" ], "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "Loading required package: pacman\n", "\n" ] } ], "metadata": { "id": "cIA9fz9v7Dss", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "2df7073b-86b2-4b32-cb86-0da605a0dc11" } }, { "cell_type": "markdown", "source": [ "ตอนนี้ มาโหลดแพ็กเกจที่ยอดเยี่ยมเหล่านี้และทำให้พร้อมใช้งานในเซสชัน R ปัจจุบันของเรา (นี่เป็นเพียงตัวอย่าง `pacman::p_load()` ได้ทำสิ่งนี้ให้คุณแล้ว)\n" ], "metadata": { "id": "gpO_P_6f9WUG" } }, { "cell_type": "code", "execution_count": null, "source": [ "# load the core Tidyverse packages\r\n", "library(tidyverse)\r\n", "\r\n", "# load the core Tidymodels packages\r\n", "library(tidymodels)\r\n" ], "outputs": [], "metadata": { "id": "NLMycgG-9ezO" } }, { "cell_type": "markdown", "source": [ "## 2. ชุดข้อมูลโรคเบาหวาน\n", "\n", "ในแบบฝึกหัดนี้ เราจะนำทักษะการวิเคราะห์การถดถอยมาใช้โดยการทำนายบนชุดข้อมูลโรคเบาหวาน ชุดข้อมูล [โรคเบาหวาน](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt) ประกอบด้วย `442 ตัวอย่าง` ของข้อมูลเกี่ยวกับโรคเบาหวาน โดยมีตัวแปรคุณลักษณะเชิงพยากรณ์ 10 ตัว ได้แก่ `อายุ`, `เพศ`, `ดัชนีมวลกาย`, `ความดันโลหิตเฉลี่ย`, และ `การวัดระดับเซรั่มในเลือดหกตัว` รวมถึงตัวแปรผลลัพธ์ `y`: การวัดเชิงปริมาณของการพัฒนาของโรคในหนึ่งปีหลังจากจุดเริ่มต้น\n", "\n", "|จำนวนการสังเกตการณ์|442|\n", "|----------------------|:---|\n", "|จำนวนตัวแปรพยากรณ์|10 คอลัมน์แรกเป็นตัวแปรเชิงพยากรณ์เชิงตัวเลข|\n", "|ผลลัพธ์/เป้าหมาย|คอลัมน์ที่ 11 เป็นการวัดเชิงปริมาณของการพัฒนาของโรคในหนึ่งปีหลังจากจุดเริ่มต้น|\n", "|ข้อมูลตัวแปรพยากรณ์|- อายุเป็นปี\n", "||- เพศ\n", "||- bmi ดัชนีมวลกาย\n", "||- bp ความดันโลหิตเฉลี่ย\n", "||- s1 tc, คอเลสเตอรอลรวมในเซรั่ม\n", "||- s2 ldl, ไลโปโปรตีนความหนาแน่นต่ำ\n", "||- s3 hdl, ไลโปโปรตีนความหนาแน่นสูง\n", "||- s4 tch, คอเลสเตอรอลรวม / HDL\n", "||- s5 ltg, อาจเป็นค่าลอการิทึมของระดับไตรกลีเซอไรด์ในเซรั่ม\n", "||- s6 glu, ระดับน้ำตาลในเลือด|\n", "\n", "> 🎓 จำไว้ว่า นี่คือการเรียนรู้แบบมีผู้สอน และเราต้องมีเป้าหมายที่ชื่อว่า 'y'\n", "\n", "ก่อนที่คุณจะสามารถจัดการข้อมูลด้วย R ได้ คุณจำเป็นต้องนำเข้าข้อมูลเข้าสู่หน่วยความจำของ R หรือสร้างการเชื่อมต่อกับข้อมูลที่ R สามารถใช้เพื่อเข้าถึงข้อมูลจากระยะไกล\n", "\n", "> แพ็กเกจ [readr](https://readr.tidyverse.org/) ซึ่งเป็นส่วนหนึ่งของ Tidyverse ให้วิธีการที่รวดเร็วและเป็นมิตรในการอ่านข้อมูลแบบสี่เหลี่ยมเข้าสู่ R\n", "\n", "ตอนนี้ เรามาโหลดชุดข้อมูลโรคเบาหวานจาก URL แหล่งข้อมูลนี้: \n", "\n", "นอกจากนี้ เราจะทำการตรวจสอบความสมเหตุสมผลของข้อมูลโดยใช้ `glimpse()` และแสดง 5 แถวแรกโดยใช้ `slice()`\n", "\n", "ก่อนที่จะไปต่อ เรามาแนะนำสิ่งที่คุณจะพบเจอบ่อยในโค้ด R 🥁🥁: ตัวดำเนินการ pipe `%>%`\n", "\n", "ตัวดำเนินการ pipe (`%>%`) ทำการดำเนินการตามลำดับตรรกะโดยส่งวัตถุไปข้างหน้าเข้าสู่ฟังก์ชันหรือคำสั่ง คุณสามารถคิดว่าตัวดำเนินการ pipe เป็นการพูดว่า \"และจากนั้น\" ในโค้ดของคุณ\n" ], "metadata": { "id": "KM6iXLH996Cl" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Import the data set\r\n", "diabetes <- read_table2(file = \"https://www4.stat.ncsu.edu/~boos/var.select/diabetes.rwrite1.txt\")\r\n", "\r\n", "\r\n", "# Get a glimpse and dimensions of the data\r\n", "glimpse(diabetes)\r\n", "\r\n", "\r\n", "# Select the first 5 rows of the data\r\n", "diabetes %>% \r\n", " slice(1:5)" ], "outputs": [], "metadata": { "id": "Z1geAMhM-bSP" } }, { "cell_type": "markdown", "source": [ "`glimpse()` แสดงให้เห็นว่าข้อมูลนี้มี 442 แถว และ 11 คอลัมน์ โดยทุกคอลัมน์เป็นชนิดข้อมูล `double`\n", "\n", "
\n", "\n", "> `glimpse()` และ `slice()` เป็นฟังก์ชันใน [`dplyr`](https://dplyr.tidyverse.org/) Dplyr ซึ่งเป็นส่วนหนึ่งของ Tidyverse เป็นไวยากรณ์สำหรับการจัดการข้อมูลที่ให้ชุดคำกริยาที่สอดคล้องกันเพื่อช่วยแก้ปัญหาท้าทายที่พบบ่อยที่สุดในการจัดการข้อมูล\n", "\n", "
\n", "\n", "ตอนนี้เมื่อเรามีข้อมูลแล้ว เรามาโฟกัสไปที่คุณลักษณะหนึ่ง (`bmi`) เพื่อใช้ในแบบฝึกหัดนี้ ซึ่งจะต้องเลือกคอลัมน์ที่ต้องการ แล้วเราจะทำสิ่งนี้ได้อย่างไร?\n", "\n", "[`dplyr::select()`](https://dplyr.tidyverse.org/reference/select.html) ช่วยให้เราสามารถ *เลือก* (และเปลี่ยนชื่อได้ถ้าต้องการ) คอลัมน์ใน data frame\n" ], "metadata": { "id": "UwjVT1Hz-c3Z" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Select predictor feature `bmi` and outcome `y`\r\n", "diabetes_select <- diabetes %>% \r\n", " select(c(bmi, y))\r\n", "\r\n", "# Print the first 5 rows\r\n", "diabetes_select %>% \r\n", " slice(1:10)" ], "outputs": [], "metadata": { "id": "RDY1oAKI-m80" } }, { "cell_type": "markdown", "source": [ "## 3. ข้อมูลการฝึกและการทดสอบ\n", "\n", "ในกระบวนการเรียนรู้แบบมีผู้สอน มักจะมีการ *แบ่ง* ข้อมูลออกเป็นสองชุดย่อย; ชุดที่ใหญ่กว่า (โดยทั่วไป) สำหรับการฝึกโมเดล และชุดที่เล็กกว่า \"สำรองไว้\" เพื่อดูว่าโมเดลทำงานได้ดีเพียงใด\n", "\n", "ตอนนี้เรามีข้อมูลพร้อมแล้ว เราสามารถดูได้ว่ามีวิธีที่เครื่องสามารถช่วยกำหนดการแบ่งที่เหมาะสมระหว่างตัวเลขในชุดข้อมูลนี้หรือไม่ เราสามารถใช้แพ็กเกจ [rsample](https://tidymodels.github.io/rsample/) ซึ่งเป็นส่วนหนึ่งของเฟรมเวิร์ก Tidymodels เพื่อสร้างออบเจ็กต์ที่มีข้อมูลเกี่ยวกับ *วิธี* การแบ่งข้อมูล และใช้ฟังก์ชัน rsample อีกสองตัวเพื่อดึงชุดข้อมูลการฝึกและการทดสอบที่สร้างขึ้น:\n" ], "metadata": { "id": "SDk668xK-tc3" } }, { "cell_type": "code", "execution_count": null, "source": [ "set.seed(2056)\r\n", "# Split 67% of the data for training and the rest for tesing\r\n", "diabetes_split <- diabetes_select %>% \r\n", " initial_split(prop = 0.67)\r\n", "\r\n", "# Extract the resulting train and test sets\r\n", "diabetes_train <- training(diabetes_split)\r\n", "diabetes_test <- testing(diabetes_split)\r\n", "\r\n", "# Print the first 3 rows of the training set\r\n", "diabetes_train %>% \r\n", " slice(1:10)" ], "outputs": [], "metadata": { "id": "EqtHx129-1h-" } }, { "cell_type": "markdown", "source": [ "## 4. ฝึกโมเดลการถดถอยเชิงเส้นด้วย Tidymodels\n", "\n", "ตอนนี้เราพร้อมที่จะฝึกโมเดลของเราแล้ว!\n", "\n", "ใน Tidymodels คุณสามารถกำหนดโมเดลโดยใช้ `parsnip()` โดยระบุแนวคิดสามอย่างดังนี้:\n", "\n", "- **ประเภทของโมเดล** ใช้เพื่อแยกแยะโมเดล เช่น การถดถอยเชิงเส้น การถดถอยโลจิสติก โมเดลต้นไม้ตัดสินใจ และอื่นๆ\n", "\n", "- **โหมดของโมเดล** รวมถึงตัวเลือกทั่วไป เช่น การถดถอยและการจำแนกประเภท; โมเดลบางประเภทสามารถรองรับทั้งสองโหมดนี้ ในขณะที่บางประเภทมีเพียงโหมดเดียว\n", "\n", "- **เครื่องมือของโมเดล** คือเครื่องมือคำนวณที่จะใช้ในการปรับโมเดล โดยมักจะเป็นแพ็กเกจใน R เช่น **`\"lm\"`** หรือ **`\"ranger\"`**\n", "\n", "ข้อมูลเกี่ยวกับการสร้างโมเดลนี้จะถูกบันทึกไว้ในสเปคโมเดล ดังนั้นเรามาสร้างกันเลย!\n" ], "metadata": { "id": "sBOS-XhB-6v7" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Build a linear model specification\r\n", "lm_spec <- \r\n", " # Type\r\n", " linear_reg() %>% \r\n", " # Engine\r\n", " set_engine(\"lm\") %>% \r\n", " # Mode\r\n", " set_mode(\"regression\")\r\n", "\r\n", "\r\n", "# Print the model specification\r\n", "lm_spec" ], "outputs": [], "metadata": { "id": "20OwEw20--t3" } }, { "cell_type": "markdown", "source": [ "หลังจากที่โมเดลถูก *กำหนด* แล้ว โมเดลสามารถถูก `ประเมิน` หรือ `ฝึกฝน` ได้โดยใช้ฟังก์ชัน [`fit()`](https://parsnip.tidymodels.org/reference/fit.html) ซึ่งมักจะใช้สูตรและข้อมูลบางส่วน\n", "\n", "`y ~ .` หมายความว่าเราจะปรับ `y` ให้เป็นค่าที่คาดการณ์/เป้าหมาย โดยอธิบายด้วยตัวแปรทำนาย/คุณลักษณะทั้งหมด เช่น `.` (ในกรณีนี้ เรามีตัวแปรทำนายเพียงตัวเดียว: `bmi`)\n" ], "metadata": { "id": "_oDHs89k_CJj" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Build a linear model specification\r\n", "lm_spec <- linear_reg() %>% \r\n", " set_engine(\"lm\") %>%\r\n", " set_mode(\"regression\")\r\n", "\r\n", "\r\n", "# Train a linear regression model\r\n", "lm_mod <- lm_spec %>% \r\n", " fit(y ~ ., data = diabetes_train)\r\n", "\r\n", "# Print the model\r\n", "lm_mod" ], "outputs": [], "metadata": { "id": "YlsHqd-q_GJQ" } }, { "cell_type": "markdown", "source": [ "จากผลลัพธ์ของโมเดล เราสามารถเห็นค่าสัมประสิทธิ์ที่ได้จากการฝึกฝน ซึ่งค่าสัมประสิทธิ์เหล่านี้แสดงถึงค่าของเส้นที่เหมาะสมที่สุดที่ช่วยลดข้อผิดพลาดโดยรวมระหว่างตัวแปรจริงและตัวแปรที่คาดการณ์\n", "\n", "
\n", "\n", "## 5. ทำนายผลบนชุดข้อมูลทดสอบ\n", "\n", "เมื่อเราได้ฝึกฝนโมเดลแล้ว เราสามารถใช้มันเพื่อทำนายการพัฒนาของโรค y สำหรับชุดข้อมูลทดสอบโดยใช้ [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html) ซึ่งจะถูกใช้เพื่อวาดเส้นแบ่งระหว่างกลุ่มข้อมูล\n" ], "metadata": { "id": "kGZ22RQj_Olu" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Make predictions for the test set\r\n", "predictions <- lm_mod %>% \r\n", " predict(new_data = diabetes_test)\r\n", "\r\n", "# Print out some of the predictions\r\n", "predictions %>% \r\n", " slice(1:5)" ], "outputs": [], "metadata": { "id": "nXHbY7M2_aao" } }, { "cell_type": "markdown", "source": [ "เย้! 💃🕺 เราเพิ่งฝึกโมเดลและใช้มันเพื่อทำการพยากรณ์!\n", "\n", "เมื่อทำการพยากรณ์ ตามธรรมเนียมของ tidymodels จะสร้างผลลัพธ์ในรูปแบบ tibble หรือ data frame ที่มีชื่อคอลัมน์มาตรฐานเสมอ วิธีนี้ช่วยให้สามารถรวมข้อมูลต้นฉบับและผลการพยากรณ์ในรูปแบบที่ใช้งานได้ง่ายสำหรับการดำเนินการต่อ เช่น การสร้างกราฟ\n", "\n", "`dplyr::bind_cols()` ช่วยรวมหลาย data frame เข้าด้วยกันอย่างมีประสิทธิภาพในรูปแบบคอลัมน์\n" ], "metadata": { "id": "R_JstwUY_bIs" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Combine the predictions and the original test set\r\n", "results <- diabetes_test %>% \r\n", " bind_cols(predictions)\r\n", "\r\n", "\r\n", "results %>% \r\n", " slice(1:5)" ], "outputs": [], "metadata": { "id": "RybsMJR7_iI8" } }, { "cell_type": "markdown", "source": [ "## 6. แสดงผลการสร้างโมเดล\n", "\n", "ถึงเวลาที่จะดูผลลัพธ์ในรูปแบบภาพแล้ว 📈 เราจะสร้างกราฟกระจายของค่าทั้งหมดใน `y` และ `bmi` จากชุดข้อมูลทดสอบ จากนั้นใช้ค่าที่คาดการณ์เพื่อวาดเส้นในตำแหน่งที่เหมาะสมที่สุด ระหว่างกลุ่มข้อมูลของโมเดล\n", "\n", "R มีระบบหลายแบบสำหรับการสร้างกราฟ แต่ `ggplot2` เป็นหนึ่งในระบบที่ดูเรียบง่ายและมีความหลากหลายมากที่สุด ระบบนี้ช่วยให้คุณสามารถสร้างกราฟโดย **การรวมองค์ประกอบที่เป็นอิสระเข้าด้วยกัน**\n" ], "metadata": { "id": "XJbYbMZW_n_s" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Set a theme for the plot\r\n", "theme_set(theme_light())\r\n", "# Create a scatter plot\r\n", "results %>% \r\n", " ggplot(aes(x = bmi)) +\r\n", " # Add a scatter plot\r\n", " geom_point(aes(y = y), size = 1.6) +\r\n", " # Add a line plot\r\n", " geom_line(aes(y = .pred), color = \"blue\", size = 1.5)" ], "outputs": [], "metadata": { "id": "R9tYp3VW_sTn" } }, { "cell_type": "markdown", "source": [ "✅ ลองคิดดูว่าเกิดอะไรขึ้นที่นี่ เส้นตรงเส้นหนึ่งกำลังผ่านจุดข้อมูลเล็กๆ หลายจุด แต่จริงๆ แล้วมันกำลังทำอะไรอยู่? คุณเห็นไหมว่าคุณควรจะสามารถใช้เส้นนี้เพื่อทำนายว่าจุดข้อมูลใหม่ที่ยังไม่เคยเห็นควรจะอยู่ตรงไหนในความสัมพันธ์กับแกน y ของกราฟ? ลองอธิบายเป็นคำพูดถึงการใช้งานจริงของโมเดลนี้\n", "\n", "ขอแสดงความยินดี! คุณสร้างโมเดลการถดถอยเชิงเส้นตัวแรกของคุณ สร้างการทำนายด้วยมัน และแสดงผลในกราฟ!\n" ], "metadata": { "id": "zrPtHIxx_tNI" } }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**ข้อจำกัดความรับผิดชอบ**: \nเอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษาจากผู้เชี่ยวชาญ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้\n" ] } ] }