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/th/2-Regression/3-Linear/solution/R/lesson_3-R.ipynb

1083 lines
67 KiB

{
"nbformat": 4,
"nbformat_minor": 2,
"metadata": {
"colab": {
"name": "lesson_3-R.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true
},
"kernelspec": {
"name": "ir",
"display_name": "R"
},
"language_info": {
"name": "R"
},
"coopTranslator": {
"original_hash": "5015d65d61ba75a223bfc56c273aa174",
"translation_date": "2025-09-06T13:23:02+00:00",
"source_file": "2-Regression/3-Linear/solution/R/lesson_3-R.ipynb",
"language_code": "th"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "EgQw8osnsUV-"
}
},
{
"cell_type": "markdown",
"source": [
"## การวิเคราะห์การถดถอยเชิงเส้นและพหุนามสำหรับการตั้งราคาฟักทอง - บทเรียนที่ 3\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>อินโฟกราฟิกโดย Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![อินโฟกราฟิกโดย Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n",
"\n",
"#### บทนำ\n",
"\n",
"จนถึงตอนนี้ คุณได้สำรวจว่าการถดถอยคืออะไรโดยใช้ข้อมูลตัวอย่างจากชุดข้อมูลการตั้งราคาฟักทองที่เราจะใช้ตลอดบทเรียนนี้ คุณยังได้สร้างภาพด้วย `ggplot2` 💪\n",
"\n",
"ตอนนี้คุณพร้อมที่จะเจาะลึกลงไปในเรื่องการถดถอยสำหรับการเรียนรู้ของเครื่อง (ML) ในบทเรียนนี้ คุณจะได้เรียนรู้เพิ่มเติมเกี่ยวกับการถดถอยสองประเภท: *การถดถอยเชิงเส้นพื้นฐาน* และ *การถดถอยพหุนาม* พร้อมกับคณิตศาสตร์บางส่วนที่อยู่เบื้องหลังเทคนิคเหล่านี้\n",
"\n",
"> ตลอดหลักสูตรนี้ เราสมมติว่าคุณมีความรู้ทางคณิตศาสตร์ในระดับพื้นฐาน และพยายามทำให้เนื้อหาเข้าถึงได้สำหรับนักเรียนที่มาจากสาขาอื่น ดังนั้นโปรดสังเกตหมายเหตุ 🧮 การเรียกออกมา แผนภาพ และเครื่องมือการเรียนรู้อื่น ๆ เพื่อช่วยในการทำความเข้าใจ\n",
"\n",
"#### การเตรียมตัว\n",
"\n",
"เพื่อเป็นการเตือนความจำ คุณกำลังโหลดข้อมูลนี้เพื่อถามคำถามเกี่ยวกับข้อมูลดังกล่าว\n",
"\n",
"- ช่วงเวลาใดที่ดีที่สุดในการซื้อฟักทอง?\n",
"\n",
"- ราคาที่คาดหวังสำหรับฟักทองขนาดเล็กหนึ่งกล่องคือเท่าไหร่?\n",
"\n",
"- ควรซื้อฟักทองในตะกร้าครึ่งบุชเชลหรือในกล่องขนาด 1 1/9 บุชเชล? มาลองเจาะลึกข้อมูลนี้กันต่อไป\n",
"\n",
"ในบทเรียนก่อนหน้านี้ คุณได้สร้าง `tibble` (การปรับปรุงใหม่ของ data frame) และเติมข้อมูลบางส่วนจากชุดข้อมูลต้นฉบับ โดยการปรับมาตรฐานราคาตามบุชเชล อย่างไรก็ตาม ด้วยวิธีนั้น คุณสามารถรวบรวมข้อมูลได้เพียงประมาณ 400 จุดข้อมูล และเฉพาะในช่วงฤดูใบไม้ร่วงเท่านั้น บางทีเราอาจได้รายละเอียดเพิ่มเติมเกี่ยวกับลักษณะของข้อมูลโดยการทำความสะอาดข้อมูลมากขึ้น? เราจะได้รู้กัน... 🕵️‍♀️\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",
"- `janitor`: [แพ็กเกจ janitor](https://github.com/sfirke/janitor) มีเครื่องมือเล็ก ๆ ที่เรียบง่ายสำหรับการตรวจสอบและทำความสะอาดข้อมูลที่สกปรก\n",
"\n",
"- `corrplot`: [แพ็กเกจ corrplot](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) เป็นเครื่องมือสำรวจภาพบนเมทริกซ์ความสัมพันธ์ที่สนับสนุนการจัดเรียงตัวแปรอัตโนมัติเพื่อช่วยตรวจจับรูปแบบที่ซ่อนอยู่ระหว่างตัวแปร\n",
"\n",
"คุณสามารถติดตั้งแพ็กเกจเหล่านี้ได้ด้วยคำสั่ง:\n",
"\n",
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"corrplot\"))`\n",
"\n",
"สคริปต์ด้านล่างจะตรวจสอบว่าคุณมีแพ็กเกจที่จำเป็นสำหรับการทำโมดูลนี้หรือไม่ และจะติดตั้งให้คุณในกรณีที่ยังไม่มี\n"
],
"metadata": {
"id": "WqQPS1OAsg3H"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"suppressWarnings(if (!require(\"pacman\")) install.packages(\"pacman\"))\n",
"\n",
"pacman::p_load(tidyverse, tidymodels, janitor, corrplot)"
],
"outputs": [],
"metadata": {
"id": "tA4C2WN3skCf",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "c06cd805-5534-4edc-f72b-d0d1dab96ac0"
}
},
{
"cell_type": "markdown",
"source": [
"เราจะโหลดแพ็กเกจที่ยอดเยี่ยมเหล่านี้และทำให้พร้อมใช้งานในเซสชัน R ปัจจุบันของเรา (นี่เป็นเพียงตัวอย่าง เพราะ `pacman::p_load()` ได้ทำสิ่งนี้ให้คุณแล้ว)\n",
"\n",
"## 1. เส้นการถดถอยเชิงเส้น\n",
"\n",
"ตามที่คุณได้เรียนรู้ในบทเรียนที่ 1 เป้าหมายของการถดถอยเชิงเส้นคือการสามารถวาด *เส้น* *ที่* *เหมาะสมที่สุด* เพื่อ:\n",
"\n",
"- **แสดงความสัมพันธ์ระหว่างตัวแปร** แสดงความสัมพันธ์ระหว่างตัวแปรต่าง ๆ\n",
"\n",
"- **ทำการพยากรณ์** ทำการพยากรณ์ที่แม่นยำเกี่ยวกับตำแหน่งที่จุดข้อมูลใหม่จะตกอยู่ในความสัมพันธ์กับเส้นนั้น\n",
"\n",
"ในการวาดเส้นประเภทนี้ เราใช้เทคนิคทางสถิติที่เรียกว่า **Least-Squares Regression** คำว่า `least-squares` หมายถึงการที่จุดข้อมูลทั้งหมดที่อยู่รอบเส้นการถดถอยถูกยกกำลังสองและนำมารวมกัน ผลรวมสุดท้ายควรมีค่าน้อยที่สุดเท่าที่จะเป็นไปได้ เพราะเราต้องการจำนวนข้อผิดพลาดที่ต่ำที่สุด หรือ `least-squares` ดังนั้น เส้นที่เหมาะสมที่สุดคือเส้นที่ให้ค่าผลรวมของข้อผิดพลาดที่ยกกำลังสองต่ำที่สุด - ซึ่งเป็นที่มาของชื่อ *least squares regression*\n",
"\n",
"เราทำเช่นนี้เพราะเราต้องการสร้างแบบจำลองเส้นที่มีระยะทางสะสมจากจุดข้อมูลทั้งหมดน้อยที่สุด นอกจากนี้ เรายังยกกำลังสองก่อนที่จะรวมกัน เพราะเราสนใจขนาดของมันมากกว่าทิศทาง\n",
"\n",
"> **🧮 แสดงคณิตศาสตร์ให้ฉันดู**\n",
">\n",
"> เส้นนี้ ซึ่งเรียกว่า *เส้นที่เหมาะสมที่สุด* สามารถแสดงได้ด้วย [สมการ](https://en.wikipedia.org/wiki/Simple_linear_regression):\n",
">\n",
"> Y = a + bX\n",
">\n",
"> `X` คือ '`ตัวแปรอธิบาย` หรือ `ตัวพยากรณ์`' ส่วน `Y` คือ '`ตัวแปรตาม` หรือ `ผลลัพธ์`' ความชันของเส้นคือ `b` และ `a` คือจุดตัดแกน y ซึ่งหมายถึงค่าของ `Y` เมื่อ `X = 0`\n",
">\n",
"\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/slope.png \"slope = $y/x$\")\n",
" อินโฟกราฟิกโดย Jen Looper\n",
">\n",
"> ขั้นแรก คำนวณความชัน `b`\n",
">\n",
"> กล่าวอีกนัยหนึ่ง และอ้างอิงถึงคำถามดั้งเดิมของข้อมูลฟักทองของเรา: \"พยากรณ์ราคาของฟักทองต่อบุชเชลตามเดือน\" `X` จะหมายถึงราคา และ `Y` จะหมายถึงเดือนที่ขาย\n",
">\n",
"> ![](../../../../../../2-Regression/3-Linear/solution/images/calculation.png)\n",
" อินโฟกราฟิกโดย Jen Looper\n",
"> \n",
"> คำนวณค่าของ Y ถ้าคุณจ่ายประมาณ \\$4 นั่นต้องเป็นเดือนเมษายน!\n",
">\n",
"> คณิตศาสตร์ที่คำนวณเส้นนี้ต้องแสดงความชันของเส้น ซึ่งยังขึ้นอยู่กับจุดตัดแกน หรือที่ที่ `Y` อยู่เมื่อ `X = 0`\n",
">\n",
"> คุณสามารถดูวิธีการคำนวณค่าสำหรับสิ่งเหล่านี้ได้ที่เว็บไซต์ [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html) และเยี่ยมชม [เครื่องคำนวณ Least-squares](https://www.mathsisfun.com/data/least-squares-calculator.html) เพื่อดูว่าค่าต่าง ๆ ส่งผลต่อเส้นอย่างไร\n",
"\n",
"ไม่น่ากลัวเท่าไหร่ใช่ไหม? 🤓\n",
"\n",
"#### ความสัมพันธ์\n",
"\n",
"อีกคำหนึ่งที่ควรเข้าใจคือ **ค่าสัมประสิทธิ์ความสัมพันธ์** ระหว่างตัวแปร X และ Y ที่กำหนด โดยใช้แผนภาพกระจาย (scatterplot) คุณสามารถมองเห็นค่าสัมประสิทธิ์นี้ได้อย่างรวดเร็ว แผนภาพที่มีจุดข้อมูลกระจายเป็นเส้นเรียบร้อยจะมีความสัมพันธ์สูง แต่แผนภาพที่มีจุดข้อมูลกระจายไปทั่วระหว่าง X และ Y จะมีความสัมพันธ์ต่ำ\n",
"\n",
"โมเดลการถดถอยเชิงเส้นที่ดีจะเป็นโมเดลที่มีค่าสัมประสิทธิ์ความสัมพันธ์สูง (ใกล้ 1 มากกว่า 0) โดยใช้วิธี Least-Squares Regression กับเส้นการถดถอย\n"
],
"metadata": {
"id": "cdX5FRpvsoP5"
}
},
{
"cell_type": "markdown",
"source": [
"## **2. การเต้นรำกับข้อมูล: สร้าง Data Frame สำหรับการสร้างโมเดล**\n",
"\n",
"<p >\n",
" <img src=\"../../images/janitor.jpg\"\n",
" width=\"700\"/>\n",
" <figcaption>ผลงานโดย @allison_horst</figcaption>\n",
"\n",
"\n",
"<!--![ผลงานโดย \\@allison_horst](../../../../../../2-Regression/3-Linear/images/janitor.jpg){width=\"700\"}-->\n"
],
"metadata": {
"id": "WdUKXk7Bs8-V"
}
},
{
"cell_type": "markdown",
"source": [
"โหลดไลบรารีและชุดข้อมูลที่จำเป็น จากนั้นแปลงข้อมูลให้เป็น Data Frame ที่มีเฉพาะส่วนย่อยของข้อมูล:\n",
"\n",
"- เลือกเฉพาะฟักทองที่มีการตั้งราคาเป็นหน่วยบุชเชล\n",
"\n",
"- แปลงวันที่ให้เป็นเดือน\n",
"\n",
"- คำนวณราคาให้เป็นค่าเฉลี่ยระหว่างราคาสูงสุดและราคาต่ำสุด\n",
"\n",
"- แปลงราคาให้สะท้อนถึงการตั้งราคาตามปริมาณในหน่วยบุชเชล\n",
"\n",
"> เราได้ครอบคลุมขั้นตอนเหล่านี้ใน [บทเรียนก่อนหน้า](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/2-Data/solution/lesson_2-R.ipynb)\n"
],
"metadata": {
"id": "fMCtu2G2s-p8"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the core Tidyverse packages\n",
"library(tidyverse)\n",
"library(lubridate)\n",
"\n",
"# Import the pumpkins data\n",
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\")\n",
"\n",
"\n",
"# Get a glimpse and dimensions of the data\n",
"glimpse(pumpkins)\n",
"\n",
"\n",
"# Print the first 50 rows of the data set\n",
"pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "ryMVZEEPtERn"
}
},
{
"cell_type": "markdown",
"source": [
"ด้วยจิตวิญญาณแห่งการผจญภัย ลองมาสำรวจ [`janitor package`](../../../../../../2-Regression/3-Linear/solution/R/github.com/sfirke/janitor) ที่มีฟังก์ชันง่ายๆ สำหรับตรวจสอบและทำความสะอาดข้อมูลที่ยุ่งเหยิงกัน ตัวอย่างเช่น ลองมาดูชื่อคอลัมน์ของข้อมูลของเรากัน:\n"
],
"metadata": {
"id": "xcNxM70EtJjb"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Return column names\n",
"pumpkins %>% \n",
" names()"
],
"outputs": [],
"metadata": {
"id": "5XtpaIigtPfW"
}
},
{
"cell_type": "markdown",
"source": [
"🤔 เราสามารถทำได้ดีกว่านี้ มาทำให้ชื่อคอลัมน์เหล่านี้เป็น `friendR` โดยการแปลงให้เป็นรูปแบบ [snake_case](https://en.wikipedia.org/wiki/Snake_case) ด้วยการใช้ `janitor::clean_names` หากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันนี้: `?clean_names`\n"
],
"metadata": {
"id": "IbIqrMINtSHe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Clean names to the snake_case convention\n",
"pumpkins <- pumpkins %>% \n",
" clean_names(case = \"snake\")\n",
"\n",
"# Return column names\n",
"pumpkins %>% \n",
" names()"
],
"outputs": [],
"metadata": {
"id": "a2uYvclYtWvX"
}
},
{
"cell_type": "markdown",
"source": [
"ช่างเป็น tidyR 🧹! ตอนนี้ มาลองเต้นรำกับข้อมูลโดยใช้ `dplyr` เหมือนในบทเรียนก่อนหน้านี้! 💃\n"
],
"metadata": {
"id": "HfhnuzDDtaDd"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select desired columns\n",
"pumpkins <- pumpkins %>% \n",
" select(variety, city_name, package, low_price, high_price, date)\n",
"\n",
"\n",
"\n",
"# Extract the month from the dates to a new column\n",
"pumpkins <- pumpkins %>%\n",
" mutate(date = mdy(date),\n",
" month = month(date)) %>% \n",
" select(-date)\n",
"\n",
"\n",
"\n",
"# Create a new column for average Price\n",
"pumpkins <- pumpkins %>% \n",
" mutate(price = (low_price + high_price)/2)\n",
"\n",
"\n",
"# Retain only pumpkins with the string \"bushel\"\n",
"new_pumpkins <- pumpkins %>% \n",
" filter(str_detect(string = package, pattern = \"bushel\"))\n",
"\n",
"\n",
"# Normalize the pricing so that you show the pricing per bushel, not per 1 1/9 or 1/2 bushel\n",
"new_pumpkins <- new_pumpkins %>% \n",
" mutate(price = case_when(\n",
" str_detect(package, \"1 1/9\") ~ price/(1.1),\n",
" str_detect(package, \"1/2\") ~ price*2,\n",
" TRUE ~ price))\n",
"\n",
"# Relocate column positions\n",
"new_pumpkins <- new_pumpkins %>% \n",
" relocate(month, .before = variety)\n",
"\n",
"\n",
"# Display the first 5 rows\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "X0wU3gQvtd9f"
}
},
{
"cell_type": "markdown",
"source": [
"เยี่ยมมาก!👌 ตอนนี้คุณมีชุดข้อมูลที่สะอาดและเป็นระเบียบเรียบร้อย พร้อมสำหรับการสร้างโมเดลการถดถอยใหม่ของคุณแล้ว!\n",
"\n",
"สนใจกราฟกระจายไหม?\n"
],
"metadata": {
"id": "UpaIwaxqth82"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set theme\n",
"theme_set(theme_light())\n",
"\n",
"# Make a scatter plot of month and price\n",
"new_pumpkins %>% \n",
" ggplot(mapping = aes(x = month, y = price)) +\n",
" geom_point(size = 1.6)\n"
],
"outputs": [],
"metadata": {
"id": "DXgU-j37tl5K"
}
},
{
"cell_type": "markdown",
"source": [
"แผนภาพกระจายช่วยเตือนเราว่าเรามีข้อมูลรายเดือนเพียงตั้งแต่เดือนสิงหาคมถึงเดือนธันวาคมเท่านั้น เราอาจต้องการข้อมูลเพิ่มเติมเพื่อที่จะสามารถสรุปผลในลักษณะเชิงเส้นได้\n",
"\n",
"ลองกลับมาดูข้อมูลการสร้างแบบจำลองของเราอีกครั้ง:\n"
],
"metadata": {
"id": "Ve64wVbwtobI"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Display first 5 rows\n",
"new_pumpkins %>% \n",
" slice_head(n = 5)"
],
"outputs": [],
"metadata": {
"id": "HFQX2ng1tuSJ"
}
},
{
"cell_type": "markdown",
"source": [
"ถ้าเราต้องการทำนาย `price` ของฟักทองโดยใช้คอลัมน์ `city` หรือ `package` ซึ่งเป็นข้อมูลประเภทตัวอักษรล่ะ? หรือถ้าจะง่ายกว่านั้น เราจะหาความสัมพันธ์ (ซึ่งต้องใช้ข้อมูลทั้งสองเป็นตัวเลข) ระหว่าง `package` กับ `price` ได้อย่างไร? 🤷🤷\n",
"\n",
"โมเดลการเรียนรู้ของเครื่องทำงานได้ดีที่สุดเมื่อใช้คุณลักษณะเป็นตัวเลขแทนที่จะเป็นค่าข้อความ ดังนั้นโดยทั่วไปคุณจำเป็นต้องแปลงคุณลักษณะเชิงหมวดหมู่ให้เป็นตัวแทนในรูปแบบตัวเลข\n",
"\n",
"นั่นหมายความว่าเราต้องหาวิธีปรับรูปแบบตัวทำนายของเราให้ใช้งานได้ง่ายขึ้นสำหรับโมเดล ซึ่งกระบวนการนี้เรียกว่า `feature engineering`\n"
],
"metadata": {
"id": "7hsHoxsStyjJ"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. การเตรียมข้อมูลสำหรับการสร้างโมเดลด้วย recipes 👩‍🍳👨‍🍳\n",
"\n",
"กิจกรรมที่ปรับเปลี่ยนค่าของตัวแปรพยากรณ์เพื่อให้โมเดลใช้งานได้อย่างมีประสิทธิภาพมากขึ้น เรียกว่า `feature engineering`\n",
"\n",
"โมเดลแต่ละแบบมีความต้องการการเตรียมข้อมูลที่แตกต่างกัน ตัวอย่างเช่น least squares ต้องการ `การเข้ารหัสตัวแปรเชิงหมวดหมู่` เช่น เดือน, ชนิด และ city_name ซึ่งกระบวนการนี้เกี่ยวข้องกับ `การแปลง` คอลัมน์ที่มี `ค่าหมวดหมู่` ให้กลายเป็นหนึ่งหรือมากกว่า `คอลัมน์ตัวเลข` ที่มาแทนที่คอลัมน์เดิม\n",
"\n",
"ตัวอย่างเช่น สมมติว่าข้อมูลของคุณมีตัวแปรเชิงหมวดหมู่ดังนี้:\n",
"\n",
"| city |\n",
"|:-------:|\n",
"| Denver |\n",
"| Nairobi |\n",
"| Tokyo |\n",
"\n",
"คุณสามารถใช้ *ordinal encoding* เพื่อแทนค่าหมวดหมู่แต่ละค่าเป็นตัวเลขจำนวนเต็มที่ไม่ซ้ำกัน เช่นนี้:\n",
"\n",
"| city |\n",
"|:----:|\n",
"| 0 |\n",
"| 1 |\n",
"| 2 |\n",
"\n",
"และนี่คือสิ่งที่เราจะทำกับข้อมูลของเรา!\n",
"\n",
"ในส่วนนี้ เราจะสำรวจแพ็กเกจ Tidymodels ที่น่าทึ่งอีกตัวหนึ่ง: [recipes](https://tidymodels.github.io/recipes/) - ซึ่งถูกออกแบบมาเพื่อช่วยคุณเตรียมข้อมูลของคุณ **ก่อน** การฝึกโมเดล โดยพื้นฐานแล้ว recipe คือออบเจ็กต์ที่กำหนดว่าควรมีขั้นตอนใดบ้างที่ต้องนำไปใช้กับชุดข้อมูลเพื่อเตรียมให้พร้อมสำหรับการสร้างโมเดล\n",
"\n",
"ตอนนี้ เรามาสร้าง recipe ที่เตรียมข้อมูลของเราสำหรับการสร้างโมเดลโดยการแทนค่าจำนวนเต็มที่ไม่ซ้ำกันให้กับทุกค่าที่พบในคอลัมน์ตัวแปรพยากรณ์:\n"
],
"metadata": {
"id": "AD5kQbcvt3Xl"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Specify a recipe\n",
"pumpkins_recipe <- recipe(price ~ ., data = new_pumpkins) %>% \n",
" step_integer(all_predictors(), zero_based = TRUE)\n",
"\n",
"\n",
"# Print out the recipe\n",
"pumpkins_recipe"
],
"outputs": [],
"metadata": {
"id": "BNaFKXfRt9TU"
}
},
{
"cell_type": "markdown",
"source": [
"เยี่ยมมาก! 👏 เราเพิ่งสร้างสูตรแรกที่กำหนดผลลัพธ์ (ราคา) และตัวทำนายที่เกี่ยวข้อง พร้อมทั้งกำหนดให้คอลัมน์ตัวทำนายทั้งหมดถูกแปลงเป็นชุดของตัวเลขจำนวนเต็ม 🙌! มาดูรายละเอียดกันอย่างรวดเร็ว:\n",
"\n",
"- การเรียกใช้ `recipe()` พร้อมสูตรจะบอกสูตรเกี่ยวกับ *บทบาท* ของตัวแปร โดยใช้ข้อมูล `new_pumpkins` เป็นข้อมูลอ้างอิง ตัวอย่างเช่น คอลัมน์ `price` ถูกกำหนดให้มีบทบาทเป็น `outcome` ในขณะที่คอลัมน์อื่น ๆ ถูกกำหนดให้มีบทบาทเป็น `predictor`\n",
"\n",
"- `step_integer(all_predictors(), zero_based = TRUE)` ระบุว่าตัวทำนายทั้งหมดควรถูกแปลงเป็นชุดของตัวเลขจำนวนเต็ม โดยเริ่มต้นการนับที่ 0\n",
"\n",
"เราเชื่อว่าคุณอาจกำลังคิดว่า: \"นี่มันเจ๋งมาก!! แต่ถ้าฉันต้องการยืนยันว่าสูตรกำลังทำงานตามที่ฉันคาดหวังจริง ๆ ล่ะ? 🤔\"\n",
"\n",
"นั่นเป็นความคิดที่ยอดเยี่ยม! คุณเห็นไหมว่า เมื่อสูตรของคุณถูกกำหนดแล้ว คุณสามารถประมาณค่าพารามิเตอร์ที่จำเป็นสำหรับการเตรียมข้อมูล และจากนั้นดึงข้อมูลที่ผ่านการประมวลผลออกมาได้ โดยปกติคุณไม่จำเป็นต้องทำเช่นนี้เมื่อใช้ Tidymodels (เราจะเห็นวิธีการทั่วไปในอีกสักครู่-\\> `workflows`) แต่สิ่งนี้อาจมีประโยชน์เมื่อคุณต้องการตรวจสอบความถูกต้องเพื่อยืนยันว่าสูตรกำลังทำงานตามที่คุณคาดหวัง\n",
"\n",
"สำหรับสิ่งนี้ คุณจะต้องใช้คำกริยาอีกสองคำ: `prep()` และ `bake()` และเช่นเคย เพื่อนตัวน้อยใน R ของเราโดย [`Allison Horst`](https://github.com/allisonhorst/stats-illustrations) จะช่วยให้คุณเข้าใจสิ่งนี้ได้ดียิ่งขึ้น!\n",
"\n",
"<p >\n",
" <img src=\"../../images/recipes.png\"\n",
" width=\"550\"/>\n",
" <figcaption>ภาพวาดโดย @allison_horst</figcaption>\n"
],
"metadata": {
"id": "KEiO0v7kuC9O"
}
},
{
"cell_type": "markdown",
"source": [
"[`prep()`](https://recipes.tidymodels.org/reference/prep.html): ประเมินค่าพารามิเตอร์ที่จำเป็นจากชุดข้อมูลการฝึกอบรม ซึ่งสามารถนำไปใช้กับชุดข้อมูลอื่นในภายหลังได้ ตัวอย่างเช่น สำหรับคอลัมน์ตัวทำนายที่กำหนด จะมีการกำหนดค่าการสังเกตเป็นเลขจำนวนเต็ม 0 หรือ 1 หรือ 2 เป็นต้น\n",
"\n",
"[`bake()`](https://recipes.tidymodels.org/reference/bake.html): ใช้สูตรที่เตรียมไว้แล้วและดำเนินการกับชุดข้อมูลใดๆ\n",
"\n",
"เมื่อกล่าวเช่นนี้ เรามาเตรียมและดำเนินการสูตรของเราเพื่อยืนยันจริงๆ ว่าเบื้องหลังนั้น คอลัมน์ตัวทำนายจะถูกเข้ารหัสก่อนที่จะนำไปปรับใช้กับโมเดล\n"
],
"metadata": {
"id": "Q1xtzebuuTCP"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Prep the recipe\n",
"pumpkins_prep <- prep(pumpkins_recipe)\n",
"\n",
"# Bake the recipe to extract a preprocessed new_pumpkins data\n",
"baked_pumpkins <- bake(pumpkins_prep, new_data = NULL)\n",
"\n",
"# Print out the baked data set\n",
"baked_pumpkins %>% \n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "FGBbJbP_uUUn"
}
},
{
"cell_type": "markdown",
"source": [
"เยี่ยมไปเลย! 🥳 ข้อมูลที่ผ่านการประมวลผล `baked_pumpkins` มีตัวแปรทำนายทั้งหมดที่ถูกเข้ารหัสแล้ว ซึ่งยืนยันว่าขั้นตอนการเตรียมข้อมูลที่เรากำหนดไว้ในสูตรนั้นทำงานได้ตามที่คาดหวัง แม้ว่ามันอาจจะทำให้คุณอ่านยากขึ้น แต่ก็ทำให้ Tidymodels เข้าใจข้อมูลได้ง่ายขึ้น ลองใช้เวลาสักครู่เพื่อดูว่าแต่ละข้อมูลถูกแปลงเป็นตัวเลขใดบ้าง\n",
"\n",
"นอกจากนี้ยังควรกล่าวถึงว่า `baked_pumpkins` เป็น data frame ที่เราสามารถทำการคำนวณต่าง ๆ ได้\n",
"\n",
"ตัวอย่างเช่น ลองหาความสัมพันธ์ที่ดีระหว่างสองจุดในข้อมูลของคุณเพื่อสร้างโมเดลทำนายที่มีประสิทธิภาพ เราจะใช้ฟังก์ชัน `cor()` เพื่อทำสิ่งนี้ พิมพ์ `?cor()` เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันนี้\n"
],
"metadata": {
"id": "1dvP0LBUueAW"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Find the correlation between the city_name and the price\n",
"cor(baked_pumpkins$city_name, baked_pumpkins$price)\n",
"\n",
"# Find the correlation between the package and the price\n",
"cor(baked_pumpkins$package, baked_pumpkins$price)\n"
],
"outputs": [],
"metadata": {
"id": "3bQzXCjFuiSV"
}
},
{
"cell_type": "markdown",
"source": [
"ปรากฏว่าความสัมพันธ์ระหว่างเมืองและราคานั้นค่อนข้างอ่อนแอ อย่างไรก็ตาม มีความสัมพันธ์ที่ดีกว่าระหว่างแพ็คเกจและราคา ซึ่งก็สมเหตุสมผลใช่ไหม? โดยปกติแล้ว กล่องสินค้ายิ่งใหญ่ ราคาก็ยิ่งสูงขึ้น\n",
"\n",
"ในขณะเดียวกัน เรามาลองสร้างภาพเมทริกซ์ความสัมพันธ์ของทุกคอลัมน์โดยใช้แพ็คเกจ `corrplot` กันเถอะ\n"
],
"metadata": {
"id": "BToPWbgjuoZw"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Load the corrplot package\n",
"library(corrplot)\n",
"\n",
"# Obtain correlation matrix\n",
"corr_mat <- cor(baked_pumpkins %>% \n",
" # Drop columns that are not really informative\n",
" select(-c(low_price, high_price)))\n",
"\n",
"# Make a correlation plot between the variables\n",
"corrplot(corr_mat, method = \"shade\", shade.col = NA, tl.col = \"black\", tl.srt = 45, addCoef.col = \"black\", cl.pos = \"n\", order = \"original\")"
],
"outputs": [],
"metadata": {
"id": "ZwAL3ksmutVR"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩 ดีขึ้นมาก\n",
"\n",
"คำถามที่ดีที่ควรถามเกี่ยวกับข้อมูลนี้คือ: '`ราคาที่คาดหวังสำหรับแพ็คเกจฟักทองคือเท่าไหร่?`' มาเริ่มกันเลย!\n",
"\n",
"> หมายเหตุ: เมื่อคุณ **`bake()`** สูตรที่เตรียมไว้ **`pumpkins_prep`** โดยใช้ **`new_data = NULL`** คุณจะได้ข้อมูลการฝึกที่ผ่านการประมวลผล (เช่น การเข้ารหัส) หากคุณมีชุดข้อมูลอื่น เช่น ชุดทดสอบ และต้องการดูว่าสูตรจะประมวลผลอย่างไร คุณเพียงแค่ bake **`pumpkins_prep`** โดยใช้ **`new_data = test_set`**\n",
"\n",
"## 4. สร้างโมเดลการถดถอยเชิงเส้น\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>อินโฟกราฟิกโดย Dasani Madipalli</figcaption>\n"
],
"metadata": {
"id": "YqXjLuWavNxW"
}
},
{
"cell_type": "markdown",
"source": [
"ตอนนี้ที่เราได้สร้างสูตรและยืนยันแล้วว่าข้อมูลจะถูกประมวลผลล่วงหน้าอย่างเหมาะสม มาสร้างโมเดลการถดถอยเพื่อหาคำตอบสำหรับคำถามนี้กัน: `ราคาที่คาดหวังของแพ็คเกจฟักทองที่กำหนดคือเท่าไร?`\n",
"\n",
"#### ฝึกโมเดลการถดถอยเชิงเส้นโดยใช้ชุดข้อมูลการฝึก\n",
"\n",
"คุณอาจสังเกตเห็นแล้วว่า คอลัมน์ *price* คือ `ตัวแปรผลลัพธ์` ในขณะที่คอลัมน์ *package* คือ `ตัวแปรพยากรณ์`\n",
"\n",
"เพื่อทำสิ่งนี้ เราจะเริ่มต้นด้วยการแบ่งข้อมูล โดยให้ 80% เป็นชุดข้อมูลการฝึก และ 20% เป็นชุดข้อมูลทดสอบ จากนั้นกำหนดสูตรที่จะเข้ารหัสคอลัมน์ตัวแปรพยากรณ์ให้เป็นชุดของตัวเลข และสร้างสเปคของโมเดล เราจะไม่เตรียมและอบสูตรของเราอีกครั้ง เพราะเรารู้อยู่แล้วว่ามันจะประมวลผลข้อมูลได้ตามที่คาดไว้\n"
],
"metadata": {
"id": "Pq0bSzCevW-h"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"set.seed(2056)\n",
"# Split the data into training and test sets\n",
"pumpkins_split <- new_pumpkins %>% \n",
" initial_split(prop = 0.8)\n",
"\n",
"\n",
"# Extract training and test data\n",
"pumpkins_train <- training(pumpkins_split)\n",
"pumpkins_test <- testing(pumpkins_split)\n",
"\n",
"\n",
"\n",
"# Create a recipe for preprocessing the data\n",
"lm_pumpkins_recipe <- recipe(price ~ package, data = pumpkins_train) %>% \n",
" step_integer(all_predictors(), zero_based = TRUE)\n",
"\n",
"\n",
"\n",
"# Create a linear model specification\n",
"lm_spec <- linear_reg() %>% \n",
" set_engine(\"lm\") %>% \n",
" set_mode(\"regression\")"
],
"outputs": [],
"metadata": {
"id": "CyoEh_wuvcLv"
}
},
{
"cell_type": "markdown",
"source": [
"เยี่ยมมาก! ตอนนี้เรามีสูตรและสเปคของโมเดลแล้ว เราต้องหาวิธีรวมสิ่งเหล่านี้เข้าด้วยกันเป็นวัตถุที่สามารถทำการเตรียมข้อมูล (prep+bake เบื้องหลัง) ฝึกโมเดลบนข้อมูลที่ผ่านการเตรียมแล้ว และยังรองรับกิจกรรมหลังการประมวลผลได้อีกด้วย แบบนี้ช่วยให้คุณสบายใจขึ้นใช่ไหม!🤩\n",
"\n",
"ใน Tidymodels วัตถุที่สะดวกนี้เรียกว่า [`workflow`](https://workflows.tidymodels.org/) ซึ่งช่วยจัดการองค์ประกอบการสร้างโมเดลของคุณได้อย่างสะดวก! สิ่งนี้คือสิ่งที่เราเรียกว่า *pipelines* ใน *Python* นั่นเอง\n",
"\n",
"ดังนั้น มาเริ่มรวมทุกอย่างเข้าด้วยกันใน workflow กันเถอะ!📦\n"
],
"metadata": {
"id": "G3zF_3DqviFJ"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Hold modelling components in a workflow\n",
"lm_wf <- workflow() %>% \n",
" add_recipe(lm_pumpkins_recipe) %>% \n",
" add_model(lm_spec)\n",
"\n",
"# Print out the workflow\n",
"lm_wf"
],
"outputs": [],
"metadata": {
"id": "T3olroU3v-WX"
}
},
{
"cell_type": "markdown",
"source": [
"นอกจากนี้ เวิร์กโฟลว์ยังสามารถปรับแต่ง/ฝึกฝนได้ในลักษณะเดียวกับที่โมเดลสามารถทำได้\n"
],
"metadata": {
"id": "zd1A5tgOwEPX"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Train the model\n",
"lm_wf_fit <- lm_wf %>% \n",
" fit(data = pumpkins_train)\n",
"\n",
"# Print the model coefficients learned \n",
"lm_wf_fit"
],
"outputs": [],
"metadata": {
"id": "NhJagFumwFHf"
}
},
{
"cell_type": "markdown",
"source": [
"จากผลลัพธ์ของโมเดล เราสามารถเห็นค่าสัมประสิทธิ์ที่ได้จากการฝึกฝน ซึ่งค่าสัมประสิทธิ์เหล่านี้แสดงถึงค่าของเส้นที่เหมาะสมที่สุดที่ช่วยลดข้อผิดพลาดโดยรวมระหว่างค่าจริงและค่าที่โมเดลทำนายได้\n",
"\n",
"#### ประเมินประสิทธิภาพของโมเดลด้วยชุดข้อมูลทดสอบ\n",
"\n",
"ถึงเวลาตรวจสอบว่าโมเดลทำงานได้ดีแค่ไหน 📏! เราจะทำอย่างไร?\n",
"\n",
"เมื่อเราได้ฝึกฝนโมเดลแล้ว เราสามารถใช้โมเดลนี้เพื่อทำนายค่าจาก `test_set` โดยใช้ `parsnip::predict()` จากนั้นเราสามารถเปรียบเทียบค่าที่ทำนายได้กับค่าป้ายกำกับจริงเพื่อประเมินว่าโมเดลทำงานได้ดีหรือไม่ดีเพียงใด\n",
"\n",
"เริ่มต้นด้วยการทำนายค่าจากชุดข้อมูลทดสอบ แล้วรวมคอลัมน์เข้ากับชุดข้อมูลทดสอบ\n"
],
"metadata": {
"id": "_4QkGtBTwItF"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make predictions for the test set\n",
"predictions <- lm_wf_fit %>% \n",
" predict(new_data = pumpkins_test)\n",
"\n",
"\n",
"# Bind predictions to the test set\n",
"lm_results <- pumpkins_test %>% \n",
" select(c(package, price)) %>% \n",
" bind_cols(predictions)\n",
"\n",
"\n",
"# Print the first ten rows of the tibble\n",
"lm_results %>% \n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "UFZzTG0gwTs9"
}
},
{
"cell_type": "markdown",
"source": [
"คุณเพิ่งฝึกโมเดลและใช้มันเพื่อทำการพยากรณ์!🔮 มันดีแค่ไหน? มาประเมินประสิทธิภาพของโมเดลกันเถอะ!\n",
"\n",
"ใน Tidymodels เราทำสิ่งนี้โดยใช้ `yardstick::metrics()`! สำหรับการวิเคราะห์การถดถอยเชิงเส้น (linear regression) เรามุ่งเน้นไปที่ตัวชี้วัดต่อไปนี้:\n",
"\n",
"- `Root Mean Square Error (RMSE)`: รากที่สองของ [MSE](https://en.wikipedia.org/wiki/Mean_squared_error) ซึ่งให้ค่าตัวชี้วัดแบบสัมบูรณ์ในหน่วยเดียวกับป้ายกำกับ (ในกรณีนี้คือราคาของฟักทอง) ค่ายิ่งเล็กยิ่งดีสำหรับโมเดล (ในความหมายง่ายๆ มันแสดงถึงราคาที่การพยากรณ์ผิดพลาดโดยเฉลี่ย!)\n",
"\n",
"- `Coefficient of Determination (มักเรียกว่า R-squared หรือ R2)`: ตัวชี้วัดแบบสัมพัทธ์ที่ค่ายิ่งสูงยิ่งดีสำหรับการปรับให้เข้ากับโมเดล โดยพื้นฐานแล้ว ตัวชี้วัดนี้แสดงถึงว่าระดับความแปรปรวนระหว่างค่าที่พยากรณ์และค่าจริงที่โมเดลสามารถอธิบายได้มากน้อยเพียงใด\n"
],
"metadata": {
"id": "0A5MjzM7wW9M"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Evaluate performance of linear regression\n",
"metrics(data = lm_results,\n",
" truth = price,\n",
" estimate = .pred)"
],
"outputs": [],
"metadata": {
"id": "reJ0UIhQwcEH"
}
},
{
"cell_type": "markdown",
"source": [
"ประสิทธิภาพของโมเดลลดลงไปแล้ว ลองมาดูกันว่าเราจะได้ข้อมูลที่ชัดเจนขึ้นหรือไม่โดยการสร้างกราฟกระจายของแพ็กเกจและราคา แล้วใช้การคาดการณ์ที่ได้มาวางเส้นแนวโน้มที่เหมาะสมที่สุดลงไป\n",
"\n",
"นั่นหมายความว่าเราจะต้องเตรียมและประมวลผลชุดทดสอบเพื่อเข้ารหัสคอลัมน์แพ็กเกจ จากนั้นจึงรวมข้อมูลนี้เข้ากับการคาดการณ์ที่โมเดลของเราสร้างขึ้น\n"
],
"metadata": {
"id": "fdgjzjkBwfWt"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Encode package column\n",
"package_encode <- lm_pumpkins_recipe %>% \n",
" prep() %>% \n",
" bake(new_data = pumpkins_test) %>% \n",
" select(package)\n",
"\n",
"\n",
"# Bind encoded package column to the results\n",
"lm_results <- lm_results %>% \n",
" bind_cols(package_encode %>% \n",
" rename(package_integer = package)) %>% \n",
" relocate(package_integer, .after = package)\n",
"\n",
"\n",
"# Print new results data frame\n",
"lm_results %>% \n",
" slice_head(n = 5)\n",
"\n",
"\n",
"# Make a scatter plot\n",
"lm_results %>% \n",
" ggplot(mapping = aes(x = package_integer, y = price)) +\n",
" geom_point(size = 1.6) +\n",
" # Overlay a line of best fit\n",
" geom_line(aes(y = .pred), color = \"orange\", size = 1.2) +\n",
" xlab(\"package\")\n",
" \n"
],
"outputs": [],
"metadata": {
"id": "R0nw719lwkHE"
}
},
{
"cell_type": "markdown",
"source": [
"ยอดเยี่ยม! ดังที่คุณเห็น โมเดลการถดถอยเชิงเส้นไม่ได้ทำงานได้ดีนักในการสรุปความสัมพันธ์ระหว่างแพ็กเกจกับราคาที่เกี่ยวข้อง\n",
"\n",
"🎃 ขอแสดงความยินดี คุณเพิ่งสร้างโมเดลที่สามารถช่วยทำนายราคาของฟักทองหลากหลายชนิดได้ แปลงฟักทองสำหรับวันหยุดของคุณจะสวยงาม แต่คุณอาจสร้างโมเดลที่ดีกว่านี้ได้!\n",
"\n",
"## 5. สร้างโมเดลการถดถอยเชิงพหุนาม\n",
"\n",
"<p >\n",
" <img src=\"../../images/linear-polynomial.png\"\n",
" width=\"800\"/>\n",
" <figcaption>อินโฟกราฟิกโดย Dasani Madipalli</figcaption>\n",
"\n",
"\n",
"<!--![อินโฟกราฟิกโดย Dasani Madipalli](../../../../../../2-Regression/3-Linear/images/linear-polynomial.png){width=\"800\"}-->\n"
],
"metadata": {
"id": "HOCqJXLTwtWI"
}
},
{
"cell_type": "markdown",
"source": [
"บางครั้งข้อมูลของเราอาจไม่มีความสัมพันธ์แบบเชิงเส้นตรง แต่เรายังคงต้องการทำนายผลลัพธ์ การใช้การถดถอยพหุนาม (Polynomial Regression) สามารถช่วยให้เราทำนายความสัมพันธ์ที่ซับซ้อนและไม่เป็นเชิงเส้นได้\n",
"\n",
"ลองพิจารณาความสัมพันธ์ระหว่างขนาดของแพ็กเกจกับราคาของชุดข้อมูลฟักทองของเรา แม้ว่าบางครั้งจะมีความสัมพันธ์แบบเชิงเส้นตรงระหว่างตัวแปร เช่น ฟักทองที่มีปริมาตรมากขึ้นมักจะมีราคาสูงขึ้น แต่บางครั้งความสัมพันธ์เหล่านี้ไม่สามารถแสดงออกมาในรูปแบบระนาบหรือเส้นตรงได้\n",
"\n",
"> ✅ นี่คือตัวอย่างเพิ่มเติม [บางตัวอย่าง](https://online.stat.psu.edu/stat501/lesson/9/9.8) ของข้อมูลที่อาจใช้การถดถอยพหุนาม\n",
">\n",
"> ลองพิจารณาความสัมพันธ์ระหว่างชนิดของฟักทอง (Variety) กับราคาในกราฟก่อนหน้านี้อีกครั้ง คุณคิดว่ากราฟกระจายนี้ควรวิเคราะห์ด้วยเส้นตรงหรือไม่? อาจจะไม่ ในกรณีนี้ คุณสามารถลองใช้การถดถอยพหุนามได้\n",
">\n",
"> ✅ พหุนาม (Polynomial) คือการแสดงออกทางคณิตศาสตร์ที่อาจประกอบด้วยตัวแปรและสัมประสิทธิ์หนึ่งตัวหรือมากกว่า\n",
"\n",
"#### ฝึกโมเดลการถดถอยพหุนามโดยใช้ชุดข้อมูลการฝึก\n",
"\n",
"การถดถอยพหุนามจะสร้าง *เส้นโค้ง* เพื่อให้เหมาะสมกับข้อมูลที่ไม่เป็นเชิงเส้นมากขึ้น\n",
"\n",
"มาดูกันว่าโมเดลพหุนามจะทำงานได้ดีกว่าในการทำนายหรือไม่ เราจะทำตามขั้นตอนที่คล้ายกับที่เราเคยทำมาก่อนหน้านี้:\n",
"\n",
"- สร้างสูตร (recipe) ที่ระบุขั้นตอนการเตรียมข้อมูลที่ควรดำเนินการเพื่อให้ข้อมูลพร้อมสำหรับการสร้างโมเดล เช่น การเข้ารหัสตัวทำนาย (predictors) และการคำนวณพหุนามของระดับ *n*\n",
"\n",
"- สร้างสเปคของโมเดล (model specification)\n",
"\n",
"- รวมสูตรและสเปคของโมเดลเข้าด้วยกันในเวิร์กโฟลว์ (workflow)\n",
"\n",
"- สร้างโมเดลโดยการปรับเวิร์กโฟลว์\n",
"\n",
"- ประเมินว่าโมเดลทำงานได้ดีเพียงใดกับข้อมูลทดสอบ\n",
"\n",
"มาเริ่มกันเลย!\n"
],
"metadata": {
"id": "VcEIpRV9wzYr"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Specify a recipe\r\n",
"poly_pumpkins_recipe <-\r\n",
" recipe(price ~ package, data = pumpkins_train) %>%\r\n",
" step_integer(all_predictors(), zero_based = TRUE) %>% \r\n",
" step_poly(all_predictors(), degree = 4)\r\n",
"\r\n",
"\r\n",
"# Create a model specification\r\n",
"poly_spec <- linear_reg() %>% \r\n",
" set_engine(\"lm\") %>% \r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Bundle recipe and model spec into a workflow\r\n",
"poly_wf <- workflow() %>% \r\n",
" add_recipe(poly_pumpkins_recipe) %>% \r\n",
" add_model(poly_spec)\r\n",
"\r\n",
"\r\n",
"# Create a model\r\n",
"poly_wf_fit <- poly_wf %>% \r\n",
" fit(data = pumpkins_train)\r\n",
"\r\n",
"\r\n",
"# Print learned model coefficients\r\n",
"poly_wf_fit\r\n",
"\r\n",
" "
],
"outputs": [],
"metadata": {
"id": "63n_YyRXw3CC"
}
},
{
"cell_type": "markdown",
"source": [
"#### ประเมินประสิทธิภาพของโมเดล\n",
"\n",
"👏👏คุณได้สร้างโมเดลพหุนามเสร็จเรียบร้อยแล้ว มาลองทำการพยากรณ์บนชุดทดสอบกันเถอะ!\n"
],
"metadata": {
"id": "-LHZtztSxDP0"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make price predictions on test data\r\n",
"poly_results <- poly_wf_fit %>% predict(new_data = pumpkins_test) %>% \r\n",
" bind_cols(pumpkins_test %>% select(c(package, price))) %>% \r\n",
" relocate(.pred, .after = last_col())\r\n",
"\r\n",
"\r\n",
"# Print the results\r\n",
"poly_results %>% \r\n",
" slice_head(n = 10)"
],
"outputs": [],
"metadata": {
"id": "YUFpQ_dKxJGx"
}
},
{
"cell_type": "markdown",
"source": [
"วู้ฮู มาประเมินกันว่ารุ่นทำงานอย่างไรกับ test_set โดยใช้ `yardstick::metrics()`\n"
],
"metadata": {
"id": "qxdyj86bxNGZ"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"metrics(data = poly_results, truth = price, estimate = .pred)"
],
"outputs": [],
"metadata": {
"id": "8AW5ltkBxXDm"
}
},
{
"cell_type": "markdown",
"source": [
"🤩🤩 ประสิทธิภาพดีขึ้นมาก\n",
"\n",
"`rmse` ลดลงจากประมาณ 7 เหลือประมาณ 3 ซึ่งแสดงถึงข้อผิดพลาดที่ลดลงระหว่างราคาจริงและราคาที่คาดการณ์ คุณสามารถ *ตีความแบบคร่าวๆ* ได้ว่าค่าเฉลี่ยของการคาดการณ์ที่ผิดพลาดนั้นผิดไปประมาณ \\$3 `rsq` เพิ่มขึ้นจากประมาณ 0.4 เป็น 0.8\n",
"\n",
"ตัวชี้วัดทั้งหมดนี้แสดงให้เห็นว่าโมเดลพหุนามทำงานได้ดีกว่าโมเดลเชิงเส้นมาก เยี่ยมมาก!\n",
"\n",
"ลองมาดูว่าพอจะสร้างภาพให้เห็นได้ไหม!\n"
],
"metadata": {
"id": "6gLHNZDwxYaS"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Bind encoded package column to the results\r\n",
"poly_results <- poly_results %>% \r\n",
" bind_cols(package_encode %>% \r\n",
" rename(package_integer = package)) %>% \r\n",
" relocate(package_integer, .after = package)\r\n",
"\r\n",
"\r\n",
"# Print new results data frame\r\n",
"poly_results %>% \r\n",
" slice_head(n = 5)\r\n",
"\r\n",
"\r\n",
"# Make a scatter plot\r\n",
"poly_results %>% \r\n",
" ggplot(mapping = aes(x = package_integer, y = price)) +\r\n",
" geom_point(size = 1.6) +\r\n",
" # Overlay a line of best fit\r\n",
" geom_line(aes(y = .pred), color = \"midnightblue\", size = 1.2) +\r\n",
" xlab(\"package\")\r\n"
],
"outputs": [],
"metadata": {
"id": "A83U16frxdF1"
}
},
{
"cell_type": "markdown",
"source": [
"คุณสามารถเห็นเส้นโค้งที่เข้ากับข้อมูลของคุณได้ดีขึ้น! 🤩\n",
"\n",
"คุณสามารถทำให้เส้นนี้ดูเรียบเนียนขึ้นได้โดยการส่งสูตรพหุนามไปที่ `geom_smooth` แบบนี้:\n"
],
"metadata": {
"id": "4U-7aHOVxlGU"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make a scatter plot\r\n",
"poly_results %>% \r\n",
" ggplot(mapping = aes(x = package_integer, y = price)) +\r\n",
" geom_point(size = 1.6) +\r\n",
" # Overlay a line of best fit\r\n",
" geom_smooth(method = lm, formula = y ~ poly(x, degree = 4), color = \"midnightblue\", size = 1.2, se = FALSE) +\r\n",
" xlab(\"package\")"
],
"outputs": [],
"metadata": {
"id": "5vzNT0Uexm-w"
}
},
{
"cell_type": "markdown",
"source": [
"เหมือนกับเส้นโค้งที่ราบรื่น!🤩\n",
"\n",
"นี่คือวิธีที่คุณจะสร้างการพยากรณ์ใหม่:\n"
],
"metadata": {
"id": "v9u-wwyLxq4G"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make a hypothetical data frame\r\n",
"hypo_tibble <- tibble(package = \"bushel baskets\")\r\n",
"\r\n",
"# Make predictions using linear model\r\n",
"lm_pred <- lm_wf_fit %>% predict(new_data = hypo_tibble)\r\n",
"\r\n",
"# Make predictions using polynomial model\r\n",
"poly_pred <- poly_wf_fit %>% predict(new_data = hypo_tibble)\r\n",
"\r\n",
"# Return predictions in a list\r\n",
"list(\"linear model prediction\" = lm_pred, \r\n",
" \"polynomial model prediction\" = poly_pred)\r\n"
],
"outputs": [],
"metadata": {
"id": "jRPSyfQGxuQv"
}
},
{
"cell_type": "markdown",
"source": [
"การทำนายด้วย `polynomial model` ดูสมเหตุสมผลเมื่อพิจารณาจากกราฟกระจายของ `price` และ `package`! และถ้านี่เป็นโมเดลที่ดีกว่าโมเดลก่อนหน้า เมื่อดูจากข้อมูลเดียวกัน คุณจำเป็นต้องวางแผนงบประมาณสำหรับฟักทองที่มีราคาสูงขึ้นเหล่านี้!\n",
"\n",
"🏆 ยอดเยี่ยมมาก! คุณได้สร้างโมเดลการถดถอยสองแบบในบทเรียนเดียว ในส่วนสุดท้ายเกี่ยวกับการถดถอย คุณจะได้เรียนรู้เกี่ยวกับการถดถอยโลจิสติกเพื่อกำหนดหมวดหมู่\n",
"\n",
"## **🚀ความท้าทาย**\n",
"\n",
"ทดลองใช้ตัวแปรที่แตกต่างกันหลายตัวในโน้ตบุ๊กนี้เพื่อดูว่าความสัมพันธ์ส่งผลต่อความแม่นยำของโมเดลอย่างไร\n",
"\n",
"## [**แบบทดสอบหลังบทเรียน**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/14/)\n",
"\n",
"## **ทบทวนและศึกษาด้วยตนเอง**\n",
"\n",
"ในบทเรียนนี้เราได้เรียนรู้เกี่ยวกับการถดถอยเชิงเส้น ยังมีประเภทการถดถอยที่สำคัญอื่น ๆ อีก อ่านเพิ่มเติมเกี่ยวกับเทคนิค Stepwise, Ridge, Lasso และ Elasticnet หลักสูตรที่ดีสำหรับการศึกษาเพิ่มเติมคือ [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning)\n",
"\n",
"หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการใช้เฟรมเวิร์ก Tidymodels ที่น่าทึ่งนี้ โปรดดูแหล่งข้อมูลต่อไปนี้:\n",
"\n",
"- เว็บไซต์ Tidymodels: [เริ่มต้นกับ Tidymodels](https://www.tidymodels.org/start/)\n",
"\n",
"- Max Kuhn และ Julia Silge, [*Tidy Modeling with R*](https://www.tmwr.org/)*.*\n",
"\n",
"###### **ขอขอบคุณ:**\n",
"\n",
"[Allison Horst](https://twitter.com/allison_horst?lang=en) สำหรับการสร้างภาพประกอบที่น่าทึ่งซึ่งทำให้ R ดูน่าสนใจและเข้าถึงได้มากขึ้น ค้นหาภาพประกอบเพิ่มเติมได้ที่ [แกลเลอรีของเธอ](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM)\n"
],
"metadata": {
"id": "8zOLOWqMxzk5"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**ข้อจำกัดความรับผิดชอบ**: \nเอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้\n"
]
}
]
}