{ "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", "> 🎓 Интересно е, че анализът на клъстери произхожда от областите на антропологията и психологията през 1930-те години. Можете ли да си представите как е бил използван?\n", "\n", "Алтернативно, можете да го използвате за групиране на резултати от търсене - например по връзки за пазаруване, изображения или ревюта. Клъстерирането е полезно, когато имате голям набор от данни, който искате да намалите и върху който искате да извършите по-детайлен анализ, така че техниката може да се използва за изучаване на данни преди изграждането на други модели.\n", "\n", "✅ След като данните ви са организирани в клъстери, им присвоявате идентификатор на клъстер, и тази техника може да бъде полезна за запазване на поверителността на набора от данни; вместо това можете да се позовавате на точка от данни чрез идентификатора на клъстера, вместо чрез по-разкриващи идентифицируеми данни. Можете ли да се сетите за други причини, поради които бихте се позовали на идентификатор на клъстер, вместо на други елементи от клъстера, за да го идентифицирате?\n", "\n", "### Започване с клъстериране\n", "\n", "> 🎓 Как създаваме клъстери има много общо с начина, по който събираме точките от данни в групи. Нека разгледаме някои термини:\n", ">\n", "> 🎓 ['Трансдуктивно' срещу 'индуктивно'](https://wikipedia.org/wiki/Transduction_(machine_learning))\n", ">\n", "> Трансдуктивното заключение се извежда от наблюдавани тренировъчни случаи, които се свързват със специфични тестови случаи. Индуктивното заключение се извежда от тренировъчни случаи, които се свързват с общи правила, които след това се прилагат към тестови случаи.\n", ">\n", "> Пример: Представете си, че имате набор от данни, който е само частично етикетиран. Някои неща са „плочи“, някои „CD-та“, а някои са празни. Вашата задача е да предоставите етикети за празните. Ако изберете индуктивен подход, бихте обучили модел, който търси „плочи“ и „CD-та“, и бихте приложили тези етикети към неетикетираните данни. Този подход ще има проблеми с класифицирането на неща, които всъщност са „касети“. Трансдуктивният подход, от друга страна, се справя с тези неизвестни данни по-ефективно, тъй като работи за групиране на подобни елементи заедно и след това прилага етикет към групата. В този случай клъстерите може да отразяват „кръгли музикални неща“ и „квадратни музикални неща“.\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", "\n", "- **Клъстериране чрез центроид**. Този популярен алгоритъм изисква избор на 'k', или броя на клъстерите, които да се формират, след което алгоритъмът определя централната точка на клъстера и събира данни около тази точка. [K-means клъстериране](https://wikipedia.org/wiki/K-means_clustering) е популярна версия на клъстериране чрез центроид, която разделя набор от данни на предварително дефинирани K групи. Центърът се определя от най-близката средна стойност, откъдето идва и името. Квадратното разстояние от клъстера се минимизира.\n", "\n", "

\n", " \n", "

Инфографика от Дасани Мадипали
\n", "\n", "\n", "\n", "- **Клъстериране, базирано на разпределение**. Основава се на статистическо моделиране, клъстерирането, базирано на разпределение, се фокусира върху определяне на вероятността дадена точка от данни да принадлежи към клъстер и я присвоява съответно. Методите на Гаусова смес принадлежат към този тип.\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`, като допълнително филтрираме набора от данни, за да премахнем всичко с нулева стойност на популярност (което означава, че не е класифицирано с популярност в набора от данни и може да се счита за шум за нашите цели):\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", "- Брадли Бьомке и Брандън Грийнуел, [*Практическо машинно обучение с 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", "[Джен Лупър](https://www.twitter.com/jenlooper) за създаването на оригиналната Python версия на този модул ♥️\n", "\n", "[`Дасани Мадипали`](https://twitter.com/dasani_decoded) за създаването на невероятните илюстрации, които правят концепциите за машинно обучение по-разбираеми и лесни за възприемане.\n", "\n", "Приятно учене,\n", "\n", "[Ерик](https://twitter.com/ericntay), Златен студентски посланик на Microsoft Learn.\n" ], "metadata": {} }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Отказ от отговорност**: \nТози документ е преведен с помощта на AI услуга за превод [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-09-04T07:46:33+00:00", "source_file": "5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb", "language_code": "bg" } }, "nbformat": 4, "nbformat_minor": 1 }