{ "cells": [ { "cell_type": "markdown", "source": [ "## **تحليل الموسيقى النيجيرية المستخرجة من Spotify**\n", "\n", "التجميع هو نوع من [التعلم غير المراقب](https://wikipedia.org/wiki/Unsupervised_learning) الذي يفترض أن مجموعة البيانات غير مصنفة أو أن مدخلاتها غير مرتبطة بمخرجات محددة مسبقًا. يستخدم خوارزميات مختلفة لفرز البيانات غير المصنفة وتقديم مجموعات بناءً على الأنماط التي يكتشفها في البيانات.\n", "\n", "[**اختبار ما قبل المحاضرة**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/27/)\n", "\n", "### **المقدمة**\n", "\n", "[التجميع](https://link.springer.com/referenceworkentry/10.1007%2F978-0-387-30164-8_124) مفيد جدًا لاستكشاف البيانات. دعونا نرى ما إذا كان يمكنه المساعدة في اكتشاف الاتجاهات والأنماط في طريقة استهلاك الجمهور النيجيري للموسيقى.\n", "\n", "> ✅ خذ دقيقة للتفكير في استخدامات التجميع. في الحياة اليومية، يحدث التجميع عندما يكون لديك كومة من الغسيل وتحتاج إلى فرز ملابس أفراد الأسرة 🧦👕👖🩲. في علم البيانات، يحدث التجميع عند محاولة تحليل تفضيلات المستخدم أو تحديد خصائص أي مجموعة بيانات غير مصنفة. التجميع، بطريقة ما، يساعد في فهم الفوضى، مثل درج الجوارب.\n", "\n", "في بيئة العمل، يمكن استخدام التجميع لتحديد أشياء مثل تقسيم السوق، أو تحديد الفئات العمرية التي تشتري منتجات معينة، على سبيل المثال. استخدام آخر يمكن أن يكون اكتشاف الشذوذ، ربما للكشف عن الاحتيال من مجموعة بيانات معاملات بطاقات الائتمان. أو قد تستخدم التجميع لتحديد الأورام في مجموعة من الفحوصات الطبية.\n", "\n", "✅ فكر لدقيقة كيف قد تكون واجهت التجميع \"في الحياة الواقعية\"، في بيئة مصرفية، تجارة إلكترونية، أو أعمال.\n", "\n", "> 🎓 من المثير للاهتمام أن تحليل التجميع نشأ في مجالات الأنثروبولوجيا وعلم النفس في الثلاثينيات. هل يمكنك تخيل كيف كان يمكن استخدامه؟\n", "\n", "بدلاً من ذلك، يمكنك استخدامه لتجميع نتائج البحث - مثل روابط التسوق، الصور، أو المراجعات، على سبيل المثال. التجميع مفيد عندما يكون لديك مجموعة بيانات كبيرة تريد تقليلها وتريد إجراء تحليل أكثر تفصيلًا عليها، لذا يمكن استخدام هذه التقنية للتعرف على البيانات قبل بناء نماذج أخرى.\n", "\n", "✅ بمجرد تنظيم بياناتك في مجموعات، يمكنك تعيين معرف مجموعة لها، وهذه التقنية يمكن أن تكون مفيدة عند الحفاظ على خصوصية مجموعة البيانات؛ يمكنك بدلاً من ذلك الإشارة إلى نقطة بيانات بمعرف المجموعة، بدلاً من بيانات تعريفية أكثر كشفًا. هل يمكنك التفكير في أسباب أخرى قد تجعلك تشير إلى معرف المجموعة بدلاً من عناصر أخرى في المجموعة لتحديدها؟\n", "\n", "### البدء مع التجميع\n", "\n", "> 🎓 كيفية إنشاء المجموعات تعتمد بشكل كبير على كيفية جمع نقاط البيانات في مجموعات. دعونا نستعرض بعض المصطلحات:\n", ">\n", "> 🎓 ['الاستنتاج الانتقالي' مقابل 'الاستنتاج الاستقرائي'](https://wikipedia.org/wiki/Transduction_(machine_learning))\n", ">\n", "> الاستنتاج الانتقالي مشتق من حالات تدريب ملاحظة ترتبط بحالات اختبار محددة. الاستنتاج الاستقرائي مشتق من حالات تدريب ترتبط بقواعد عامة يتم تطبيقها بعد ذلك فقط على حالات الاختبار.\n", ">\n", "> مثال: تخيل أن لديك مجموعة بيانات مصنفة جزئيًا فقط. بعض الأشياء هي \"سجلات\"، وبعضها \"أقراص مدمجة\"، وبعضها فارغ. مهمتك هي توفير تسميات للفارغات. إذا اخترت نهجًا استقرائيًا، ستدرب نموذجًا يبحث عن \"السجلات\" و\"الأقراص المدمجة\"، وتطبق تلك التسميات على بياناتك غير المصنفة. هذا النهج سيواجه صعوبة في تصنيف الأشياء التي هي في الواقع \"كاسيتات\". من ناحية أخرى، النهج الانتقالي يتعامل مع هذه البيانات غير المعروفة بشكل أكثر فعالية حيث يعمل على تجميع العناصر المتشابهة معًا ثم يطبق تسمية على المجموعة. في هذه الحالة، قد تعكس المجموعات \"أشياء موسيقية دائرية\" و\"أشياء موسيقية مربعة\".\n", ">\n", "> 🎓 ['الهندسة غير المسطحة' مقابل 'الهندسة المسطحة'](https://datascience.stackexchange.com/questions/52260/terminology-flat-geometry-in-the-context-of-clustering)\n", ">\n", "> مشتقة من المصطلحات الرياضية، تشير الهندسة غير المسطحة مقابل الهندسة المسطحة إلى قياس المسافات بين النقاط إما بطرق هندسية \"مسطحة\" ([إقليدية](https://wikipedia.org/wiki/Euclidean_geometry)) أو \"غير مسطحة\" (غير إقليدية).\n", ">\n", "> \"مسطحة\" في هذا السياق تشير إلى الهندسة الإقليدية (بعض أجزائها تُدرس كـ \"هندسة مستوية\")، و\"غير مسطحة\" تشير إلى الهندسة غير الإقليدية. ما علاقة الهندسة بتعلم الآلة؟ حسنًا، كحقلين متجذرين في الرياضيات، يجب أن يكون هناك طريقة مشتركة لقياس المسافات بين النقاط في المجموعات، ويمكن القيام بذلك بطريقة \"مسطحة\" أو \"غير مسطحة\"، اعتمادًا على طبيعة البيانات. [المسافات الإقليدية](https://wikipedia.org/wiki/Euclidean_distance) تُقاس كطول قطعة مستقيمة بين نقطتين. [المسافات غير الإقليدية](https://wikipedia.org/wiki/Non-Euclidean_geometry) تُقاس على طول منحنى. إذا كانت بياناتك، عند تصورها، تبدو وكأنها لا توجد على مستوى، قد تحتاج إلى استخدام خوارزمية متخصصة للتعامل معها.\n", "\n", "

\n", " \n", "

إنفوجرافيك بواسطة داساني ماديبالي
\n", "\n", "\n", "\n", "> 🎓 ['المسافات'](https://web.stanford.edu/class/cs345a/slides/12-clustering.pdf)\n", ">\n", "> تُعرّف المجموعات بمصفوفة المسافات الخاصة بها، مثل المسافات بين النقاط. يمكن قياس هذه المسافة بعدة طرق. تُعرّف المجموعات الإقليدية بمتوسط قيم النقاط، وتحتوي على \"مركز\" أو نقطة مركزية. تُقاس المسافات بالتالي بالمسافة إلى هذا المركز. تشير المسافات غير الإقليدية إلى \"مراكز المجموعات\"، وهي النقطة الأقرب إلى النقاط الأخرى. يمكن تعريف مراكز المجموعات بطرق مختلفة.\n", ">\n", "> 🎓 ['المقيدة'](https://wikipedia.org/wiki/Constrained_clustering)\n", ">\n", "> [التجميع المقيد](https://web.cs.ucdavis.edu/~davidson/Publications/ICDMTutorial.pdf) يقدم التعلم \"شبه المراقب\" إلى هذه الطريقة غير المراقبة. يتم تمييز العلاقات بين النقاط كـ \"لا يمكن الربط\" أو \"يجب الربط\" بحيث تُفرض بعض القواعد على مجموعة البيانات.\n", ">\n", "> مثال: إذا تُركت خوارزمية حرة على مجموعة بيانات غير مصنفة أو شبه مصنفة، قد تكون المجموعات التي تنتجها ذات جودة ضعيفة. في المثال أعلاه، قد تُجمع المجموعات \"أشياء موسيقية دائرية\" و\"أشياء موسيقية مربعة\" و\"أشياء مثلثة\" و\"كوكيز\". إذا أُعطيت بعض القيود، أو قواعد لتتبعها (\"يجب أن يكون العنصر مصنوعًا من البلاستيك\"، \"يجب أن يكون العنصر قادرًا على إنتاج الموسيقى\") يمكن أن يساعد ذلك في \"تقييد\" الخوارزمية لاتخاذ خيارات أفضل.\n", ">\n", "> 🎓 'الكثافة'\n", ">\n", "> تُعتبر البيانات \"الصاخبة\" بأنها \"كثيفة\". قد تُظهر المسافات بين النقاط في كل مجموعة من مجموعاتها، عند الفحص، أنها أكثر أو أقل كثافة، أو \"مزدحمة\"، وبالتالي تحتاج هذه البيانات إلى التحليل باستخدام الطريقة المناسبة للتجميع. [هذه المقالة](https://www.kdnuggets.com/2020/02/understanding-density-based-clustering.html) توضح الفرق بين استخدام خوارزميات التجميع K-Means مقابل HDBSCAN لاستكشاف مجموعة بيانات صاخبة ذات كثافة غير متساوية.\n", "\n", "تعلم المزيد عن تقنيات التجميع في هذا [الوحدة التعليمية](https://docs.microsoft.com/learn/modules/train-evaluate-cluster-models?WT.mc_id=academic-77952-leestott)\n", "\n", "### **خوارزميات التجميع**\n", "\n", "هناك أكثر من 100 خوارزمية للتجميع، ويعتمد استخدامها على طبيعة البيانات المتوفرة. دعونا نناقش بعض الأنواع الرئيسية:\n", "\n", "- **التجميع الهرمي**. إذا تم تصنيف كائن بناءً على قربه من كائن قريب، بدلاً من كائن بعيد، تُشكل المجموعات بناءً على المسافة بين أعضائها. يتميز التجميع الهرمي بدمج مجموعتين بشكل متكرر.\n", "\n", "

\n", " \n", "

إنفوجرافيك بواسطة داساني ماديبالي
\n", "\n", "\n", "\n", "- **التجميع المركزي**. تتطلب هذه الخوارزمية الشهيرة اختيار \"k\"، أو عدد المجموعات التي سيتم تشكيلها، وبعد ذلك تحدد الخوارزمية النقطة المركزية للمجموعة وتجمع البيانات حول تلك النقطة. [التجميع K-means](https://wikipedia.org/wiki/K-means_clustering) هو نسخة شهيرة من التجميع المركزي الذي يفصل مجموعة البيانات إلى مجموعات K محددة مسبقًا. يتم تحديد المركز بواسطة أقرب متوسط، ومن هنا جاء الاسم. يتم تقليل المسافة المربعة من المجموعة.\n", "\n", "

\n", " \n", "

إنفوجرافيك بواسطة داساني ماديبالي
\n", "\n", "\n", "\n", "- **التجميع القائم على التوزيع**. يعتمد على النمذجة الإحصائية، يركز التجميع القائم على التوزيع على تحديد احتمال انتماء نقطة بيانات إلى مجموعة، وتعيينها وفقًا لذلك. تنتمي طرق Gaussian mixture إلى هذا النوع.\n", "\n", "- **التجميع القائم على الكثافة**. تُعيّن نقاط البيانات إلى مجموعات بناءً على كثافتها، أو تجمعها حول بعضها البعض. تُعتبر نقاط البيانات البعيدة عن المجموعة شذوذًا أو ضوضاء. تنتمي DBSCAN، Mean-shift وOPTICS إلى هذا النوع من التجميع.\n", "\n", "- **التجميع القائم على الشبكة**. بالنسبة لمجموعات البيانات متعددة الأبعاد، يتم إنشاء شبكة وتقسيم البيانات بين خلايا الشبكة، مما يؤدي إلى إنشاء مجموعات.\n", "\n", "أفضل طريقة لتعلم التجميع هي تجربته بنفسك، وهذا ما ستفعله في هذا التمرين.\n", "\n", "سنحتاج إلى بعض الحزم لإكمال هذا الوحدة. يمكنك تثبيتها باستخدام: `install.packages(c('tidyverse', 'tidymodels', 'DataExplorer', 'summarytools', 'plotly', 'paletteer', 'corrplot', 'patchwork'))`\n", "\n", "بدلاً من ذلك، يقوم البرنامج النصي أدناه بالتحقق مما إذا كانت الحزم المطلوبة لإكمال هذا الوحدة مثبتة ويقوم بتثبيتها لك في حالة وجود نقص.\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\r\n", "\r\n", "pacman::p_load('tidyverse', 'tidymodels', 'DataExplorer', 'summarytools', 'plotly', 'paletteer', 'corrplot', 'patchwork')\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "## تمرين - تجميع بياناتك\n", "\n", "التجميع كطريقة يعتمد بشكل كبير على التصور الصحيح، لذا دعونا نبدأ بتصور بيانات الموسيقى الخاصة بنا. هذا التمرين سيساعدنا في تحديد أي من طرق التجميع يمكننا استخدامها بشكل أكثر فعالية بناءً على طبيعة هذه البيانات.\n", "\n", "لنبدأ مباشرة باستيراد البيانات.\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Load the core tidyverse and make it available in your current R session\r\n", "library(tidyverse)\r\n", "\r\n", "# Import the data into a tibble\r\n", "df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\")\r\n", "\r\n", "# View the first 5 rows of the data set\r\n", "df %>% \r\n", " slice_head(n = 5)\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "في بعض الأحيان، قد نرغب في الحصول على معلومات إضافية حول بياناتنا. يمكننا إلقاء نظرة على `البيانات` و`هيكلها` باستخدام وظيفة [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html):\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Glimpse into the data set\r\n", "df %>% \r\n", " glimpse()\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "عمل رائع! 💪\n", "\n", "يمكننا ملاحظة أن `glimpse()` يعرض لك العدد الإجمالي للصفوف (الملاحظات) والأعمدة (المتغيرات)، ثم يعرض أول بضعة إدخالات لكل متغير في صف بعد اسم المتغير. بالإضافة إلى ذلك، يتم عرض *نوع البيانات* الخاص بالمتغير مباشرة بعد اسم المتغير داخل `< >`.\n", "\n", "`DataExplorer::introduce()` يمكنه تلخيص هذه المعلومات بشكل منظم:\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Describe basic information for our data\r\n", "df %>% \r\n", " introduce()\r\n", "\r\n", "# A visual display of the same\r\n", "df %>% \r\n", " plot_intro()\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "رائع! لقد اكتشفنا للتو أن بياناتنا لا تحتوي على أي قيم مفقودة.\n", "\n", "وبينما نحن في هذا السياق، يمكننا استكشاف إحصائيات النزعة المركزية الشائعة (مثل [المتوسط](https://en.wikipedia.org/wiki/Arithmetic_mean) و[الوسيط](https://en.wikipedia.org/wiki/Median)) وقياسات التشتت (مثل [الانحراف المعياري](https://en.wikipedia.org/wiki/Standard_deviation)) باستخدام `summarytools::descr()`\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Describe common statistics\r\n", "df %>% \r\n", " descr(stats = \"common\")\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "دعونا نلقي نظرة على القيم العامة للبيانات. لاحظ أن الشعبية يمكن أن تكون `0`، مما يظهر الأغاني التي ليس لها تصنيف. سنقوم بإزالة تلك قريبًا.\n", "\n", "> 🤔 إذا كنا نعمل مع التجميع، وهي طريقة غير خاضعة للإشراف لا تتطلب بيانات ذات تسميات، فلماذا نعرض هذه البيانات مع تسميات؟ في مرحلة استكشاف البيانات، تكون مفيدة، لكنها ليست ضرورية لعمل خوارزميات التجميع.\n", "\n", "### 1. استكشاف الأنواع الموسيقية الشهيرة\n", "\n", "لنمضي قدمًا ونكتشف الأنواع الموسيقية الأكثر شهرة 🎶 من خلال حساب عدد مرات ظهورها.\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Popular genres\r\n", "top_genres <- df %>% \r\n", " count(artist_top_genre, sort = TRUE) %>% \r\n", "# Encode to categorical and reorder the according to count\r\n", " mutate(artist_top_genre = factor(artist_top_genre) %>% fct_inorder())\r\n", "\r\n", "# Print the top genres\r\n", "top_genres\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "هذا سار بشكل جيد! يقولون إن الصورة تساوي ألف صف من إطار البيانات (في الواقع، لا أحد يقول ذلك أبدًا 😅). لكنك فهمت الفكرة، أليس كذلك؟\n", "\n", "إحدى الطرق لتصور البيانات الفئوية (المتغيرات النصية أو الفئوية) هي استخدام الرسوم البيانية الشريطية. لنقم بإنشاء رسم شريطي لأفضل 10 أنواع:\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Change the default gray theme\r\n", "theme_set(theme_light())\r\n", "\r\n", "# Visualize popular genres\r\n", "top_genres %>%\r\n", " slice(1:10) %>% \r\n", " ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n", " fill = artist_top_genre)) +\r\n", " geom_col(alpha = 0.8) +\r\n", " paletteer::scale_fill_paletteer_d(\"rcartocolor::Vivid\") +\r\n", " ggtitle(\"Top genres\") +\r\n", " theme(plot.title = element_text(hjust = 0.5),\r\n", " # Rotates the X markers (so we can read them)\r\n", " axis.text.x = element_text(angle = 90))\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "الآن أصبح من الأسهل تحديد أن لدينا أنواع موسيقية `مفقودة` 🧐!\n", "\n", "> التصور الجيد سيظهر لك أشياء لم تكن تتوقعها، أو يثير أسئلة جديدة حول البيانات - هادلي ويكهام وغاريت غروليموند، [R For Data Science](https://r4ds.had.co.nz/introduction.html)\n", "\n", "ملاحظة، عندما يتم وصف النوع الموسيقي الأعلى بأنه `مفقود`، فهذا يعني أن Spotify لم يقم بتصنيفه، لذا دعونا نتخلص منه.\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Visualize popular genres\r\n", "top_genres %>%\r\n", " filter(artist_top_genre != \"Missing\") %>% \r\n", " slice(1:10) %>% \r\n", " ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n", " fill = artist_top_genre)) +\r\n", " geom_col(alpha = 0.8) +\r\n", " paletteer::scale_fill_paletteer_d(\"rcartocolor::Vivid\") +\r\n", " ggtitle(\"Top genres\") +\r\n", " theme(plot.title = element_text(hjust = 0.5),\r\n", " # Rotates the X markers (so we can read them)\r\n", " axis.text.x = element_text(angle = 90))\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "من خلال استكشاف البيانات بشكل بسيط، نلاحظ أن الأنواع الثلاثة الأكثر شيوعًا تهيمن على هذه المجموعة من البيانات. دعونا نركز على `afro dancehall`، `afropop`، و`nigerian pop`. بالإضافة إلى ذلك، نقوم بتصفية البيانات لإزالة أي عنصر بقيمة شعبية تساوي 0 (مما يعني أنه لم يتم تصنيفه بشعبية في المجموعة ويمكن اعتباره ضوضاء لأغراضنا):\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "nigerian_songs <- df %>% \r\n", " # Concentrate on top 3 genres\r\n", " filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \r\n", " # Remove unclassified observations\r\n", " filter(popularity != 0)\r\n", "\r\n", "\r\n", "\r\n", "# Visualize popular genres\r\n", "nigerian_songs %>%\r\n", " count(artist_top_genre) %>%\r\n", " ggplot(mapping = aes(x = artist_top_genre, y = n,\r\n", " fill = artist_top_genre)) +\r\n", " geom_col(alpha = 0.8) +\r\n", " paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\r\n", " ggtitle(\"Top genres\") +\r\n", " theme(plot.title = element_text(hjust = 0.5))\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "دعونا نرى ما إذا كانت هناك أي علاقة خطية واضحة بين المتغيرات العددية في مجموعة البيانات الخاصة بنا. يتم قياس هذه العلاقة رياضيًا باستخدام [إحصائية الارتباط](https://en.wikipedia.org/wiki/Correlation).\n", "\n", "إحصائية الارتباط هي قيمة تتراوح بين -1 و 1 تشير إلى قوة العلاقة. القيم التي تزيد عن 0 تشير إلى وجود ارتباط *إيجابي* (تميل القيم العالية لأحد المتغيرات إلى التزامن مع القيم العالية للمتغير الآخر)، بينما القيم التي تقل عن 0 تشير إلى وجود ارتباط *سلبي* (تميل القيم العالية لأحد المتغيرات إلى التزامن مع القيم المنخفضة للمتغير الآخر).\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Narrow down to numeric variables and fid correlation\r\n", "corr_mat <- nigerian_songs %>% \r\n", " select(where(is.numeric)) %>% \r\n", " cor()\r\n", "\r\n", "# Visualize correlation matrix\r\n", "corrplot(corr_mat, order = 'AOE', col = c('white', 'black'), bg = 'gold2') \r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "البيانات ليست مترابطة بشكل قوي باستثناء بين `energy` و `loudness`، وهذا منطقي، نظرًا لأن الموسيقى الصاخبة عادةً ما تكون مليئة بالطاقة. هناك ارتباط بين `Popularity` و `release date`، وهذا أيضًا منطقي، حيث أن الأغاني الحديثة غالبًا ما تكون أكثر شهرة. يبدو أن هناك علاقة بين الطول والطاقة أيضًا.\n", "\n", "سيكون من المثير للاهتمام معرفة ما يمكن أن يفعله خوارزمية التجميع بهذه البيانات!\n", "\n", "> 🎓 لاحظ أن الارتباط لا يعني السببية! لدينا دليل على وجود ارتباط ولكن ليس لدينا دليل على وجود سببية. هناك [موقع ويب ممتع](https://tylervigen.com/spurious-correlations) يحتوي على بعض الرسوم التي تؤكد هذه النقطة.\n", "\n", "### 2. استكشاف توزيع البيانات\n", "\n", "دعونا نطرح بعض الأسئلة الأكثر دقة. هل الأنواع الموسيقية تختلف بشكل كبير في تصور قابليتها للرقص بناءً على شهرتها؟ دعونا نفحص توزيع البيانات لأكثر ثلاثة أنواع موسيقية شهرة من حيث الشعبية وقابلية الرقص على محور x و y باستخدام [مخططات الكثافة](https://www.khanacademy.org/math/ap-statistics/density-curves-normal-distribution-ap/density-curves/v/density-curves).\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# Perform 2D kernel density estimation\r\n", "density_estimate_2d <- nigerian_songs %>% \r\n", " ggplot(mapping = aes(x = popularity, y = danceability, color = artist_top_genre)) +\r\n", " geom_density_2d(bins = 5, size = 1) +\r\n", " paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n", " xlim(-20, 80) +\r\n", " ylim(0, 1.2)\r\n", "\r\n", "# Density plot based on the popularity\r\n", "density_estimate_pop <- nigerian_songs %>% \r\n", " ggplot(mapping = aes(x = popularity, fill = artist_top_genre, color = artist_top_genre)) +\r\n", " geom_density(size = 1, alpha = 0.5) +\r\n", " paletteer::scale_fill_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n", " paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n", " theme(legend.position = \"none\")\r\n", "\r\n", "# Density plot based on the danceability\r\n", "density_estimate_dance <- nigerian_songs %>% \r\n", " ggplot(mapping = aes(x = danceability, fill = artist_top_genre, color = artist_top_genre)) +\r\n", " geom_density(size = 1, alpha = 0.5) +\r\n", " paletteer::scale_fill_paletteer_d(\"RSkittleBrewer::wildberry\") +\r\n", " paletteer::scale_color_paletteer_d(\"RSkittleBrewer::wildberry\")\r\n", "\r\n", "\r\n", "# Patch everything together\r\n", "library(patchwork)\r\n", "density_estimate_2d / (density_estimate_pop + density_estimate_dance)\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "نلاحظ وجود دوائر متداخلة تتماشى مع بعضها البعض، بغض النظر عن النوع الموسيقي. هل يمكن أن تكون الأذواق النيجيرية تتقارب عند مستوى معين من قابلية الرقص لهذا النوع؟\n", "\n", "بشكل عام، تتوافق الأنواع الثلاثة من حيث شعبيتها وقابليتها للرقص. تحديد التجمعات في هذه البيانات غير المرتبطة بشكل وثيق سيكون تحديًا. دعونا نرى ما إذا كان الرسم البياني النقطي يمكن أن يدعم ذلك.\n" ], "metadata": {} }, { "cell_type": "code", "execution_count": null, "source": [ "# A scatter plot of popularity and danceability\r\n", "scatter_plot <- nigerian_songs %>% \r\n", " ggplot(mapping = aes(x = popularity, y = danceability, color = artist_top_genre, shape = artist_top_genre)) +\r\n", " geom_point(size = 2, alpha = 0.8) +\r\n", " paletteer::scale_color_paletteer_d(\"futurevisions::mars\")\r\n", "\r\n", "# Add a touch of interactivity\r\n", "ggplotly(scatter_plot)\r\n" ], "outputs": [], "metadata": {} }, { "cell_type": "markdown", "source": [ "مخطط التبعثر لنفس المحاور يظهر نمطًا مشابهًا للتقارب.\n", "\n", "بشكل عام، بالنسبة للتجميع، يمكنك استخدام مخططات التبعثر لإظهار مجموعات البيانات، لذا فإن إتقان هذا النوع من التصور مفيد جدًا. في الدرس التالي، سنأخذ هذه البيانات المصفاة ونستخدم التجميع باستخدام خوارزمية k-means لاكتشاف مجموعات في هذه البيانات التي تبدو متداخلة بطرق مثيرة للاهتمام.\n", "\n", "## **🚀 التحدي**\n", "\n", "استعدادًا للدرس التالي، قم بإنشاء مخطط حول خوارزميات التجميع المختلفة التي قد تكتشفها وتستخدمها في بيئة الإنتاج. ما هي أنواع المشاكل التي يحاول التجميع معالجتها؟\n", "\n", "## [**اختبار ما بعد المحاضرة**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/28/)\n", "\n", "## **المراجعة والدراسة الذاتية**\n", "\n", "قبل تطبيق خوارزميات التجميع، كما تعلمنا، من الجيد فهم طبيعة مجموعة البيانات الخاصة بك. اقرأ المزيد عن هذا الموضوع [هنا](https://www.kdnuggets.com/2019/10/right-clustering-algorithm.html)\n", "\n", "عمّق فهمك لتقنيات التجميع:\n", "\n", "- [تدريب وتقييم نماذج التجميع باستخدام Tidymodels وأدوات أخرى](https://rpubs.com/eR_ic/clustering)\n", "\n", "- برادلي بومكي وبراندون غرينويل، [*Hands-On Machine Learning with R*](https://bradleyboehmke.github.io/HOML/)*.*\n", "\n", "## **التكليف**\n", "\n", "[ابحث عن تصورات أخرى للتجميع](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/assignment.md)\n", "\n", "## شكر خاص إلى:\n", "\n", "[Jen Looper](https://www.twitter.com/jenlooper) لإنشاء النسخة الأصلية من هذا الوحدة بلغة بايثون ♥️\n", "\n", "[`Dasani Madipalli`](https://twitter.com/dasani_decoded) لإنشاء الرسوم التوضيحية الرائعة التي تجعل مفاهيم تعلم الآلة أكثر قابلية للفهم وأسهل للاستيعاب.\n", "\n", "تعلم سعيد،\n", "\n", "[Eric](https://twitter.com/ericntay)، سفير ذهبي في Microsoft Learn.\n" ], "metadata": {} }, { "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", "language": "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": "99c36449cad3708a435f6798cfa39972", "translation_date": "2025-08-29T15:11:46+00:00", "source_file": "5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb", "language_code": "ar" } }, "nbformat": 4, "nbformat_minor": 1 }