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.
640 lines
28 KiB
640 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-06T14:27:39+00:00",
|
|
"source_file": "5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb",
|
|
"language_code": "sv"
|
|
}
|
|
},
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "GULATlQXLXyR"
|
|
},
|
|
"source": [
|
|
"## Utforska K-Means-klustring med R och principer för Tidy-data.\n",
|
|
"\n",
|
|
"### [**Quiz före föreläsningen**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/29/)\n",
|
|
"\n",
|
|
"I den här lektionen kommer du att lära dig hur man skapar kluster med hjälp av Tidymodels-paketet och andra paket i R-ekosystemet (vi kallar dem vänner 🧑🤝🧑) samt den nigerianska musikdatamängden som du importerade tidigare. Vi kommer att gå igenom grunderna i K-Means för klustring. Kom ihåg att, som du lärde dig i den tidigare lektionen, finns det många sätt att arbeta med kluster, och metoden du använder beror på din data. Vi kommer att prova K-Means eftersom det är den vanligaste klustringstekniken. Nu kör vi!\n",
|
|
"\n",
|
|
"Begrepp du kommer att lära dig om:\n",
|
|
"\n",
|
|
"- Silhuettvärdering\n",
|
|
"\n",
|
|
"- Armbågmetoden\n",
|
|
"\n",
|
|
"- Tröghet\n",
|
|
"\n",
|
|
"- Varians\n",
|
|
"\n",
|
|
"### **Introduktion**\n",
|
|
"\n",
|
|
"[K-Means-klustring](https://wikipedia.org/wiki/K-means_clustering) är en metod som härstammar från signalbehandlingsområdet. Den används för att dela upp och gruppera data i `k kluster` baserat på likheter i deras egenskaper.\n",
|
|
"\n",
|
|
"Klustrerna kan visualiseras som [Voronoi-diagram](https://wikipedia.org/wiki/Voronoi_diagram), som inkluderar en punkt (eller 'frö') och dess motsvarande område.\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/voronoi.png\"\n",
|
|
" width=\"500\"/>\n",
|
|
" <figcaption>Infografik av Jen Looper</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"K-Means-klustring har följande steg:\n",
|
|
"\n",
|
|
"1. Dataanalytikern börjar med att specificera det önskade antalet kluster som ska skapas.\n",
|
|
"\n",
|
|
"2. Därefter väljer algoritmen slumpmässigt K observationer från datamängden som ska fungera som de initiala centren för klustren (dvs. centroiderna).\n",
|
|
"\n",
|
|
"3. Sedan tilldelas varje återstående observation till sin närmaste centroid.\n",
|
|
"\n",
|
|
"4. Därefter beräknas de nya medelvärdena för varje kluster och centroiden flyttas till medelvärdet.\n",
|
|
"\n",
|
|
"5. Nu när centren har räknats om kontrolleras varje observation igen för att se om den kanske är närmare ett annat kluster. Alla objekt tilldelas på nytt med hjälp av de uppdaterade klustermedlen. Stegen för klustertilldelning och centroiduppdatering upprepas iterativt tills klustertilldelningarna slutar förändras (dvs. när konvergens uppnås). Vanligtvis avslutas algoritmen när varje ny iteration resulterar i försumbar rörelse av centroiderna och klustren blir statiska.\n",
|
|
"\n",
|
|
"<div>\n",
|
|
"\n",
|
|
"> Observera att på grund av slumpmässigheten i de initiala k observationerna som används som startcentroider kan vi få något olika resultat varje gång vi tillämpar proceduren. Av denna anledning använder de flesta algoritmer flera *slumpmässiga starter* och väljer iterationen med lägst WCSS. Därför rekommenderas det starkt att alltid köra K-Means med flera värden på *nstart* för att undvika ett *oönskat lokalt optimum.*\n",
|
|
"\n",
|
|
"</div>\n",
|
|
"\n",
|
|
"Den här korta animationen med [illustrationer](https://github.com/allisonhorst/stats-illustrations) av Allison Horst förklarar klustringsprocessen:\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/kmeans.gif\"\n",
|
|
" width=\"550\"/>\n",
|
|
" <figcaption>Illustration av @allison_horst</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"En grundläggande fråga som uppstår vid klustring är denna: hur vet du hur många kluster du ska dela upp din data i? En nackdel med att använda K-Means är att du måste fastställa `k`, det vill säga antalet `centroider`. Lyckligtvis hjälper `armbågmetoden` till att uppskatta ett bra startvärde för `k`. Du kommer att prova det om en stund.\n",
|
|
"\n",
|
|
"### \n",
|
|
"\n",
|
|
"**Förkunskaper**\n",
|
|
"\n",
|
|
"Vi fortsätter precis där vi slutade i [föregående lektion](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb), där vi analyserade datamängden, skapade många visualiseringar och filtrerade datamängden till intressanta observationer. Se till att kolla in den!\n",
|
|
"\n",
|
|
"Vi kommer att behöva några paket för att klara av den här modulen. Du kan installera dem med: `install.packages(c('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork'))`\n",
|
|
"\n",
|
|
"Alternativt kontrollerar skriptet nedan om du har de paket som krävs för att slutföra den här modulen och installerar dem åt dig om några saknas.\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": [
|
|
"## 1. En dans med data: Begränsa till de 3 mest populära musikgenrerna\n",
|
|
"\n",
|
|
"Det här är en sammanfattning av vad vi gjorde i föregående lektion. Låt oss analysera och bearbeta lite data!\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": [
|
|
"🤩 Det gick bra!\n",
|
|
"\n",
|
|
"## 2. Mer datautforskning.\n",
|
|
"\n",
|
|
"Hur ren är denna data? Låt oss kontrollera för avvikare med hjälp av låddiagram. Vi kommer att fokusera på numeriska kolumner med färre avvikare (även om du skulle kunna rensa bort avvikarna). Låddiagram kan visa datans intervall och hjälpa till att välja vilka kolumner som ska användas. Observera att låddiagram inte visar varians, en viktig aspekt av bra data som kan klustras. Se gärna [denna diskussion](https://stats.stackexchange.com/questions/91536/deduce-variance-from-boxplot) för mer information.\n",
|
|
"\n",
|
|
"[Låddiagram](https://en.wikipedia.org/wiki/Box_plot) används för att grafiskt visa fördelningen av `numerisk` data, så låt oss börja med att *välja* alla numeriska kolumner tillsammans med de populära musikgenrerna.\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": [
|
|
"Se hur urvalshjälparen `where` gör detta enkelt 💁? Utforska fler sådana funktioner [här](https://tidyselect.r-lib.org/).\n",
|
|
"\n",
|
|
"Eftersom vi ska skapa ett lådagram för varje numerisk egenskap och vill undvika att använda loopar, låt oss omformatera våra data till ett *längre* format som gör det möjligt för oss att dra nytta av `facets` - delgrafer som var och en visar en delmängd av data.\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": [
|
|
"Mycket längre! Nu är det dags för några `ggplots`! Så vilken `geom` ska vi använda?\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",
|
|
"Nu kan vi se att dessa data är lite brusiga: genom att observera varje kolumn som ett låddiagram kan du se avvikare. Du skulle kunna gå igenom datasetet och ta bort dessa avvikare, men det skulle göra datan ganska minimal.\n",
|
|
"\n",
|
|
"För tillfället, låt oss välja vilka kolumner vi ska använda för vår klusterövning. Låt oss välja de numeriska kolumnerna med liknande intervall. Vi skulle kunna koda `artist_top_genre` som numerisk, men vi hoppar över det för tillfället.\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. Beräkning av k-means-klustring i R\n",
|
|
"\n",
|
|
"Vi kan beräkna k-means i R med den inbyggda funktionen `kmeans`, se `help(\"kmeans()\")`. Funktionen `kmeans()` accepterar en data frame med enbart numeriska kolumner som sitt primära argument.\n",
|
|
"\n",
|
|
"Det första steget när man använder k-means-klustring är att ange antalet kluster (k) som ska genereras i den slutliga lösningen. Vi vet att det finns 3 musikgenrer som vi har identifierat från datasetet, så låt oss prova med 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": [
|
|
"Kmeans-objektet innehåller flera delar av information som förklaras väl i `help(\"kmeans()\")`. För tillfället fokuserar vi på några få. Vi ser att data har delats in i 3 kluster med storlekarna 65, 110, 111. Utdata innehåller också klustercentra (medelvärden) för de 3 grupperna över de 5 variablerna.\n",
|
|
"\n",
|
|
"Klustervektorn är klustertilldelningen för varje observation. Låt oss använda funktionen `augment` för att lägga till klustertilldelningen till den ursprungliga datamängden.\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": [
|
|
"Perfekt, vi har precis delat upp vår dataset i en uppsättning av 3 grupper. Så, hur bra är vår klustring 🤷? Låt oss ta en titt på `Silhouette score`.\n",
|
|
"\n",
|
|
"### **Silhouette score**\n",
|
|
"\n",
|
|
"[Silhouette-analys](https://en.wikipedia.org/wiki/Silhouette_(clustering)) kan användas för att studera separationsavståndet mellan de resulterande klustren. Denna poäng varierar från -1 till 1, och om poängen är nära 1 är klustret tätt och väl separerat från andra kluster. Ett värde nära 0 representerar överlappande kluster med prover som ligger mycket nära beslutsgränsen för de närliggande klustren. [källa](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam).\n",
|
|
"\n",
|
|
"Metoden för genomsnittlig silhouette beräknar den genomsnittliga silhouette för observationer för olika värden av *k*. En hög genomsnittlig silhouette-poäng indikerar en bra klustring.\n",
|
|
"\n",
|
|
"Funktionen `silhouette` i klusterpaketet används för att beräkna den genomsnittliga silhouette-bredden.\n",
|
|
"\n",
|
|
"> Silhouetten kan beräknas med vilken [avståndsmetrik](https://en.wikipedia.org/wiki/Distance \"Distance\") som helst, såsom [Euklidiskt avstånd](https://en.wikipedia.org/wiki/Euclidean_distance \"Euclidean distance\") eller [Manhattan-avstånd](https://en.wikipedia.org/wiki/Manhattan_distance \"Manhattan distance\") som vi diskuterade i [föregående lektion](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": [
|
|
"Vårt resultat är **0,549**, alltså precis i mitten. Detta tyder på att våra data inte är särskilt väl lämpade för den här typen av klustring. Låt oss se om vi kan bekräfta denna misstanke visuellt. Paketet [factoextra](https://rpkgs.datanovia.com/factoextra/index.html) erbjuder funktioner (`fviz_cluster()`) för att visualisera klustring.\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": [
|
|
"Överlappningen i kluster indikerar att vår data inte är särskilt väl lämpad för denna typ av klustring, men låt oss fortsätta.\n",
|
|
"\n",
|
|
"## 4. Bestämma optimalt antal kluster\n",
|
|
"\n",
|
|
"En grundläggande fråga som ofta uppstår vid K-Means-klustring är denna - utan kända klassetiketter, hur vet du hur många kluster du ska dela upp din data i?\n",
|
|
"\n",
|
|
"Ett sätt att försöka ta reda på det är att använda ett dataprovs för att `skapa en serie klustringsmodeller` med ett ökande antal kluster (t.ex. från 1-10) och utvärdera klustringsmått som **Silhouette-poängen.**\n",
|
|
"\n",
|
|
"Låt oss bestämma det optimala antalet kluster genom att beräkna klustringsalgoritmen för olika värden av *k* och utvärdera **Within Cluster Sum of Squares** (WCSS). Den totala inom-kluster-summan av kvadrater (WCSS) mäter klustringens kompakthet, och vi vill att den ska vara så liten som möjligt, där lägre värden innebär att datapunkterna är närmare varandra.\n",
|
|
"\n",
|
|
"Låt oss undersöka effekten av olika val av `k`, från 1 till 10, på denna klustring.\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": [
|
|
"Nu när vi har den totala inomklustersumman av kvadrater (tot.withinss) för varje klustringsalgoritm med centrum *k*, använder vi [elbow-metoden](https://en.wikipedia.org/wiki/Elbow_method_(clustering)) för att hitta det optimala antalet kluster. Metoden innebär att man plottar WCSS som en funktion av antalet kluster och väljer [kurvans \"armbåge\"](https://en.wikipedia.org/wiki/Elbow_of_the_curve \"Elbow of the curve\") som det antal kluster som ska användas.\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": [
|
|
"Diagrammet visar en stor minskning i WCSS (alltså större *sammanhållning*) när antalet kluster ökar från ett till två, och ytterligare en märkbar minskning från två till tre kluster. Därefter blir minskningen mindre framträdande, vilket resulterar i en `armbåge` 💪 i diagrammet vid ungefär tre kluster. Detta är en bra indikation på att det finns två till tre rimligt väl separerade kluster av datapunkter.\n",
|
|
"\n",
|
|
"Vi kan nu gå vidare och extrahera klustermodellen där `k = 3`:\n",
|
|
"\n",
|
|
"> `pull()`: används för att extrahera en enskild kolumn\n",
|
|
">\n",
|
|
"> `pluck()`: används för att indexera datastrukturer såsom listor\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": [
|
|
"Bra! Låt oss visualisera de kluster vi fått fram. Är du sugen på lite interaktivitet med hjälp av `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": [
|
|
"Kanske hade vi förväntat oss att varje kluster (representerat av olika färger) skulle ha distinkta genrer (representerat av olika former).\n",
|
|
"\n",
|
|
"Låt oss ta en titt på modellens noggrannhet.\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": [
|
|
"Den här modellens noggrannhet är inte dålig, men inte heller fantastisk. Det kan vara så att datan inte lämpar sig särskilt väl för K-Means-klustring. Datan är för obalanserad, har för låg korrelation och det finns för mycket variation mellan kolumnvärdena för att klustringen ska fungera bra. Faktum är att de kluster som bildas troligen är starkt påverkade eller snedvridna av de tre genrekategorier vi definierade ovan.\n",
|
|
"\n",
|
|
"Trots det var det en lärorik process!\n",
|
|
"\n",
|
|
"I Scikit-learns dokumentation kan du se att en modell som denna, med kluster som inte är särskilt väl avgränsade, har ett \"varians\"-problem:\n",
|
|
"\n",
|
|
"<p >\n",
|
|
" <img src=\"../../images/problems.png\"\n",
|
|
" width=\"500\"/>\n",
|
|
" <figcaption>Infografik från Scikit-learn</figcaption>\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"## **Varians**\n",
|
|
"\n",
|
|
"Varians definieras som \"medelvärdet av de kvadrerade avvikelserna från medelvärdet\" [källa](https://www.mathsisfun.com/data/standard-deviation.html). I kontexten av detta klustringsproblem syftar det på att siffrorna i vår dataset tenderar att avvika lite för mycket från medelvärdet.\n",
|
|
"\n",
|
|
"✅ Det här är ett bra tillfälle att fundera över alla sätt du kan lösa detta problem. Justera datan lite mer? Använda andra kolumner? Testa en annan algoritm? Tips: Prova att [skala din data](https://www.mygreatlearning.com/blog/learning-data-science-with-k-means-clustering/) för att normalisera den och testa andra kolumner.\n",
|
|
"\n",
|
|
"> Prova denna '[varianskalkylator](https://www.calculatorsoup.com/calculators/statistics/variance-calculator.php)' för att förstå konceptet lite bättre.\n",
|
|
"\n",
|
|
"------------------------------------------------------------------------\n",
|
|
"\n",
|
|
"## **🚀Utmaning**\n",
|
|
"\n",
|
|
"Tillbringa lite tid med denna notebook och justera parametrarna. Kan du förbättra modellens noggrannhet genom att rensa datan mer (till exempel ta bort outliers)? Du kan använda vikter för att ge större vikt åt vissa dataprover. Vad mer kan du göra för att skapa bättre kluster?\n",
|
|
"\n",
|
|
"Tips: Försök att skala din data. Det finns kommenterad kod i notebooken som lägger till standardisering för att få datakolumnerna att likna varandra mer i termer av intervall. Du kommer att märka att även om silhuettpoängen sjunker, så jämnas \"knäet\" i armbågsgrafen ut. Detta beror på att om datan lämnas oskalad, får data med mindre varians större vikt. Läs mer om detta problem [här](https://stats.stackexchange.com/questions/21222/are-mean-normalization-and-feature-scaling-needed-for-k-means-clustering/21226#21226).\n",
|
|
"\n",
|
|
"## [**Efterföreläsningsquiz**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/30/)\n",
|
|
"\n",
|
|
"## **Granskning & Självstudier**\n",
|
|
"\n",
|
|
"- Ta en titt på en K-Means-simulator [som denna](https://user.ceng.metu.edu.tr/~akifakkus/courses/ceng574/k-means/). Du kan använda detta verktyg för att visualisera exempeldata och bestämma dess centroid. Du kan redigera datans slumpmässighet, antal kluster och antal centroid. Hjälper detta dig att få en bättre förståelse för hur datan kan grupperas?\n",
|
|
"\n",
|
|
"- Ta också en titt på [detta handout om K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) från Stanford.\n",
|
|
"\n",
|
|
"Vill du testa dina nyförvärvade klustringskunskaper på dataset som lämpar sig väl för K-Means-klustring? Se:\n",
|
|
"\n",
|
|
"- [Träna och utvärdera klustringsmodeller](https://rpubs.com/eR_ic/clustering) med hjälp av Tidymodels och vänner\n",
|
|
"\n",
|
|
"- [K-means Cluster Analysis](https://uc-r.github.io/kmeans_clustering), UC Business Analytics R Programming Guide\n",
|
|
"\n",
|
|
"- [K-means-klustring med principer för \"tidy data\"](https://www.tidymodels.org/learn/statistics/k-means/)\n",
|
|
"\n",
|
|
"## **Uppgift**\n",
|
|
"\n",
|
|
"[Prova olika klustringsmetoder](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/2-K-Means/assignment.md)\n",
|
|
"\n",
|
|
"## TACK TILL:\n",
|
|
"\n",
|
|
"[Jen Looper](https://www.twitter.com/jenlooper) för att ha skapat den ursprungliga Python-versionen av denna modul ♥️\n",
|
|
"\n",
|
|
"[`Allison Horst`](https://twitter.com/allison_horst/) för att ha skapat de fantastiska illustrationerna som gör R mer välkomnande och engagerande. Hitta fler illustrationer i hennes [galleri](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n",
|
|
"\n",
|
|
"Lycka till med lärandet,\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>Konstverk av @allison_horst</figcaption>\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Ansvarsfriskrivning**: \nDetta dokument har översatts med hjälp av AI-översättningstjänsten [Co-op Translator](https://github.com/Azure/co-op-translator). Även om vi strävar efter noggrannhet, vänligen notera att automatiska översättningar kan innehålla fel eller felaktigheter. Det ursprungliga dokumentet på dess originalspråk bör betraktas som den auktoritativa källan. För kritisk information rekommenderas professionell mänsklig översättning. Vi ansvarar inte för eventuella missförstånd eller feltolkningar som uppstår vid användning av denna översättning.\n"
|
|
]
|
|
}
|
|
]
|
|
} |