{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Bina model regresi logistik - Pelajaran 4\n", "\n", "![Infografik regresi logistik vs. linear](../../../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png)\n", "\n", "#### **[Kuiz pra-kuliah](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### Pengenalan\n", "\n", "Dalam pelajaran terakhir mengenai Regresi ini, salah satu teknik asas *klasik* ML, kita akan melihat Regresi Logistik. Anda boleh menggunakan teknik ini untuk mengenal pasti corak bagi meramalkan kategori binari. Adakah gula-gula ini coklat atau tidak? Adakah penyakit ini berjangkit atau tidak? Adakah pelanggan ini akan memilih produk ini atau tidak?\n", "\n", "Dalam pelajaran ini, anda akan belajar:\n", "\n", "- Teknik untuk regresi logistik\n", "\n", "βœ… Tingkatkan pemahaman anda tentang bekerja dengan jenis regresi ini dalam [modul pembelajaran ini](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n", "\n", "## Prasyarat\n", "\n", "Setelah bekerja dengan data labu, kita kini cukup biasa dengannya untuk menyedari bahawa terdapat satu kategori binari yang boleh kita gunakan: `Color`.\n", "\n", "Mari kita bina model regresi logistik untuk meramalkan, berdasarkan beberapa pemboleh ubah, *warna apa yang mungkin dimiliki oleh labu tertentu* (oren πŸŽƒ atau putih πŸ‘»).\n", "\n", "> Mengapa kita bercakap tentang klasifikasi binari dalam kumpulan pelajaran mengenai regresi? Hanya untuk kemudahan linguistik, kerana regresi logistik adalah [sebenarnya kaedah klasifikasi](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), walaupun ia berasaskan linear. Ketahui cara lain untuk mengklasifikasikan data dalam kumpulan pelajaran seterusnya.\n", "\n", "Untuk pelajaran ini, kita memerlukan pakej berikut:\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/) ialah [koleksi pakej R](https://www.tidyverse.org/packages) yang direka untuk menjadikan sains data lebih pantas, mudah dan menyeronokkan!\n", "\n", "- `tidymodels`: Rangka kerja [tidymodels](https://www.tidymodels.org/) ialah [koleksi pakej](https://www.tidymodels.org/packages/) untuk pemodelan dan pembelajaran mesin.\n", "\n", "- `janitor`: Pakej [janitor](https://github.com/sfirke/janitor) menyediakan alat kecil yang mudah untuk memeriksa dan membersihkan data yang kotor.\n", "\n", "- `ggbeeswarm`: Pakej [ggbeeswarm](https://github.com/eclarke/ggbeeswarm) menyediakan kaedah untuk mencipta plot gaya beeswarm menggunakan ggplot2.\n", "\n", "Anda boleh memasangnya seperti berikut:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "Sebagai alternatif, skrip di bawah akan memeriksa sama ada anda mempunyai pakej yang diperlukan untuk melengkapkan modul ini dan memasangnya untuk anda jika ia tiada.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n", "\n", "pacman::p_load(tidyverse, tidymodels, janitor, ggbeeswarm)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **Tentukan soalan**\n", "\n", "Untuk tujuan kita, kita akan menyatakannya sebagai binari: 'Putih' atau 'Bukan Putih'. Terdapat juga kategori 'berjalur' dalam dataset kita tetapi terdapat sedikit contoh mengenainya, jadi kita tidak akan menggunakannya. Ia akan hilang apabila kita membuang nilai null daripada dataset, bagaimanapun.\n", "\n", "> πŸŽƒ Fakta menarik, kadang-kadang kita memanggil labu putih sebagai labu 'hantu'. Ia tidak mudah untuk diukir, jadi ia tidak sepopular labu oren tetapi ia kelihatan menarik! Jadi kita juga boleh merumuskan semula soalan kita sebagai: 'Hantu' atau 'Bukan Hantu'. πŸ‘»\n", "\n", "## **Tentang regresi logistik**\n", "\n", "Regresi logistik berbeza daripada regresi linear, yang telah anda pelajari sebelum ini, dalam beberapa cara penting.\n", "\n", "#### **Klasifikasi binari**\n", "\n", "Regresi logistik tidak menawarkan ciri yang sama seperti regresi linear. Regresi logistik memberikan ramalan tentang `kategori binari` (\"oren atau bukan oren\") manakala regresi linear mampu meramalkan `nilai berterusan`, contohnya berdasarkan asal labu dan masa penuaian, *berapa banyak harga labu akan meningkat*.\n", "\n", "![Infografik oleh Dasani Madipalli](../../../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png)\n", "\n", "### Klasifikasi lain\n", "\n", "Terdapat jenis regresi logistik lain, termasuk multinomial dan ordinal:\n", "\n", "- **Multinomial**, yang melibatkan lebih daripada satu kategori - \"Oren, Putih, dan Berjalur\".\n", "\n", "- **Ordinal**, yang melibatkan kategori yang teratur, berguna jika kita ingin menyusun hasil kita secara logik, seperti labu kita yang disusun mengikut bilangan saiz yang terhad (mini,kecil,sederhana,besar,xl,xxl).\n", "\n", "![Regresi multinomial vs ordinal](../../../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png)\n", "\n", "#### **Pembolehubah TIDAK perlu berkorelasi**\n", "\n", "Ingat bagaimana regresi linear berfungsi lebih baik dengan pembolehubah yang lebih berkorelasi? Regresi logistik adalah sebaliknya - pembolehubah tidak perlu sejajar. Ini sesuai untuk data ini yang mempunyai korelasi yang agak lemah.\n", "\n", "#### **Anda memerlukan banyak data yang bersih**\n", "\n", "Regresi logistik akan memberikan hasil yang lebih tepat jika anda menggunakan lebih banyak data; dataset kecil kita tidak optimum untuk tugas ini, jadi ingatlah perkara ini.\n", "\n", "βœ… Fikirkan tentang jenis data yang sesuai untuk regresi logistik\n", "\n", "## Latihan - kemaskan data\n", "\n", "Pertama, bersihkan data sedikit, buang nilai null dan pilih hanya beberapa kolum:\n", "\n", "1. Tambahkan kod berikut:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Load the core tidyverse packages\n", "library(tidyverse)\n", "\n", "# Import the data and clean column names\n", "pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\") %>% \n", " clean_names()\n", "\n", "# Select desired columns\n", "pumpkins_select <- pumpkins %>% \n", " select(c(city_name, package, variety, origin, item_size, color)) \n", "\n", "# Drop rows containing missing values and encode color as factor (category)\n", "pumpkins_select <- pumpkins_select %>% \n", " drop_na() %>% \n", " mutate(color = factor(color))\n", "\n", "# View the first few rows\n", "pumpkins_select %>% \n", " slice_head(n = 5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Anda sentiasa boleh melihat sekilas dataframe baharu anda dengan menggunakan fungsi [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) seperti di bawah:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mari kita pastikan bahawa kita sebenarnya akan melakukan masalah klasifikasi binari:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Subset distinct observations in outcome column\n", "pumpkins_select %>% \n", " distinct(color)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualisasi - plot kategori\n", "Pada masa ini, anda telah memuatkan semula data labu dan membersihkannya untuk mengekalkan dataset yang mengandungi beberapa pemboleh ubah, termasuk Warna. Mari visualisasikan dataframe dalam notebook menggunakan perpustakaan ggplot.\n", "\n", "Perpustakaan ggplot menawarkan beberapa cara menarik untuk memvisualisasikan data anda. Sebagai contoh, anda boleh membandingkan taburan data untuk setiap Jenis dan Warna dalam plot kategori.\n", "\n", "1. Cipta plot seperti ini dengan menggunakan fungsi geombar, menggunakan data labu kita, dan menentukan pemetaan warna untuk setiap kategori labu (oren atau putih):\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "# Specify colors for each value of the hue variable\n", "palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n", "\n", "# Create the bar plot\n", "ggplot(pumpkins_select, aes(y = variety, fill = color)) +\n", " geom_bar(position = \"dodge\") +\n", " scale_fill_manual(values = palette) +\n", " labs(y = \"Variety\", fill = \"Color\") +\n", " theme_minimal()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dengan memerhatikan data, anda dapat melihat bagaimana data Warna berkaitan dengan Variasi.\n", "\n", "βœ… Berdasarkan plot kategori ini, apakah beberapa penerokaan menarik yang boleh anda bayangkan?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pra-pemprosesan Data: Pengekodan Ciri\n", "\n", "Dataset labu kita mengandungi nilai string untuk semua kolumnya. Bekerja dengan data kategori adalah intuitif untuk manusia tetapi tidak untuk mesin. Algoritma pembelajaran mesin berfungsi dengan baik dengan nombor. Itulah sebabnya pengekodan adalah langkah yang sangat penting dalam fasa pra-pemprosesan data, kerana ia membolehkan kita menukar data kategori kepada data berangka tanpa kehilangan sebarang maklumat. Pengekodan yang baik membawa kepada pembinaan model yang baik.\n", "\n", "Untuk pengekodan ciri, terdapat dua jenis pengekod utama:\n", "\n", "1. **Ordinal encoder**: Ia sesuai untuk pemboleh ubah ordinal, iaitu pemboleh ubah kategori di mana datanya mengikuti susunan logik, seperti kolum `item_size` dalam dataset kita. Ia mencipta pemetaan di mana setiap kategori diwakili oleh nombor, yang merupakan susunan kategori dalam kolum tersebut.\n", "\n", "2. **Categorical encoder**: Ia sesuai untuk pemboleh ubah nominal, iaitu pemboleh ubah kategori di mana datanya tidak mengikuti susunan logik, seperti semua ciri selain daripada `item_size` dalam dataset kita. Ia adalah pengekodan satu-hot, yang bermaksud setiap kategori diwakili oleh kolum binari: pemboleh ubah yang dikodkan adalah sama dengan 1 jika labu tergolong dalam Variety tersebut dan 0 jika tidak.\n", "\n", "Tidymodels menyediakan satu lagi pakej yang berguna: [recipes](https://recipes.tidymodels.org/) - pakej untuk pra-pemprosesan data. Kita akan mendefinisikan `recipe` yang menentukan bahawa semua kolum peramal harus dikodkan kepada satu set integer, `prep` untuk menganggarkan kuantiti dan statistik yang diperlukan oleh sebarang operasi, dan akhirnya `bake` untuk menerapkan pengiraan kepada data baharu.\n", "\n", "> Biasanya, recipes biasanya digunakan sebagai pra-pemproses untuk pemodelan di mana ia menentukan langkah-langkah yang harus diterapkan pada dataset untuk menjadikannya siap untuk pemodelan. Dalam kes ini, **sangat disarankan** agar anda menggunakan `workflow()` daripada menganggarkan recipe secara manual menggunakan prep dan bake. Kita akan melihat semua ini sebentar lagi.\n", ">\n", "> Walau bagaimanapun, buat masa ini, kita menggunakan recipes + prep + bake untuk menentukan langkah-langkah yang harus diterapkan pada dataset untuk menjadikannya siap untuk analisis data dan kemudian mengekstrak data yang telah dipra-pemproses dengan langkah-langkah yang diterapkan.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Preprocess and extract data to allow some data analysis\n", "baked_pumpkins <- recipe(color ~ ., data = pumpkins_select) %>%\n", " # Define ordering for item_size column\n", " step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n", " # Convert factors to numbers using the order defined above (Ordinal encoding)\n", " step_integer(item_size, zero_based = F) %>%\n", " # Encode all other predictors using one hot encoding\n", " step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE) %>%\n", " prep(data = pumpkin_select) %>%\n", " bake(new_data = NULL)\n", "\n", "# Display the first few rows of preprocessed data\n", "baked_pumpkins %>% \n", " slice_head(n = 5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "βœ… Apakah kelebihan menggunakan ordinal encoder untuk lajur Item Size?\n", "\n", "### Menganalisis hubungan antara pemboleh ubah\n", "\n", "Sekarang kita telah memproses data kita, kita boleh menganalisis hubungan antara ciri-ciri dan label untuk mendapatkan gambaran tentang sejauh mana model dapat meramalkan label berdasarkan ciri-ciri tersebut. Cara terbaik untuk melakukan analisis seperti ini adalah dengan memplotkan data. \n", "Kita akan menggunakan semula fungsi ggplot geom_boxplot_ untuk memvisualisasikan hubungan antara Item Size, Variety, dan Color dalam plot kategori. Untuk memplotkan data dengan lebih baik, kita akan menggunakan lajur Item Size yang telah dikodkan dan lajur Variety yang tidak dikodkan.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Define the color palette\n", "palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n", "\n", "# We need the encoded Item Size column to use it as the x-axis values in the plot\n", "pumpkins_select_plot<-pumpkins_select\n", "pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n", "\n", "# Create the grouped box plot\n", "ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n", " geom_boxplot() +\n", " facet_grid(variety ~ ., scales = \"free_x\") +\n", " scale_fill_manual(values = palette) +\n", " labs(x = \"Item Size\", y = \"\") +\n", " theme_minimal() +\n", " theme(strip.text = element_text(size = 12)) +\n", " theme(axis.text.x = element_text(size = 10)) +\n", " theme(axis.title.x = element_text(size = 12)) +\n", " theme(axis.title.y = element_blank()) +\n", " theme(legend.position = \"bottom\") +\n", " guides(fill = guide_legend(title = \"Color\")) +\n", " theme(panel.spacing = unit(0.5, \"lines\"))+\n", " theme(strip.text.y = element_text(size = 4, hjust = 0)) \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Gunakan plot swarm\n", "\n", "Oleh kerana Color adalah kategori binari (Putih atau Tidak), ia memerlukan '[pendekatan khusus](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) untuk visualisasi'.\n", "\n", "Cuba gunakan `plot swarm` untuk menunjukkan taburan warna berdasarkan item_size.\n", "\n", "Kami akan menggunakan [pakej ggbeeswarm](https://github.com/eclarke/ggbeeswarm) yang menyediakan kaedah untuk mencipta plot gaya beeswarm menggunakan ggplot2. Plot beeswarm adalah cara untuk memplotkan titik-titik yang biasanya bertindih supaya ia jatuh bersebelahan antara satu sama lain.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Create beeswarm plots of color and item_size\n", "baked_pumpkins %>% \n", " mutate(color = factor(color)) %>% \n", " ggplot(mapping = aes(x = color, y = item_size, color = color)) +\n", " geom_quasirandom() +\n", " scale_color_brewer(palette = \"Dark2\", direction = -1) +\n", " theme(legend.position = \"none\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sekarang kita mempunyai gambaran tentang hubungan antara kategori binari warna dan kumpulan saiz yang lebih besar, mari kita terokai regresi logistik untuk menentukan kemungkinan warna bagi labu tertentu.\n", "\n", "## Bina model anda\n", "\n", "Pilih pemboleh ubah yang ingin anda gunakan dalam model klasifikasi dan bahagikan data kepada set latihan dan ujian. [rsample](https://rsample.tidymodels.org/), sebuah pakej dalam Tidymodels, menyediakan infrastruktur untuk pembahagian data dan pensampelan semula yang cekap:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Split data into 80% for training and 20% for testing\n", "set.seed(2056)\n", "pumpkins_split <- pumpkins_select %>% \n", " initial_split(prop = 0.8)\n", "\n", "# Extract the data in each split\n", "pumpkins_train <- training(pumpkins_split)\n", "pumpkins_test <- testing(pumpkins_split)\n", "\n", "# Print out the first 5 rows of the training set\n", "pumpkins_train %>% \n", " slice_head(n = 5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "πŸ™Œ Kita kini bersedia untuk melatih model dengan memadankan ciri latihan kepada label latihan (warna).\n", "\n", "Kita akan mulakan dengan mencipta resipi yang menentukan langkah-langkah prapemprosesan yang perlu dilakukan pada data kita untuk mempersiapkannya bagi pemodelan, iaitu: mengekod pembolehubah kategori kepada satu set integer. Sama seperti `baked_pumpkins`, kita mencipta `pumpkins_recipe` tetapi tidak melakukan `prep` dan `bake` kerana ia akan dimasukkan ke dalam aliran kerja, yang akan anda lihat dalam beberapa langkah seterusnya.\n", "\n", "Terdapat beberapa cara untuk menentukan model regresi logistik dalam Tidymodels. Lihat `?logistic_reg()`. Buat masa ini, kita akan menentukan model regresi logistik melalui enjin lalai `stats::glm()`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Create a recipe that specifies preprocessing steps for modelling\n", "pumpkins_recipe <- recipe(color ~ ., data = pumpkins_train) %>% \n", " step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n", " step_integer(item_size, zero_based = F) %>% \n", " step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE)\n", "\n", "# Create a logistic model specification\n", "log_reg <- logistic_reg() %>% \n", " set_engine(\"glm\") %>% \n", " set_mode(\"classification\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sekarang kita mempunyai resipi dan spesifikasi model, kita perlu mencari cara untuk menggabungkan kedua-duanya ke dalam satu objek yang akan terlebih dahulu memproses data (prep+bake di belakang tabir), melatih model pada data yang telah diproses, dan juga membolehkan aktiviti pasca-pemprosesan yang berpotensi.\n", "\n", "Dalam Tidymodels, objek yang mudah ini dipanggil [`workflow`](https://workflows.tidymodels.org/) dan dengan mudah menyimpan komponen pemodelan anda.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Bundle modelling components in a workflow\n", "log_reg_wf <- workflow() %>% \n", " add_recipe(pumpkins_recipe) %>% \n", " add_model(log_reg)\n", "\n", "# Print out the workflow\n", "log_reg_wf\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Selepas aliran kerja *ditentukan*, model boleh `dilatih` menggunakan fungsi [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Aliran kerja ini akan menganggarkan resipi dan memproses data sebelum latihan, jadi kita tidak perlu melakukannya secara manual menggunakan prep dan bake.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Train the model\n", "wf_fit <- log_reg_wf %>% \n", " fit(data = pumpkins_train)\n", "\n", "# Print the trained workflow\n", "wf_fit\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Model ini mencetak pekali yang dipelajari semasa latihan.\n", "\n", "Sekarang kita telah melatih model menggunakan data latihan, kita boleh membuat ramalan pada data ujian menggunakan [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Mari kita mulakan dengan menggunakan model untuk meramalkan label bagi set ujian kita dan kebarangkalian untuk setiap label. Apabila kebarangkalian lebih daripada 0.5, kelas ramalan adalah `WHITE`, jika tidak, `ORANGE`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Make predictions for color and corresponding probabilities\n", "results <- pumpkins_test %>% select(color) %>% \n", " bind_cols(wf_fit %>% \n", " predict(new_data = pumpkins_test)) %>%\n", " bind_cols(wf_fit %>%\n", " predict(new_data = pumpkins_test, type = \"prob\"))\n", "\n", "# Compare predictions\n", "results %>% \n", " slice_head(n = 10)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sangat bagus! Ini memberikan lebih banyak pemahaman tentang bagaimana regresi logistik berfungsi.\n", "\n", "### Pemahaman yang lebih baik melalui matriks kekeliruan\n", "\n", "Membandingkan setiap ramalan dengan nilai sebenar \"ground truth\" yang sepadan bukanlah cara yang sangat efisien untuk menentukan sejauh mana model meramal dengan baik. Nasib baik, Tidymodels mempunyai beberapa helah lagi: [`yardstick`](https://yardstick.tidymodels.org/) - sebuah pakej yang digunakan untuk mengukur keberkesanan model menggunakan metrik prestasi.\n", "\n", "Salah satu metrik prestasi yang berkaitan dengan masalah klasifikasi ialah [`matriks kekeliruan`](https://wikipedia.org/wiki/Confusion_matrix). Matriks kekeliruan menerangkan sejauh mana prestasi model klasifikasi. Matriks kekeliruan menyusun berapa banyak contoh dalam setiap kelas yang diklasifikasikan dengan betul oleh model. Dalam kes kita, ia akan menunjukkan berapa banyak labu oren yang diklasifikasikan sebagai oren dan berapa banyak labu putih yang diklasifikasikan sebagai putih; matriks kekeliruan juga menunjukkan berapa banyak yang diklasifikasikan ke dalam kategori yang **salah**.\n", "\n", "Fungsi [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) daripada yardstick mengira tabulasi silang ini bagi kelas yang diperhatikan dan diramal.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Confusion matrix for prediction results\n", "conf_mat(data = results, truth = color, estimate = .pred_class)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mari kita tafsirkan matriks kekeliruan. Model kita diminta untuk mengklasifikasikan labu kepada dua kategori binari, kategori `putih` dan kategori `bukan-putih`.\n", "\n", "- Jika model anda meramalkan labu sebagai putih dan ia sebenarnya tergolong dalam kategori 'putih', kita panggil ini sebagai `benar positif`, ditunjukkan oleh nombor di sudut kiri atas.\n", "\n", "- Jika model anda meramalkan labu sebagai bukan putih dan ia sebenarnya tergolong dalam kategori 'putih', kita panggil ini sebagai `salah negatif`, ditunjukkan oleh nombor di sudut kiri bawah.\n", "\n", "- Jika model anda meramalkan labu sebagai putih dan ia sebenarnya tergolong dalam kategori 'bukan-putih', kita panggil ini sebagai `salah positif`, ditunjukkan oleh nombor di sudut kanan atas.\n", "\n", "- Jika model anda meramalkan labu sebagai bukan putih dan ia sebenarnya tergolong dalam kategori 'bukan-putih', kita panggil ini sebagai `benar negatif`, ditunjukkan oleh nombor di sudut kanan bawah.\n", "\n", "| Kebenaran |\n", "|:-----:|\n", "\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **Diramal** | PUTIH | OREN |\n", "| PUTIH | TP | FP |\n", "| OREN | FN | TN |\n", "\n", "Seperti yang anda mungkin telah teka, adalah lebih baik untuk mempunyai bilangan benar positif dan benar negatif yang lebih besar serta bilangan salah positif dan salah negatif yang lebih kecil, yang menunjukkan bahawa model berprestasi lebih baik.\n", "\n", "Matriks kekeliruan sangat berguna kerana ia menghasilkan metrik lain yang dapat membantu kita menilai prestasi model klasifikasi dengan lebih baik. Mari kita lihat beberapa daripadanya:\n", "\n", "πŸŽ“ Ketepatan: `TP/(TP + FP)` ditakrifkan sebagai nisbah ramalan positif yang sebenarnya positif. Juga dikenali sebagai [nilai ramalan positif](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n", "\n", "πŸŽ“ Ingatan: `TP/(TP + FN)` ditakrifkan sebagai nisbah hasil positif daripada jumlah sampel yang sebenarnya positif. Juga dikenali sebagai `sensitiviti`.\n", "\n", "πŸŽ“ Kekhususan: `TN/(TN + FP)` ditakrifkan sebagai nisbah hasil negatif daripada jumlah sampel yang sebenarnya negatif.\n", "\n", "πŸŽ“ Ketepatan: `TP + TN/(TP + TN + FP + FN)` Peratusan label yang diramal dengan tepat untuk satu sampel.\n", "\n", "πŸŽ“ Ukuran F: Purata wajaran antara ketepatan dan ingatan, dengan nilai terbaik adalah 1 dan nilai terburuk adalah 0.\n", "\n", "Mari kita kira metrik-metrik ini!\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Combine metric functions and calculate them all at once\n", "eval_metrics <- metric_set(ppv, recall, spec, f_meas, accuracy)\n", "eval_metrics(data = results, truth = color, estimate = .pred_class)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualisasikan lengkung ROC model ini\n", "\n", "Mari kita lakukan satu lagi visualisasi untuk melihat apa yang dipanggil sebagai [`lengkung ROC`](https://en.wikipedia.org/wiki/Receiver_operating_characteristic):\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Make a roc_curve\n", "results %>% \n", " roc_curve(color, .pred_ORANGE) %>% \n", " autoplot()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Graf ROC sering digunakan untuk mendapatkan gambaran tentang output pengklasifikasi dari segi positif benar vs. positif palsu. Graf ROC biasanya memaparkan `True Positive Rate`/Sensitiviti pada paksi Y, dan `False Positive Rate`/1-Spesifisiti pada paksi X. Oleh itu, kecuraman graf dan ruang antara garis tengah dengan graf adalah penting: anda mahukan graf yang cepat naik dan melepasi garis tersebut. Dalam kes kita, terdapat positif palsu pada permulaan, dan kemudian garis tersebut naik dan melepasi dengan betul.\n", "\n", "Akhir sekali, mari gunakan `yardstick::roc_auc()` untuk mengira Nilai Kawasan Di Bawah Graf (Area Under the Curve) yang sebenar. Salah satu cara untuk mentafsirkan AUC adalah sebagai kebarangkalian bahawa model meletakkan contoh positif rawak lebih tinggi daripada contoh negatif rawak.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "# Calculate area under curve\n", "results %>% \n", " roc_auc(color, .pred_ORANGE)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hasilnya adalah sekitar `0.975`. Memandangkan AUC berkisar dari 0 hingga 1, anda mahukan skor yang tinggi, kerana model yang 100% tepat dalam ramalannya akan mempunyai AUC sebanyak 1; dalam kes ini, model ini *agak baik*.\n", "\n", "Dalam pelajaran akan datang mengenai klasifikasi, anda akan belajar cara meningkatkan skor model anda (seperti menangani data yang tidak seimbang dalam kes ini).\n", "\n", "## πŸš€Cabaran\n", "\n", "Terdapat banyak lagi yang boleh diterokai mengenai regresi logistik! Tetapi cara terbaik untuk belajar adalah dengan mencuba. Cari dataset yang sesuai untuk jenis analisis ini dan bina model dengannya. Apa yang anda pelajari? tip: cuba [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) untuk dataset yang menarik.\n", "\n", "## Kajian & Pembelajaran Kendiri\n", "\n", "Baca beberapa halaman pertama [kertas kerja dari Stanford ini](https://web.stanford.edu/~jurafsky/slp3/5.pdf) mengenai beberapa kegunaan praktikal untuk regresi logistik. Fikirkan tentang tugas-tugas yang lebih sesuai untuk satu jenis regresi berbanding yang lain yang telah kita pelajari sehingga kini. Apa yang akan berfungsi dengan terbaik?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Penafian**: \nDokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Walaupun kami berusaha untuk memastikan ketepatan, sila ambil perhatian bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang berwibawa. Untuk maklumat yang kritikal, terjemahan manusia profesional adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.\n" ] } ], "metadata": { "anaconda-cloud": "", "kernelspec": { "display_name": "R", "langauge": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "3.4.1" }, "coopTranslator": { "original_hash": "feaf125f481a89c468fa115bf2aed580", "translation_date": "2025-09-06T11:42:46+00:00", "source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb", "language_code": "ms" } }, "nbformat": 4, "nbformat_minor": 1 }