{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## ساخت یک مدل رگرسیون لجستیک - درس ۴\n", "\n", "![اینفوگرافیک رگرسیون لجستیک در مقابل رگرسیون خطی](../../../../../../translated_images/linear-vs-logistic.ba180bf95e7ee66721ba10ebf2dac2666acbd64a88b003c83928712433a13c7d.fa.png)\n", "\n", "#### **[آزمون پیش از درس](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n", "\n", "#### مقدمه\n", "\n", "در این درس پایانی درباره رگرسیون، یکی از تکنیک‌های پایه‌ای و *کلاسیک* یادگیری ماشین، به بررسی رگرسیون لجستیک خواهیم پرداخت. از این تکنیک برای کشف الگوها به منظور پیش‌بینی دسته‌بندی‌های دودویی استفاده می‌شود. آیا این آب‌نبات شکلاتی است یا نه؟ آیا این بیماری مسری است یا نه؟ آیا این مشتری این محصول را انتخاب می‌کند یا نه؟\n", "\n", "در این درس، شما یاد خواهید گرفت:\n", "\n", "- تکنیک‌های مربوط به رگرسیون لجستیک\n", "\n", "✅ درک خود را از کار با این نوع رگرسیون در این [ماژول آموزشی](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott) عمیق‌تر کنید.\n", "\n", "## پیش‌نیاز\n", "\n", "با کار کردن روی داده‌های کدو تنبل، اکنون به اندازه کافی با آن آشنا هستیم تا متوجه شویم که یک دسته‌بندی دودویی وجود دارد که می‌توانیم با آن کار کنیم: `Color`.\n", "\n", "بیایید یک مدل رگرسیون لجستیک بسازیم تا پیش‌بینی کنیم که با توجه به برخی متغیرها، *رنگ یک کدو تنبل احتمالاً چه خواهد بود* (نارنجی 🎃 یا سفید 👻).\n", "\n", "> چرا در یک درس مربوط به رگرسیون درباره دسته‌بندی دودویی صحبت می‌کنیم؟ فقط به دلیل راحتی زبانی، زیرا رگرسیون لجستیک [در واقع یک روش دسته‌بندی](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression) است، هرچند که مبتنی بر خطی بودن است. درباره روش‌های دیگر دسته‌بندی داده‌ها در گروه درس بعدی یاد بگیرید.\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", "- `ggbeeswarm`: بسته [ggbeeswarm](https://github.com/eclarke/ggbeeswarm) روش‌هایی برای ایجاد نمودارهای سبک \"beeswarm\" با استفاده از ggplot2 ارائه می‌دهد.\n", "\n", "می‌توانید این بسته‌ها را به این صورت نصب کنید:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n", "\n", "به طور جایگزین، اسکریپت زیر بررسی می‌کند که آیا بسته‌های مورد نیاز برای تکمیل این ماژول را دارید یا خیر و در صورت نبود، آن‌ها را برای شما نصب می‌کند.\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": [ "## **تعریف سوال**\n", "\n", "برای اهداف ما، این سوال را به صورت دودویی بیان می‌کنیم: «سفید» یا «غیر سفید». همچنین یک دسته «راه‌راه» در مجموعه داده ما وجود دارد، اما تعداد نمونه‌های آن کم است، بنابراین از آن استفاده نمی‌کنیم. این دسته به هر حال پس از حذف مقادیر خالی از مجموعه داده ناپدید می‌شود.\n", "\n", "> 🎃 یک نکته جالب: گاهی اوقات کدوهای سفید را «کدوهای روح» می‌نامیم. حکاکی روی آن‌ها خیلی آسان نیست، به همین دلیل به اندازه کدوهای نارنجی محبوب نیستند، اما ظاهر جالبی دارند! بنابراین می‌توانیم سوال خود را به این صورت بازنویسی کنیم: «روح» یا «غیر روح». 👻\n", "\n", "## **درباره رگرسیون لجستیک**\n", "\n", "رگرسیون لجستیک در چندین جنبه مهم با رگرسیون خطی که قبلاً درباره آن یاد گرفتید، تفاوت دارد.\n", "\n", "#### **دسته‌بندی دودویی**\n", "\n", "رگرسیون لجستیک ویژگی‌های مشابه رگرسیون خطی را ارائه نمی‌دهد. رگرسیون لجستیک پیش‌بینی درباره یک `دسته‌بندی دودویی` (\"نارنجی یا غیر نارنجی\") ارائه می‌دهد، در حالی که رگرسیون خطی قادر به پیش‌بینی `مقادیر پیوسته` است، مثلاً با توجه به منشأ کدو و زمان برداشت، *چقدر قیمت آن افزایش خواهد یافت*.\n", "\n", "![اینفوگرافیک توسط Dasani Madipalli](../../../../../../translated_images/pumpkin-classifier.562771f104ad5436b87d1c67bca02a42a17841133556559325c0a0e348e5b774.fa.png)\n", "\n", "### دسته‌بندی‌های دیگر\n", "\n", "انواع دیگری از رگرسیون لجستیک وجود دارد، از جمله چندگانه و ترتیبی:\n", "\n", "- **چندگانه**، که شامل داشتن بیش از یک دسته است - \"نارنجی، سفید، و راه‌راه\".\n", "\n", "- **ترتیبی**، که شامل دسته‌های مرتب شده است، مفید اگر بخواهیم نتایج خود را به صورت منطقی مرتب کنیم، مانند کدوهایی که بر اساس تعداد محدودی از اندازه‌ها مرتب شده‌اند (کوچک، متوسط، بزرگ، خیلی بزرگ، و غیره).\n", "\n", "![رگرسیون چندگانه در مقابل ترتیبی](../../../../../../translated_images/multinomial-vs-ordinal.36701b4850e37d86c9dd49f7bef93a2f94dbdb8fe03443eb68f0542f97f28f29.fa.png)\n", "\n", "#### **متغیرها لازم نیست همبستگی داشته باشند**\n", "\n", "به یاد دارید که رگرسیون خطی با متغیرهای همبسته بهتر عمل می‌کرد؟ رگرسیون لجستیک برعکس است - متغیرها لازم نیست هم‌راستا باشند. این ویژگی برای این داده‌ها که همبستگی‌های نسبتاً ضعیفی دارند، مناسب است.\n", "\n", "#### **نیاز به داده‌های تمیز و زیاد**\n", "\n", "رگرسیون لجستیک اگر از داده‌های بیشتری استفاده کنید، نتایج دقیق‌تری ارائه می‌دهد؛ مجموعه داده کوچک ما برای این کار بهینه نیست، بنابراین این نکته را در نظر داشته باشید.\n", "\n", "✅ به انواع داده‌هایی فکر کنید که برای رگرسیون لجستیک مناسب هستند.\n", "\n", "## تمرین - مرتب‌سازی داده‌ها\n", "\n", "ابتدا داده‌ها را کمی تمیز کنید، مقادیر خالی را حذف کنید و فقط برخی از ستون‌ها را انتخاب کنید:\n", "\n", "1. کد زیر را اضافه کنید:\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": [ "شما همیشه می‌توانید با استفاده از تابع [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) که در زیر نشان داده شده است، نگاهی سریع به دیتافریم جدید خود بیندازید:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "vscode": { "languageId": "r" } }, "outputs": [], "source": [ "pumpkins_select %>% \n", " glimpse()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "بیایید تأیید کنیم که ما واقعاً قصد داریم یک مسئله طبقه‌بندی دودویی را حل کنیم:\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": [ "### تجسم‌سازی - نمودار دسته‌بندی‌شده\n", "تا اینجا داده‌های کدو تنبل را دوباره بارگذاری کرده‌اید و آن‌ها را پاک‌سازی کرده‌اید تا مجموعه داده‌ای شامل چند متغیر، از جمله رنگ، حفظ شود. حالا بیایید دیتافریم را در نوت‌بوک با استفاده از کتابخانه ggplot تجسم کنیم.\n", "\n", "کتابخانه ggplot روش‌های جالبی برای تجسم داده‌ها ارائه می‌دهد. به عنوان مثال، می‌توانید توزیع داده‌ها را برای هر گونه و رنگ در یک نمودار دسته‌بندی‌شده مقایسه کنید.\n", "\n", "1. چنین نموداری را با استفاده از تابع geombar ایجاد کنید، از داده‌های کدو تنبل ما استفاده کنید و یک نگاشت رنگی برای هر دسته کدو تنبل (نارنجی یا سفید) مشخص کنید:\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": [ "با مشاهده داده‌ها، می‌توانید ببینید که داده‌های مربوط به رنگ چگونه با نوع (Variety) ارتباط دارند.\n", "\n", "✅ با توجه به این نمودار دسته‌بندی، چه بررسی‌های جالبی می‌توانید تصور کنید؟\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### پیش‌پردازش داده‌ها: کدگذاری ویژگی‌ها\n", "\n", "مجموعه داده‌های کدو تنبل ما شامل مقادیر رشته‌ای برای تمام ستون‌های خود است. کار با داده‌های دسته‌بندی‌شده برای انسان‌ها شهودی است، اما برای ماشین‌ها این‌گونه نیست. الگوریتم‌های یادگیری ماشین با اعداد بهتر کار می‌کنند. به همین دلیل، کدگذاری یک مرحله بسیار مهم در فاز پیش‌پردازش داده‌ها است، زیرا به ما امکان می‌دهد داده‌های دسته‌بندی‌شده را به داده‌های عددی تبدیل کنیم، بدون اینکه اطلاعاتی از دست برود. کدگذاری خوب منجر به ساخت یک مدل خوب می‌شود.\n", "\n", "برای کدگذاری ویژگی‌ها، دو نوع اصلی کدگذار وجود دارد:\n", "\n", "1. کدگذار ترتیبی: این نوع کدگذاری برای متغیرهای ترتیبی مناسب است، که متغیرهای دسته‌بندی‌شده‌ای هستند که داده‌هایشان از یک ترتیب منطقی پیروی می‌کنند، مانند ستون `item_size` در مجموعه داده ما. این کدگذار یک نگاشت ایجاد می‌کند که هر دسته با یک عدد نشان داده می‌شود، که ترتیب دسته در ستون را نشان می‌دهد.\n", "\n", "2. کدگذار دسته‌ای: این نوع کدگذاری برای متغیرهای اسمی مناسب است، که متغیرهای دسته‌بندی‌شده‌ای هستند که داده‌هایشان از یک ترتیب منطقی پیروی نمی‌کنند، مانند تمام ویژگی‌هایی که متفاوت از `item_size` در مجموعه داده ما هستند. این نوع کدگذاری به صورت یک کدگذاری یک‌به‌چند است، به این معنا که هر دسته با یک ستون دودویی نشان داده می‌شود: متغیر کدگذاری‌شده برابر با 1 است اگر کدو تنبل متعلق به آن نوع باشد و در غیر این صورت برابر با 0 است.\n", "\n", "Tidymodels یک بسته دیگر بسیار کاربردی ارائه می‌دهد: [recipes](https://recipes.tidymodels.org/) - یک بسته برای پیش‌پردازش داده‌ها. ما یک `recipe` تعریف می‌کنیم که مشخص می‌کند تمام ستون‌های پیش‌بینی‌کننده باید به مجموعه‌ای از اعداد صحیح کدگذاری شوند، آن را `prep` می‌کنیم تا مقادیر و آمار مورد نیاز برای هر عملیات تخمین زده شود و در نهایت آن را `bake` می‌کنیم تا محاسبات را به داده‌های جدید اعمال کنیم.\n", "\n", "> به طور معمول، recipes معمولاً به عنوان یک پیش‌پردازنده برای مدل‌سازی استفاده می‌شود، جایی که مشخص می‌کند چه مراحلی باید بر روی یک مجموعه داده اعمال شود تا برای مدل‌سازی آماده شود. در این حالت، **به شدت توصیه می‌شود** که به جای تخمین دستی یک recipe با استفاده از prep و bake، از یک `workflow()` استفاده کنید. به زودی همه این‌ها را خواهیم دید.\n", ">\n", "> اما در حال حاضر، ما از recipes + prep + bake استفاده می‌کنیم تا مشخص کنیم چه مراحلی باید بر روی یک مجموعه داده اعمال شود تا برای تحلیل داده‌ها آماده شود و سپس داده‌های پیش‌پردازش‌شده را با مراحل اعمال‌شده استخراج کنیم.\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": [ "✅ مزایای استفاده از رمزگذار ترتیبی برای ستون اندازه آیتم چیست؟\n", "\n", "### تحلیل روابط بین متغیرها\n", "\n", "اکنون که داده‌های خود را پیش‌پردازش کرده‌ایم، می‌توانیم روابط بین ویژگی‌ها و برچسب را تحلیل کنیم تا ایده‌ای از اینکه مدل چقدر قادر خواهد بود برچسب را با توجه به ویژگی‌ها پیش‌بینی کند، به دست آوریم. بهترین روش برای انجام این نوع تحلیل، رسم داده‌ها است. \n", "ما دوباره از تابع ggplot geom_boxplot_ استفاده خواهیم کرد تا روابط بین اندازه آیتم، تنوع و رنگ را در یک نمودار دسته‌بندی شده به تصویر بکشیم. برای رسم بهتر داده‌ها، از ستون رمزگذاری‌شده اندازه آیتم و ستون رمزگذاری‌نشده تنوع استفاده خواهیم کرد.\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": [ "#### استفاده از نمودار ازدحام\n", "\n", "از آنجا که رنگ یک دسته‌بندی دودویی است (سفید یا غیرسفید)، برای نمایش نیاز به '[رویکرد تخصصی](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf)' دارد.\n", "\n", "از یک `نمودار ازدحام` استفاده کنید تا توزیع رنگ را نسبت به اندازه آیتم نشان دهید.\n", "\n", "ما از [بسته ggbeeswarm](https://github.com/eclarke/ggbeeswarm) استفاده خواهیم کرد که روش‌هایی برای ایجاد نمودارهای سبک ازدحام با استفاده از ggplot2 ارائه می‌دهد. نمودارهای ازدحام روشی برای نمایش نقاطی هستند که معمولاً روی هم قرار می‌گیرند، به‌طوری‌که در کنار یکدیگر قرار بگیرند.\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": [ "حالا که ایده‌ای از رابطه بین دسته‌های دودویی رنگ و گروه بزرگ‌تر اندازه‌ها داریم، بیایید رگرسیون لجستیک را بررسی کنیم تا رنگ احتمالی یک کدو تنبل مشخص را تعیین کنیم.\n", "\n", "## مدل خود را بسازید\n", "\n", "متغیرهایی را که می‌خواهید در مدل طبقه‌بندی خود استفاده کنید انتخاب کنید و داده‌ها را به مجموعه‌های آموزشی و آزمایشی تقسیم کنید. [rsample](https://rsample.tidymodels.org/)، یک بسته در Tidymodels، زیرساختی برای تقسیم و نمونه‌گیری مجدد داده‌ها به صورت کارآمد فراهم می‌کند:\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": [ "🙌 حالا آماده‌ایم که یک مدل را با تطبیق ویژگی‌های آموزشی به برچسب آموزشی (رنگ) آموزش دهیم.\n", "\n", "ابتدا یک دستورالعمل (recipe) ایجاد می‌کنیم که مراحل پیش‌پردازش داده‌ها را مشخص می‌کند تا داده‌ها برای مدل‌سازی آماده شوند؛ به عنوان مثال: کدگذاری متغیرهای دسته‌بندی‌شده به مجموعه‌ای از اعداد صحیح. درست مانند `baked_pumpkins`، یک `pumpkins_recipe` ایجاد می‌کنیم اما آن را `prep` و `bake` نمی‌کنیم، زیرا این مراحل در یک جریان کاری (workflow) گنجانده می‌شوند که چند مرحله بعد آن را خواهید دید.\n", "\n", "روش‌های متعددی برای مشخص کردن یک مدل رگرسیون لجستیک در Tidymodels وجود دارد. به `?logistic_reg()` مراجعه کنید. فعلاً، یک مدل رگرسیون لجستیک را از طریق موتور پیش‌فرض `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": [ "حالا که یک دستورالعمل و مشخصات مدل داریم، باید راهی پیدا کنیم تا آن‌ها را در قالب یک شیء ترکیب کنیم که ابتدا داده‌ها را پیش‌پردازش کند (پشت صحنه با prep+bake)، مدل را روی داده‌های پیش‌پردازش شده اجرا کند و همچنین امکان فعالیت‌های پس‌پردازش احتمالی را فراهم کند.\n", "\n", "در Tidymodels، این شیء کاربردی [`workflow`](https://workflows.tidymodels.org/) نامیده می‌شود و به راحتی اجزای مدل‌سازی شما را نگه می‌دارد.\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": [ "پس از اینکه یک جریان کاری *مشخص* شد، می‌توان یک مدل را با استفاده از تابع [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html) `آموزش` داد. جریان کاری ابتدا یک دستورالعمل را تخمین زده و داده‌ها را پیش‌پردازش می‌کند، بنابراین نیازی نیست که این کار را به صورت دستی با استفاده از prep و 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": [ "مدل مقادیر ضرایب یاد گرفته شده در طول آموزش را نشان می‌دهد.\n", "\n", "حالا که مدل را با استفاده از داده‌های آموزشی آموزش داده‌ایم، می‌توانیم با استفاده از [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html) پیش‌بینی‌هایی روی داده‌های آزمایشی انجام دهیم. بیایید با استفاده از مدل، برچسب‌ها را برای مجموعه آزمایشی و احتمال‌ها برای هر برچسب پیش‌بینی کنیم. وقتی احتمال بیشتر از 0.5 باشد، کلاس پیش‌بینی شده `WHITE` است و در غیر این صورت `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": [ "خیلی عالی! این توضیحات بیشتری درباره نحوه عملکرد رگرسیون لجستیک ارائه می‌دهد.\n", "\n", "### درک بهتر با استفاده از ماتریس سردرگمی\n", "\n", "مقایسه هر پیش‌بینی با مقدار واقعی متناظر آن (که به عنوان \"حقیقت زمین\" شناخته می‌شود) روش چندان موثری برای تعیین میزان دقت مدل در پیش‌بینی نیست. خوشبختانه، Tidymodels چند ابزار دیگر نیز در اختیار دارد: [`yardstick`](https://yardstick.tidymodels.org/) - یک بسته که برای اندازه‌گیری اثربخشی مدل‌ها با استفاده از معیارهای عملکرد استفاده می‌شود.\n", "\n", "یکی از معیارهای عملکرد مرتبط با مسائل طبقه‌بندی، [`ماتریس سردرگمی`](https://wikipedia.org/wiki/Confusion_matrix) است. ماتریس سردرگمی نشان می‌دهد که یک مدل طبقه‌بندی چقدر خوب عمل می‌کند. این ماتریس تعداد نمونه‌هایی را که در هر کلاس به درستی توسط مدل طبقه‌بندی شده‌اند، ثبت می‌کند. در مورد ما، این ماتریس نشان می‌دهد که چند کدو تنبل نارنجی به درستی به عنوان نارنجی طبقه‌بندی شده‌اند و چند کدو تنبل سفید به درستی به عنوان سفید طبقه‌بندی شده‌اند؛ همچنین ماتریس سردرگمی نشان می‌دهد که چند نمونه به دسته‌بندی‌های **اشتباه** اختصاص داده شده‌اند.\n", "\n", "تابع [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) از بسته yardstick این جدول متقاطع از کلاس‌های مشاهده‌شده و پیش‌بینی‌شده را محاسبه می‌کند.\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": [ "بیایید ماتریس سردرگمی را تفسیر کنیم. مدل ما باید کدوها را بین دو دسته‌ی دودویی، دسته‌ی `سفید` و دسته‌ی `غیر سفید` طبقه‌بندی کند.\n", "\n", "- اگر مدل شما یک کدو را سفید پیش‌بینی کند و در واقع به دسته‌ی 'سفید' تعلق داشته باشد، به آن `مثبت واقعی` می‌گوییم که با عدد بالا سمت چپ نشان داده می‌شود.\n", "\n", "- اگر مدل شما یک کدو را غیر سفید پیش‌بینی کند و در واقع به دسته‌ی 'سفید' تعلق داشته باشد، به آن `منفی کاذب` می‌گوییم که با عدد پایین سمت چپ نشان داده می‌شود.\n", "\n", "- اگر مدل شما یک کدو را سفید پیش‌بینی کند و در واقع به دسته‌ی 'غیر سفید' تعلق داشته باشد، به آن `مثبت کاذب` می‌گوییم که با عدد بالا سمت راست نشان داده می‌شود.\n", "\n", "- اگر مدل شما یک کدو را غیر سفید پیش‌بینی کند و در واقع به دسته‌ی 'غیر سفید' تعلق داشته باشد، به آن `منفی واقعی` می‌گوییم که با عدد پایین سمت راست نشان داده می‌شود.\n", "\n", "| حقیقت |\n", "|:-----:|\n", "\n", "| | | |\n", "|---------------|--------|-------|\n", "| **پیش‌بینی‌شده** | سفید | نارنجی |\n", "| سفید | TP | FP |\n", "| نارنجی | FN | TN |\n", "\n", "همان‌طور که احتمالاً حدس زده‌اید، ترجیح داده می‌شود تعداد مثبت‌های واقعی و منفی‌های واقعی بیشتر باشد و تعداد مثبت‌های کاذب و منفی‌های کاذب کمتر باشد، که نشان‌دهنده‌ی عملکرد بهتر مدل است.\n", "\n", "ماتریس سردرگمی مفید است زیرا منجر به معیارهای دیگری می‌شود که می‌توانند به ما در ارزیابی بهتر عملکرد یک مدل طبقه‌بندی کمک کنند. بیایید برخی از آن‌ها را مرور کنیم:\n", "\n", "🎓 دقت: `TP/(TP + FP)` که به عنوان نسبت مثبت‌های پیش‌بینی‌شده که واقعاً مثبت هستند تعریف می‌شود. همچنین به آن [ارزش پیش‌بینی مثبت](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\") گفته می‌شود.\n", "\n", "🎓 بازیابی: `TP/(TP + FN)` که به عنوان نسبت نتایج مثبت از تعداد نمونه‌هایی که واقعاً مثبت هستند تعریف می‌شود. همچنین به آن `حساسیت` گفته می‌شود.\n", "\n", "🎓 ویژگی: `TN/(TN + FP)` که به عنوان نسبت نتایج منفی از تعداد نمونه‌هایی که واقعاً منفی هستند تعریف می‌شود.\n", "\n", "🎓 دقت کلی: `TP + TN/(TP + TN + FP + FN)` درصد برچسب‌هایی که برای یک نمونه به درستی پیش‌بینی شده‌اند.\n", "\n", "🎓 معیار F: میانگین وزنی دقت و بازیابی، که بهترین مقدار آن ۱ و بدترین مقدار آن ۰ است.\n", "\n", "بیایید این معیارها را محاسبه کنیم!\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": [ "## نمایش منحنی ROC این مدل\n", "\n", "بیایید یک تجسم دیگر انجام دهیم تا به اصطلاح [`منحنی 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": [ "منحنی‌های ROC اغلب برای بررسی خروجی یک دسته‌بند از نظر مثبت‌های واقعی در مقابل مثبت‌های کاذب استفاده می‌شوند. در منحنی‌های ROC معمولاً `True Positive Rate`/حساسیت در محور عمودی (Y) و `False Positive Rate`/1-ویژگی در محور افقی (X) نمایش داده می‌شوند. بنابراین، شیب منحنی و فاصله بین خط میانی و منحنی اهمیت دارد: شما به دنبال منحنی‌ای هستید که به سرعت به سمت بالا حرکت کند و از خط عبور کند. در مورد ما، ابتدا مثبت‌های کاذب وجود دارند و سپس خط به درستی به سمت بالا و جلو حرکت می‌کند.\n", "\n", "در نهایت، بیایید از `yardstick::roc_auc()` استفاده کنیم تا مساحت زیر منحنی (AUC) را محاسبه کنیم. یکی از روش‌های تفسیر AUC این است که آن را به‌عنوان احتمال اینکه مدل یک نمونه مثبت تصادفی را بالاتر از یک نمونه منفی تصادفی رتبه‌بندی کند، در نظر بگیریم.\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": [ "نتیجه حدود `0.975` است. با توجه به اینکه AUC بین 0 تا 1 قرار دارد، شما به دنبال امتیاز بالایی هستید، زیرا مدلی که پیش‌بینی‌هایش 100% درست باشد، AUC برابر با 1 خواهد داشت؛ در این مورد، مدل *نسبتاً خوب* عمل کرده است.\n", "\n", "در درس‌های آینده درباره طبقه‌بندی‌ها، یاد خواهید گرفت که چگونه امتیازات مدل خود را بهبود دهید (مانند برخورد با داده‌های نامتوازن در این مورد).\n", "\n", "## 🚀چالش\n", "\n", "چیزهای زیادی درباره رگرسیون لجستیک وجود دارد که باید کشف شوند! اما بهترین راه برای یادگیری، آزمایش کردن است. یک مجموعه داده پیدا کنید که برای این نوع تحلیل مناسب باشد و با آن یک مدل بسازید. چه چیزی یاد می‌گیرید؟ نکته: برای مجموعه داده‌های جالب [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) را امتحان کنید.\n", "\n", "## مرور و مطالعه شخصی\n", "\n", "چند صفحه اول [این مقاله از دانشگاه استنفورد](https://web.stanford.edu/~jurafsky/slp3/5.pdf) را درباره کاربردهای عملی رگرسیون لجستیک بخوانید. درباره وظایفی فکر کنید که برای یکی از انواع رگرسیون‌هایی که تا اینجا مطالعه کرده‌ایم مناسب‌تر هستند. کدام بهتر عمل می‌کند؟\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**سلب مسئولیت**: \nاین سند با استفاده از سرویس ترجمه هوش مصنوعی [Co-op Translator](https://github.com/Azure/co-op-translator) ترجمه شده است. در حالی که ما برای دقت تلاش می‌کنیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادقتی‌هایی باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حساس، ترجمه حرفه‌ای انسانی توصیه می‌شود. ما هیچ مسئولیتی در قبال سوءتفاهم‌ها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.\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-04T01:27:27+00:00", "source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb", "language_code": "fa" } }, "nbformat": 4, "nbformat_minor": 1 }