{ "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-08-29T23:09:02+00:00", "source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb", "language_code": "mo" } }, "cells": [ { "cell_type": "markdown", "source": [], "metadata": { "id": "YJUHCXqK57yz" } }, { "cell_type": "markdown", "source": [ "## 回歸分析入門 - 第一課\n", "\n", "#### 放到情境中來看\n", "\n", "✅ 回歸方法有很多種類,選擇哪一種取決於你想要解答的問題。如果你想預測某個年齡段的人可能的身高,你會使用 `線性回歸`,因為你在尋找一個**數值**。如果你想了解某種料理是否應該被歸類為純素,你則是在尋找一個**類別分配**,因此會使用 `邏輯回歸`。稍後你會學到更多關於邏輯回歸的內容。試著思考一些你可以向數據提出的問題,以及哪種方法更適合回答這些問題。\n", "\n", "在本節中,你將使用一個[關於糖尿病的小型數據集](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html)。想像一下,如果你想測試一種針對糖尿病患者的治療方法,機器學習模型可能會幫助你判斷哪些患者對治療的反應會更好,基於多種變數的組合。即使是一個非常基礎的回歸模型,當可視化後,也可能顯示出一些關於變數的信息,幫助你組織理論上的臨床試驗。\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()` 對數據進行基本檢查,並使用 `slice()` 顯示前 5 行。\n", "\n", "在繼續之前,讓我們介紹一個您在 R 代碼中經常會遇到的東西 🥁🥁:管道運算符 `%>%`\n", "\n", "管道運算符 (`%>%`) 通過將一個對象向前傳遞到函數或調用表達式中,按邏輯順序執行操作。您可以將管道運算符理解為在代碼中表示 \"然後\" 的意思。\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) 允許我們在資料框中*選擇*(並可選擇性地重新命名)欄位。\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", "## 5. 在測試集上進行預測\n", "\n", "現在我們已經訓練了一個模型,可以使用 [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html) 來對測試數據集中的疾病進展 y 進行預測。這將用於繪製數據組之間的分界線。\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/資料框結果。這樣可以輕鬆地將原始數據和預測結果結合成一個可用的格式,方便後續操作,例如繪圖。\n", "\n", "`dplyr::bind_cols()` 可以高效地將多個資料框按欄位結合起來。\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" ] } ] }