{ "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", "

\n", " \n", "

อินโฟกราฟิกโดย Dasani Madipalli
\n", "\n", "\n", "\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", "

\n", " \n", "

ผลงานโดย @allison_horst
\n", "\n", "\n", "\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", "

\n", " \n", "

ภาพวาดโดย @allison_horst
\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", "

\n", " \n", "

อินโฟกราฟิกโดย Dasani Madipalli
\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", "

\n", " \n", "

อินโฟกราฟิกโดย Dasani Madipalli
\n", "\n", "\n", "\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" ] } ] }