You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
639 lines
28 KiB
639 lines
28 KiB
{
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0,
|
|
"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"
|
|
},
|
|
"colab": {
|
|
"name": "lesson_14.ipynb",
|
|
"provenance": [],
|
|
"collapsed_sections": [],
|
|
"toc_visible": true
|
|
},
|
|
"coopTranslator": {
|
|
"original_hash": "ad65fb4aad0a156b42216e4929f490fc",
|
|
"translation_date": "2025-09-06T12:21:23+00:00",
|
|
"source_file": "5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb",
|
|
"language_code": "ro"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "GULATlQXLXyR"
|
|
},
|
|
"source": [
|
|
"## Explorează gruparea K-Means folosind R și principiile datelor ordonate.\n",
|
|
"\n",
|
|
"### [**Chestionar înainte de lecție**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/29/)\n",
|
|
"\n",
|
|
"În această lecție, vei învăța cum să creezi grupuri folosind pachetul Tidymodels și alte pachete din ecosistemul R (le vom numi prieteni 🧑🤝🧑), precum și setul de date despre muzica nigeriană pe care l-ai importat anterior. Vom acoperi elementele de bază ale K-Means pentru grupare. Ține minte că, așa cum ai învățat în lecția anterioară, există multe moduri de a lucra cu grupuri, iar metoda pe care o folosești depinde de datele tale. Vom încerca K-Means, deoarece este cea mai comună tehnică de grupare. Să începem!\n",
|
|
"\n",
|
|
"Termeni pe care îi vei învăța:\n",
|
|
"\n",
|
|
"- Scorul siluetei\n",
|
|
"\n",
|
|
"- Metoda cotului\n",
|
|
"\n",
|
|
"- Inerția\n",
|
|
"\n",
|
|
"- Variația\n",
|
|
"\n",
|
|
"### **Introducere**\n",
|
|
"\n",
|
|
"[Gruparea K-Means](https://wikipedia.org/wiki/K-means_clustering) este o metodă derivată din domeniul procesării semnalelor. Este utilizată pentru a împărți și partitiona grupuri de date în `k grupuri` pe baza similarităților dintre caracteristicile lor.\n",
|
|
"\n",
|
|
"Grupurile pot fi vizualizate ca [diagrame Voronoi](https://wikipedia.org/wiki/Voronoi_diagram), care includ un punct (sau 'sămânță') și regiunea corespunzătoare acestuia.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/voronoi.png\"\n",
|
|
" width=\"500\"/>\n",
|
|
" <figcaption>Infografic de Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"Pașii grupării K-Means sunt următorii:\n",
|
|
"\n",
|
|
"1. Specialistul în date începe prin specificarea numărului dorit de grupuri care urmează să fie create.\n",
|
|
"\n",
|
|
"2. Apoi, algoritmul selectează aleatoriu K observații din setul de date pentru a servi drept centre inițiale pentru grupuri (adică, centroizi).\n",
|
|
"\n",
|
|
"3. Următorul pas este atribuirea fiecărei observații rămase la cel mai apropiat centroid.\n",
|
|
"\n",
|
|
"4. Se calculează noile medii ale fiecărui grup, iar centroidul este mutat la medie.\n",
|
|
"\n",
|
|
"5. Acum că centrele au fost recalibrate, fiecare observație este verificată din nou pentru a vedea dacă ar putea fi mai aproape de un alt grup. Toate obiectele sunt realocate folosind noile medii ale grupurilor. Pașii de atribuire a grupurilor și actualizare a centroizilor sunt repetați iterativ până când atribuirea grupurilor încetează să se schimbe (adică, când se atinge convergența). De obicei, algoritmul se oprește atunci când fiecare nouă iterație rezultă în mișcări neglijabile ale centroizilor, iar grupurile devin statice.\n",
|
|
"\n",
|
|
"<div>\n",
|
|
"\n",
|
|
"> Reține că, din cauza aleatorizării observațiilor inițiale k utilizate ca centroizi de pornire, putem obține rezultate ușor diferite de fiecare dată când aplicăm procedura. Din acest motiv, majoritatea algoritmilor folosesc mai multe *porniri aleatorii* și aleg iterația cu cel mai mic WCSS. Astfel, este puternic recomandat să rulezi întotdeauna K-Means cu mai multe valori de *nstart* pentru a evita un *optimum local nedorit.*\n",
|
|
"\n",
|
|
"</div>\n",
|
|
"\n",
|
|
"Această animație scurtă folosind [ilustrațiile](https://github.com/allisonhorst/stats-illustrations) ale lui Allison Horst explică procesul de grupare:\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/kmeans.gif\"\n",
|
|
" width=\"550\"/>\n",
|
|
" <figcaption>Ilustrație de @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"O întrebare fundamentală care apare în grupare este aceasta: cum știi câte grupuri să separi datele? Un dezavantaj al utilizării K-Means este faptul că va trebui să stabilești `k`, adică numărul de `centroizi`. Din fericire, `metoda cotului` ajută la estimarea unei valori bune de pornire pentru `k`. Vei încerca acest lucru în curând.\n",
|
|
"\n",
|
|
"### \n",
|
|
"\n",
|
|
"**Prerechizite**\n",
|
|
"\n",
|
|
"Vom continua exact de unde am rămas în [lecția anterioară](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb), unde am analizat setul de date, am realizat multe vizualizări și am filtrat setul de date pentru observațiile de interes. Asigură-te că o verifici!\n",
|
|
"\n",
|
|
"Vom avea nevoie de câteva pachete pentru a finaliza acest modul. Le poți instala astfel: `install.packages(c('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork'))`\n",
|
|
"\n",
|
|
"Alternativ, scriptul de mai jos verifică dacă ai pachetele necesare pentru a finaliza acest modul și le instalează pentru tine în cazul în care lipsesc.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "ah_tBi58LXyi"
|
|
},
|
|
"source": [
|
|
"suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n",
|
|
"\n",
|
|
"pacman::p_load('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork')\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "7e--UCUTLXym"
|
|
},
|
|
"source": [
|
|
"Să trecem direct la treabă!\n",
|
|
"\n",
|
|
"## 1. Un dans cu datele: Redu la cele 3 cele mai populare genuri muzicale\n",
|
|
"\n",
|
|
"Aceasta este o recapitulare a ceea ce am făcut în lecția anterioară. Hai să analizăm și să procesăm niște date!\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "Ycamx7GGLXyn"
|
|
},
|
|
"source": [
|
|
"# Load the core tidyverse and make it available in your current R session\n",
|
|
"library(tidyverse)\n",
|
|
"\n",
|
|
"# Import the data into a tibble\n",
|
|
"df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\", show_col_types = FALSE)\n",
|
|
"\n",
|
|
"# Narrow down to top 3 popular genres\n",
|
|
"nigerian_songs <- df %>% \n",
|
|
" # Concentrate on top 3 genres\n",
|
|
" filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \n",
|
|
" # Remove unclassified observations\n",
|
|
" filter(popularity != 0)\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"# Visualize popular genres using bar plots\n",
|
|
"theme_set(theme_light())\n",
|
|
"nigerian_songs %>%\n",
|
|
" count(artist_top_genre) %>%\n",
|
|
" ggplot(mapping = aes(x = artist_top_genre, y = n,\n",
|
|
" fill = artist_top_genre)) +\n",
|
|
" geom_col(alpha = 0.8) +\n",
|
|
" paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\n",
|
|
" ggtitle(\"Top genres\") +\n",
|
|
" theme(plot.title = element_text(hjust = 0.5))\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "b5h5zmkPLXyp"
|
|
},
|
|
"source": [
|
|
"🤩 A mers bine!\n",
|
|
"\n",
|
|
"## 2. Mai multă explorare a datelor.\n",
|
|
"\n",
|
|
"Cât de curate sunt aceste date? Hai să verificăm existența valorilor extreme folosind diagrame de tip boxplot. Ne vom concentra pe coloanele numerice cu mai puține valori extreme (deși ai putea elimina valorile extreme). Boxplot-urile pot arăta intervalul datelor și te vor ajuta să alegi ce coloane să folosești. Reține, boxplot-urile nu arată variația, un element important pentru datele care pot fi grupate eficient. Te rog să consulți [această discuție](https://stats.stackexchange.com/questions/91536/deduce-variance-from-boxplot) pentru mai multe informații.\n",
|
|
"\n",
|
|
"[Boxplot-urile](https://en.wikipedia.org/wiki/Box_plot) sunt utilizate pentru a reprezenta grafic distribuția datelor `numerice`, așa că să începem prin *selectarea* tuturor coloanelor numerice alături de genurile populare de muzică.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "HhNreJKLLXyq"
|
|
},
|
|
"source": [
|
|
"# Select top genre column and all other numeric columns\n",
|
|
"df_numeric <- nigerian_songs %>% \n",
|
|
" select(artist_top_genre, where(is.numeric)) \n",
|
|
"\n",
|
|
"# Display the data\n",
|
|
"df_numeric %>% \n",
|
|
" slice_head(n = 5)\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "uYXrwJRaLXyq"
|
|
},
|
|
"source": [
|
|
"Observați cât de simplu este să folosiți funcția `where` pentru a selecta 💁? Descoperiți alte funcții similare [aici](https://tidyselect.r-lib.org/).\n",
|
|
"\n",
|
|
"Deoarece vom crea un boxplot pentru fiecare caracteristică numerică și dorim să evităm utilizarea buclelor, haideți să reformăm datele noastre într-un format *mai lung* care ne va permite să profităm de `facets` - subgrafice care afișează fiecare un subset al datelor.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "gd5bR3f8LXys"
|
|
},
|
|
"source": [
|
|
"# Pivot data from wide to long\n",
|
|
"df_numeric_long <- df_numeric %>% \n",
|
|
" pivot_longer(!artist_top_genre, names_to = \"feature_names\", values_to = \"values\") \n",
|
|
"\n",
|
|
"# Print out data\n",
|
|
"df_numeric_long %>% \n",
|
|
" slice_head(n = 15)\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "-7tE1swnLXyv"
|
|
},
|
|
"source": [
|
|
"Mult mai detaliat! Acum este momentul pentru câteva `ggplots`! Deci, ce `geom` vom folosi?\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "r88bIsyuLXyy"
|
|
},
|
|
"source": [
|
|
"# Make a box plot\n",
|
|
"df_numeric_long %>% \n",
|
|
" ggplot(mapping = aes(x = feature_names, y = values, fill = feature_names)) +\n",
|
|
" geom_boxplot() +\n",
|
|
" facet_wrap(~ feature_names, ncol = 4, scales = \"free\") +\n",
|
|
" theme(legend.position = \"none\")\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "EYVyKIUELXyz"
|
|
},
|
|
"source": [
|
|
"Easy-gg!\n",
|
|
"\n",
|
|
"Acum putem observa că aceste date sunt puțin zgomotoase: analizând fiecare coloană ca un boxplot, poți vedea valori extreme. Ai putea parcurge setul de date și elimina aceste valori extreme, dar asta ar face ca datele să fie destul de limitate.\n",
|
|
"\n",
|
|
"Deocamdată, să alegem coloanele pe care le vom folosi pentru exercițiul de grupare. Să selectăm coloanele numerice cu intervale similare. Am putea codifica `artist_top_genre` ca numeric, dar îl vom elimina pentru moment.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "-wkpINyZLXy0"
|
|
},
|
|
"source": [
|
|
"# Select variables with similar ranges\n",
|
|
"df_numeric_select <- df_numeric %>% \n",
|
|
" select(popularity, danceability, acousticness, loudness, energy) \n",
|
|
"\n",
|
|
"# Normalize data\n",
|
|
"# df_numeric_select <- scale(df_numeric_select)\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "D7dLzgpqLXy1"
|
|
},
|
|
"source": [
|
|
"## 3. Calcularea clusteringului k-means în R\n",
|
|
"\n",
|
|
"Putem calcula k-means în R folosind funcția integrată `kmeans`, vezi `help(\"kmeans()\")`. Funcția `kmeans()` acceptă un cadru de date cu toate coloanele numerice ca argument principal.\n",
|
|
"\n",
|
|
"Primul pas atunci când utilizăm clusteringul k-means este să specificăm numărul de clustere (k) care vor fi generate în soluția finală. Știm că există 3 genuri muzicale pe care le-am extras din setul de date, așa că să încercăm cu 3:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "uC4EQ5w7LXy5"
|
|
},
|
|
"source": [
|
|
"set.seed(2056)\n",
|
|
"# Kmeans clustering for 3 clusters\n",
|
|
"kclust <- kmeans(\n",
|
|
" df_numeric_select,\n",
|
|
" # Specify the number of clusters\n",
|
|
" centers = 3,\n",
|
|
" # How many random initial configurations\n",
|
|
" nstart = 25\n",
|
|
")\n",
|
|
"\n",
|
|
"# Display clustering object\n",
|
|
"kclust\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "hzfhscWrLXy-"
|
|
},
|
|
"source": [
|
|
"Obiectul kmeans conține mai multe informații care sunt bine explicate în `help(\"kmeans()\")`. Deocamdată, să ne concentrăm pe câteva dintre ele. Observăm că datele au fost grupate în 3 clustere de dimensiuni 65, 110, 111. Rezultatul conține, de asemenea, centrele clusterelor (medii) pentru cele 3 grupuri pe cele 5 variabile.\n",
|
|
"\n",
|
|
"Vectorul de clustering reprezintă atribuirea clusterului pentru fiecare observație. Să folosim funcția `augment` pentru a adăuga atribuirea clusterului la setul de date original.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "0XwwpFGQLXy_"
|
|
},
|
|
"source": [
|
|
"# Add predicted cluster assignment to data set\n",
|
|
"augment(kclust, df_numeric_select) %>% \n",
|
|
" relocate(.cluster) %>% \n",
|
|
" slice_head(n = 10)\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "NXIVXXACLXzA"
|
|
},
|
|
"source": [
|
|
"Perfect, tocmai am împărțit setul nostru de date în 3 grupuri. Deci, cât de bună este gruparea noastră 🤷? Haideți să aruncăm o privire la `Scorul Silhouette`.\n",
|
|
"\n",
|
|
"### **Scorul Silhouette**\n",
|
|
"\n",
|
|
"[Analiza Silhouette](https://en.wikipedia.org/wiki/Silhouette_(clustering)) poate fi utilizată pentru a studia distanța de separare dintre grupurile rezultate. Acest scor variază de la -1 la 1, iar dacă scorul este aproape de 1, grupul este dens și bine separat de celelalte grupuri. O valoare aproape de 0 reprezintă grupuri care se suprapun, cu mostre foarte apropiate de limita de decizie a grupurilor vecine. [sursa](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam).\n",
|
|
"\n",
|
|
"Metoda mediei Silhouette calculează media scorurilor Silhouette ale observațiilor pentru diferite valori ale *k*. Un scor mediu Silhouette ridicat indică o grupare bună.\n",
|
|
"\n",
|
|
"Funcția `silhouette` din pachetul cluster este utilizată pentru a calcula lățimea medie a Silhouette.\n",
|
|
"\n",
|
|
"> Silhouette poate fi calculat cu orice [metrică de distanță](https://en.wikipedia.org/wiki/Distance \"Distance\"), cum ar fi [distanța Euclidiană](https://en.wikipedia.org/wiki/Euclidean_distance \"Euclidean distance\") sau [distanța Manhattan](https://en.wikipedia.org/wiki/Manhattan_distance \"Manhattan distance\"), pe care le-am discutat în [lecția anterioară](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb).\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "Jn0McL28LXzB"
|
|
},
|
|
"source": [
|
|
"# Load cluster package\n",
|
|
"library(cluster)\n",
|
|
"\n",
|
|
"# Compute average silhouette score\n",
|
|
"ss <- silhouette(kclust$cluster,\n",
|
|
" # Compute euclidean distance\n",
|
|
" dist = dist(df_numeric_select))\n",
|
|
"mean(ss[, 3])\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "QyQRn97nLXzC"
|
|
},
|
|
"source": [
|
|
"Scorul nostru este **.549**, deci exact la mijloc. Acest lucru indică faptul că datele noastre nu sunt deosebit de potrivite pentru acest tip de grupare. Să vedem dacă putem confirma această bănuială vizual. Pachetul [factoextra](https://rpkgs.datanovia.com/factoextra/index.html) oferă funcții (`fviz_cluster()`) pentru a vizualiza gruparea.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "7a6Km1_FLXzD"
|
|
},
|
|
"source": [
|
|
"library(factoextra)\n",
|
|
"\n",
|
|
"# Visualize clustering results\n",
|
|
"fviz_cluster(kclust, df_numeric_select)\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "IBwCWt-0LXzD"
|
|
},
|
|
"source": [
|
|
"Suprapunerea dintre clustere indică faptul că datele noastre nu sunt foarte potrivite pentru acest tip de clustering, dar să continuăm.\n",
|
|
"\n",
|
|
"## 4. Determinarea numărului optim de clustere\n",
|
|
"\n",
|
|
"O întrebare fundamentală care apare frecvent în clusteringul K-Means este aceasta - fără etichete de clasă cunoscute, cum știi în câte clustere să împarți datele?\n",
|
|
"\n",
|
|
"O modalitate prin care putem încerca să aflăm este să folosim un eșantion de date pentru a `crea o serie de modele de clustering` cu un număr crescător de clustere (de exemplu, de la 1 la 10) și să evaluăm metrici de clustering, cum ar fi **scorul Silhouette.**\n",
|
|
"\n",
|
|
"Să determinăm numărul optim de clustere calculând algoritmul de clustering pentru diferite valori ale *k* și evaluând **Suma pătratelor din interiorul clusterelor** (WCSS). Suma totală a pătratelor din interiorul clusterelor (WCSS) măsoară compactitatea clusteringului, iar noi dorim să fie cât mai mică posibil, valorile mai mici indicând că punctele de date sunt mai apropiate.\n",
|
|
"\n",
|
|
"Să explorăm efectul diferitelor alegeri ale lui `k`, de la 1 la 10, asupra acestui clustering.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "hSeIiylDLXzE"
|
|
},
|
|
"source": [
|
|
"# Create a series of clustering models\n",
|
|
"kclusts <- tibble(k = 1:10) %>% \n",
|
|
" # Perform kmeans clustering for 1,2,3 ... ,10 clusters\n",
|
|
" mutate(model = map(k, ~ kmeans(df_numeric_select, centers = .x, nstart = 25)),\n",
|
|
" # Farm out clustering metrics eg WCSS\n",
|
|
" glanced = map(model, ~ glance(.x))) %>% \n",
|
|
" unnest(cols = glanced)\n",
|
|
" \n",
|
|
"\n",
|
|
"# View clustering rsulsts\n",
|
|
"kclusts\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "m7rS2U1eLXzE"
|
|
},
|
|
"source": [
|
|
"Acum că avem suma totală a pătratelor din interiorul clusterelor (tot.withinss) pentru fiecare algoritm de grupare cu centrul *k*, folosim [metoda cotului](https://en.wikipedia.org/wiki/Elbow_method_(clustering)) pentru a determina numărul optim de clustere. Metoda constă în reprezentarea grafică a WCSS în funcție de numărul de clustere și alegerea [cotului curbei](https://en.wikipedia.org/wiki/Elbow_of_the_curve \"Elbow of the curve\") ca număr de clustere de utilizat.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "o_DjHGItLXzF"
|
|
},
|
|
"source": [
|
|
"set.seed(2056)\n",
|
|
"# Use elbow method to determine optimum number of clusters\n",
|
|
"kclusts %>% \n",
|
|
" ggplot(mapping = aes(x = k, y = tot.withinss)) +\n",
|
|
" geom_line(size = 1.2, alpha = 0.8, color = \"#FF7F0EFF\") +\n",
|
|
" geom_point(size = 2, color = \"#FF7F0EFF\")\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "pLYyt5XSLXzG"
|
|
},
|
|
"source": [
|
|
"Graficul arată o reducere semnificativă a WCSS (deci o *strângere* mai mare) pe măsură ce numărul de clustere crește de la unul la două, și o reducere vizibilă suplimentară de la două la trei clustere. După aceea, reducerea este mai puțin pronunțată, rezultând un `cot` 💪 în grafic în jurul valorii de trei clustere. Acesta este un indiciu bun că există două până la trei clustere de puncte de date, destul de bine separate.\n",
|
|
"\n",
|
|
"Acum putem merge mai departe și extrage modelul de clustering unde `k = 3`:\n",
|
|
"\n",
|
|
"> `pull()`: folosit pentru a extrage o singură coloană\n",
|
|
">\n",
|
|
"> `pluck()`: folosit pentru a indexa structuri de date precum liste\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "JP_JPKBILXzG"
|
|
},
|
|
"source": [
|
|
"# Extract k = 3 clustering\n",
|
|
"final_kmeans <- kclusts %>% \n",
|
|
" filter(k == 3) %>% \n",
|
|
" pull(model) %>% \n",
|
|
" pluck(1)\n",
|
|
"\n",
|
|
"\n",
|
|
"final_kmeans\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "l_PDTu8tLXzI"
|
|
},
|
|
"source": [
|
|
"Minunat! Haide să vizualizăm clusterele obținute. Îți surâde ideea de a adăuga un pic de interactivitate folosind `plotly`?\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "dNcleFe-LXzJ"
|
|
},
|
|
"source": [
|
|
"# Add predicted cluster assignment to data set\n",
|
|
"results <- augment(final_kmeans, df_numeric_select) %>% \n",
|
|
" bind_cols(df_numeric %>% select(artist_top_genre)) \n",
|
|
"\n",
|
|
"# Plot cluster assignments\n",
|
|
"clust_plt <- results %>% \n",
|
|
" ggplot(mapping = aes(x = popularity, y = danceability, color = .cluster, shape = artist_top_genre)) +\n",
|
|
" geom_point(size = 2, alpha = 0.8) +\n",
|
|
" paletteer::scale_color_paletteer_d(\"ggthemes::Tableau_10\")\n",
|
|
"\n",
|
|
"ggplotly(clust_plt)\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "6JUM_51VLXzK"
|
|
},
|
|
"source": [
|
|
"Poate că ne-am fi așteptat ca fiecare grup (reprezentat prin culori diferite) să aibă genuri distincte (reprezentate prin forme diferite).\n",
|
|
"\n",
|
|
"Să analizăm acuratețea modelului.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {
|
|
"id": "HdIMUGq7LXzL"
|
|
},
|
|
"source": [
|
|
"# Assign genres to predefined integers\n",
|
|
"label_count <- results %>% \n",
|
|
" group_by(artist_top_genre) %>% \n",
|
|
" mutate(id = cur_group_id()) %>% \n",
|
|
" ungroup() %>% \n",
|
|
" summarise(correct_labels = sum(.cluster == id))\n",
|
|
"\n",
|
|
"\n",
|
|
"# Print results \n",
|
|
"cat(\"Result:\", label_count$correct_labels, \"out of\", nrow(results), \"samples were correctly labeled.\")\n",
|
|
"\n",
|
|
"cat(\"\\nAccuracy score:\", label_count$correct_labels/nrow(results))\n"
|
|
],
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "C50wvaAOLXzM"
|
|
},
|
|
"source": [
|
|
"Acuratețea acestui model nu este rea, dar nici grozavă. Este posibil ca datele să nu fie potrivite pentru Clustering K-Means. Aceste date sunt prea dezechilibrate, prea puțin corelate și există prea multă variație între valorile coloanelor pentru a forma clustere eficiente. De fapt, clusterele care se formează sunt probabil puternic influențate sau distorsionate de cele trei categorii de genuri pe care le-am definit mai sus.\n",
|
|
"\n",
|
|
"Cu toate acestea, a fost un proces de învățare destul de interesant!\n",
|
|
"\n",
|
|
"În documentația Scikit-learn, puteți vedea că un model ca acesta, cu clustere care nu sunt foarte bine delimitate, are o problemă de 'varianță':\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/problems.png\"\n",
|
|
" width=\"500\"/>\n",
|
|
" <figcaption>Infografic din Scikit-learn</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"## **Varianță**\n",
|
|
"\n",
|
|
"Varianța este definită ca \"media diferențelor pătrate față de medie\" [sursa](https://www.mathsisfun.com/data/standard-deviation.html). În contextul acestei probleme de clustering, se referă la datele în care valorile din setul nostru de date tind să se abată prea mult de la medie.\n",
|
|
"\n",
|
|
"✅ Acesta este un moment excelent pentru a reflecta asupra tuturor modalităților prin care ați putea corecta această problemă. Ajustați puțin datele? Folosiți alte coloane? Utilizați un algoritm diferit? Sugestie: Încercați [scalarea datelor](https://www.mygreatlearning.com/blog/learning-data-science-with-k-means-clustering/) pentru a le normaliza și testați alte coloane.\n",
|
|
"\n",
|
|
"> Încercați acest '[calculator de varianță](https://www.calculatorsoup.com/calculators/statistics/variance-calculator.php)' pentru a înțelege mai bine conceptul.\n",
|
|
"\n",
|
|
"------------------------------------------------------------------------\n",
|
|
"\n",
|
|
"## **🚀Provocare**\n",
|
|
"\n",
|
|
"Petreceți ceva timp cu acest notebook, ajustând parametrii. Puteți îmbunătăți acuratețea modelului prin curățarea mai riguroasă a datelor (eliminarea valorilor extreme, de exemplu)? Puteți folosi ponderi pentru a acorda mai multă importanță anumitor eșantioane de date. Ce altceva puteți face pentru a crea clustere mai bune?\n",
|
|
"\n",
|
|
"Sugestie: Încercați să scalați datele. Există cod comentat în notebook care adaugă scalarea standard pentru a face ca coloanele de date să semene mai mult între ele în ceea ce privește intervalul. Veți observa că, deși scorul siluetei scade, 'cotul' din graficul elbow devine mai neted. Acest lucru se întâmplă deoarece lăsarea datelor nescalate permite datelor cu mai puțină varianță să aibă o influență mai mare. Citiți mai multe despre această problemă [aici](https://stats.stackexchange.com/questions/21222/are-mean-normalization-and-feature-scaling-needed-for-k-means-clustering/21226#21226).\n",
|
|
"\n",
|
|
"## [**Quiz post-lectură**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/30/)\n",
|
|
"\n",
|
|
"## **Recapitulare & Studiu individual**\n",
|
|
"\n",
|
|
"- Aruncați o privire la un Simulator K-Means [cum ar fi acesta](https://user.ceng.metu.edu.tr/~akifakkus/courses/ceng574/k-means/). Puteți folosi acest instrument pentru a vizualiza punctele de date eșantionate și pentru a determina centroizii acestora. Puteți edita aleatoritatea datelor, numărul de clustere și numărul de centroizi. Vă ajută acest lucru să înțelegeți mai bine cum pot fi grupate datele?\n",
|
|
"\n",
|
|
"- De asemenea, consultați [acest material despre K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) de la Stanford.\n",
|
|
"\n",
|
|
"Doriți să vă testați noile abilități de clustering pe seturi de date care se potrivesc bine cu Clustering K-Means? Consultați:\n",
|
|
"\n",
|
|
"- [Antrenați și evaluați modele de clustering](https://rpubs.com/eR_ic/clustering) folosind Tidymodels și prietenii\n",
|
|
"\n",
|
|
"- [Analiza clusterelor K-Means](https://uc-r.github.io/kmeans_clustering), Ghidul de Programare Analitică UC Business\n",
|
|
"\n",
|
|
"- [Clustering K-Means cu principii de date ordonate](https://www.tidymodels.org/learn/statistics/k-means/)\n",
|
|
"\n",
|
|
"## **Temă**\n",
|
|
"\n",
|
|
"[Încercați metode diferite de clustering](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/2-K-Means/assignment.md)\n",
|
|
"\n",
|
|
"## MULȚUMIRI SPECIALE:\n",
|
|
"\n",
|
|
"[Jen Looper](https://www.twitter.com/jenlooper) pentru crearea versiunii originale în Python a acestui modul ♥️\n",
|
|
"\n",
|
|
"[`Allison Horst`](https://twitter.com/allison_horst/) pentru crearea ilustrațiilor uimitoare care fac R mai accesibil și captivant. Găsiți mai multe ilustrații în [galeria ei](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
|
|
"\n",
|
|
"Învățare plăcută,\n",
|
|
"\n",
|
|
"[Eric](https://twitter.com/ericntay), Gold Microsoft Learn Student Ambassador.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/r_learners_sm.jpeg\"\n",
|
|
" width=\"500\"/>\n",
|
|
" <figcaption>Ilustrație de @allison_horst</figcaption>\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Declinarea responsabilității**: \nAcest document a fost tradus folosind serviciul de traducere AI [Co-op Translator](https://github.com/Azure/co-op-translator). Deși depunem eforturi pentru a asigura acuratețea, vă rugăm să aveți în vedere că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa nativă ar trebui considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist. Nu ne asumăm răspunderea pentru eventualele neînțelegeri sau interpretări greșite care pot apărea din utilizarea acestei traduceri.\n"
|
|
]
|
|
}
|
|
]
|
|
} |