K-mijloace ClusterProgramare în R cu exemplu
⚡ Rezumat inteligent
K-înseamnă ClusterGruparea în R a observațiilor prin minimizarea distanței dintre fiecare punct și centroidul clusterului său. Această demonstrație standardizează setul de date privind prețurile computerizate, animează algoritmul, găsește k optim cu metoda cotului și citește clusterele printr-o hartă termică.

Ce Este Cluster analiză?
Cluster analiza aparține învățare nesupravegheată. Un cluster este un grup de date care au caracteristici similare. Putem spune că analiza grupării este mai mult despre descoperire decât despre o predicție. Aparatul caută asemănarea datelor. De exemplu, puteți utiliza analiza cluster pentru următoarea aplicație:
- Segmentarea clienților: caută asemănarea între grupurile de clienți
- Gruparea pieței de valori: acțiunile grupului pe baza performanțelor
- Reducerea dimensionalității unui set de date prin grupareping observații cu valori similare
ClusterAnaliza nu este prea dificil de implementat și este semnificativă și acționabilă pentru afaceri.
Cea mai izbitoare diferență între învățarea supravegheată și nesupravegheată constă în rezultate. Învățarea nesupravegheată creează o nouă variabilă, eticheta, în timp ce învățarea supravegheată prezice un rezultat. Aparatul ajută practicantul în încercarea de a eticheta datele pe baza unei strânse relații. Depinde de analist să folosească grupurile și să le dea un nume.
Să facem un exemplu pentru a înțelege conceptul de clustering. Pentru simplitate, lucrăm în două dimensiuni. Aveți date despre cheltuielile totale ale clienților și vârstele acestora. Pentru a îmbunătăți publicitatea, echipa de marketing dorește să trimită e-mailuri mai bine direcționate clienților lor.
În graficul următor, reprezentați cheltuiala totală și vârsta clienților.
library(ggplot2) df <- data.frame(age = c(18, 21, 22, 24, 26, 26, 27, 30, 31, 35, 39, 40, 41, 42, 44, 46, 47, 48, 49, 54), spend = c(10, 11, 22, 15, 12, 13, 14, 33, 39, 37, 44, 27, 29, 20, 28, 21, 30, 31, 23, 24) ) ggplot(df, aes(x = age, y = spend)) + geom_point()
Un model este vizibil în acest moment
- În stânga jos, puteți vedea tineri cu o putere de cumpărare mai mică
- Mijlocul superior reflectă oamenii cu un loc de muncă pe care își pot permite să cheltuiască mai mult
- În sfârșit, persoanele în vârstă cu un buget mai mic.
În figura de mai sus, grupați observațiile manual și definiți fiecare dintre cele trei grupuri. Acest exemplu este oarecum simplu și foarte vizual. Dacă se adaugă observații noi la setul de date, le puteți eticheta în cercuri. Definiți cercul pe baza judecății noastre. În schimb, puteți folosi Invatare mecanica pentru a grupa datele în mod obiectiv.
În acest tutorial, veți învăța cum să utilizați k-înseamnă algoritm.
Algoritmul K-Means
K-means este cea mai utilizată metodă de clustering. Algoritmul datează din anii 1950 și a fost rafinat de multe ori de atunci.
Algoritmul încearcă să găsească grupuri reducând la minimum distanța dintre observații, numite optim local soluții. Distanțele sunt măsurate pe baza coordonatelor observațiilor. De exemplu, într-un spațiu bidimensional, coordonatele sunt pur și simplu x și y.
Algoritmul funcționează după cum urmează:
- Pasul 1: Alegeți k centroizi inițiali la întâmplare în spațiul de caracteristici
- Pasul 2: Atribuiți fiecare observație celui mai apropiat centru al clusterului, centroidAceasta produce k grupuri
- Pasul 3: Shift centroidul inițial la media coordonatelor dintr-un grup.
- Pasul 4: Minimizați distanța conform noilor centroizi. Sunt create noi granițe. Astfel, observațiile se vor muta de la un grup la altul
- Repetați până când nicio observație nu schimbă grupurile
K-means măsoară în mod normal distanța euclidiană dintre două observații x și y:
Sunt disponibile și alte măsuri, cum ar fi distanța Manhattan sau Minkowski. Rețineți că K-mean returnează grupuri diferite de fiecare dată când rulați algoritmul. Rețineți că primele estimări inițiale sunt aleatorii și calculați distanțele până când algoritmul atinge o omogenitate în cadrul grupurilor. Adică, k-mean este foarte sensibil la prima alegere și, dacă numărul de observații și grupuri nu este mic, este aproape imposibil să obțineți aceeași grupare.
Selectarea numărului de clustere
O altă dificultate întâlnită cu k-mean este alegerea numărului de clustere. Puteți seta o valoare mare a lui k, adică un număr mare de grupuri, pentru a îmbunătăți omogenitatea în cadrul grupului, dar riscați supraîncadrarea datele. Supraadaptarea înseamnă că performanța scade brusc la date noi, deoarece modelul a memorat zgomotul din acest eșantion particular, mai degrabă decât modelul subiacent.
Numărul de clustere depinde de natura setului de date, de industrie, de afaceri și așa mai departe. Cu toate acestea, există o regulă generală pentru a selecta numărul adecvat de clustere:
unde n este numărul de observații din setul de date.
În practică, merită să petreceți timp căutând valoarea lui k care se potrivește cel mai bine nevoilor afacerii.
Vom folosi setul de date Prețurile computerelor personale pentru a efectua analiza noastră de grupare. Acest set de date conține 6259 de observații și 10 caracteristici. Setul de date observă prețul din 1993 până în 1995 a 486 de computere personale din SUA. Variabilele sunt preț, viteză, ram, ecran, cd, printre altele.
Veți proceda după cum urmează:
- Date de import
- Antrenează modelul
- Evaluați modelul
Date de import
K-means nu este potrivit pentru variabilele factoriale, deoarece funcționează pe distanțe, iar etichetele discrete nu au o distanță semnificativă între ele. Eliminați cele trei coloane categorice (cd, multi, premium) împreună cu indicele de rând X. Acest set de date nu conține valori lipsă.
library(dplyr) PATH <-"https://raw.githubusercontent.com/guru99-edu/R-Programming/master/computers.csv" df <- read.csv(PATH) %>% select(-c(X, cd, multi, premium)) glimpse(df)
producție
## Observations: 6,259 ## Variables: 7 ## $ price <int> 1499, 1795, 1595, 1849, 3295, 3695, 1720, 1995, 2225, 2... ## $ speed <int> 25, 33, 25, 25, 33, 66, 25, 50, 50, 50, 33, 66, 50, 25, ... ## $ hd <int> 80, 85, 170, 170, 340, 340, 170, 85, 210, 210, 170, 210... ## $ ram <int> 4, 2, 4, 8, 16, 16, 4, 2, 8, 4, 8, 8, 4, 8, 8, 4, 2, 4, ... ## $ screen <int> 14, 14, 15, 14, 14, 14, 14, 14, 14, 15, 15, 14, 14, 14, ... ## $ ads <int> 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, ... ## $ trend <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
Din statisticile rezumative, puteți observa că datele au valori mari. O practică bună înainte de orice metodă bazată pe distanță este standardizarea datelor astfel încât fiecare variabilă să aibă un medie de zero și o abatere standard de unuFără aceasta, prețul, ale cărui valori se ridică la mii, ar domina calculul distanței, iar dimensiunea ecranului nu ar conta aproape deloc.
summary(df)
ieșire:
## price speed hd ram ## Min. : 949 Min. : 25.00 Min. : 80.0 Min. : 2.000 ## 1st Qu.:1794 1st Qu.: 33.00 1st Qu.: 214.0 1st Qu.: 4.000 ## Median :2144 Median : 50.00 Median : 340.0 Median : 8.000 ## Mean :2220 Mean : 52.01 Mean : 416.6 Mean : 8.287 ## 3rd Qu.:2595 3rd Qu.: 66.00 3rd Qu.: 528.0 3rd Qu.: 8.000 ## Max. :5399 Max. :100.00 Max. :2100.0 Max. :32.000 ## screen ads trend ## Min. :14.00 Min. : 39.0 Min. : 1.00 ## 1st Qu.:14.00 1st Qu.:162.5 1st Qu.:10.00 ## Median :14.00 Median :246.0 Median :16.00 ## Mean :14.61 Mean :221.3 Mean :15.93 ## 3rd Qu.:15.00 3rd Qu.:275.0 3rd Qu.:21.50 ## Max. :17.00 Max. :339.0 Max. :35.00
Redimensionați variabilele cu funcția scale() a bibliotecii dplyr. Transformarea reduce impactul valorii aberante și permite compararea unei singure observații cu media. Dacă o valoare standardizată (sau scor z) este mare, puteți fi sigur că această observație este într-adevăr peste medie (un scor z mare implică faptul că acest punct este departe de medie în termeni de abatere standard. Un scor z de doi indică valoarea 2 standard). abateri de la medie. Rețineți că scorul z urmează o distribuție Gaussiană și este simetric în jurul mediei.
# Note: speed is deliberately left out of the scaled data frame rescale_df <- df %>% mutate(price_scal = scale(price), hd_scal = scale(hd), ram_scal = scale(ram), screen_scal = scale(screen), ads_scal = scale(ads), trend_scal = scale(trend)) %>% select(-c(price, speed, hd, ram, screen, ads, trend))
R baza are o funcție pentru a rula algoritmul k mediu. Funcția de bază a mediei k este:
kmeans(df, k) arguments: -df: dataset used to run the algorithm -k: Number of clusters
Antrenează modelul
În figura trei, ați detaliat cum funcționează algoritmul. Puteți urmări fiecare pas grafic cu pachetul de animație scris de Yihui Xie, care a creat și knitr pentru R Markdown. Pachetul nu se află în canalele conda, așa că instalați-l din CRAN:
install.packages("animation")
După ce încărcați biblioteca, adăugați .ani după kmeans și R va trasa toți pașii. În scop ilustrativ, rulați algoritmul doar cu variabilele redimensionate hd și ram cu trei clustere.
set.seed(2345) library(animation) kmeans.ani(rescale_df[2:3], 3)
Code Explicație
- kmeans.ani(rescale_df[2:3], 3): Selectați coloanele 2 și 3 din setul de date rescale_df și rulați algoritmul cu k seturi la 3. Trasați animația.
Puteți interpreta animația după cum urmează:
- Pasul 1: R alege aleatoriu trei puncte
- Pasul 2: Calculați distanța euclidiană și desenați clusterele. Aveți un grup în verde în stânga jos, un grup mare colorat în negru în dreapta și unul roșu între ele.
- Pasul 3: Calculați centroidul, adică media clusterelor
- Repetați până când niciun cluster nu se modifică de date
Algoritmul a convergit după șapte iterații. Puteți rula algoritmul k-mean în setul nostru de date cu cinci clustere și îl puteți numi pc_cluster.
pc_cluster <-kmeans(rescale_df, 5)
Lista pc_cluster conține șapte elemente utile:
- pc_cluster$cluster: Clusterul atribuit fiecărei observații
- pc_cluster$centers: Clusterul se centrează
- pc_cluster$totss: suma totală de pătrate
- pc_cluster$withinss: În limita sumei pătratelor, o valoare per cluster
- pc_cluster$tot.withinss: Suma dintre withinss
- pc_cluster$betweenss: Suma totală a pătratelor minus suma pătratelor din interiorul grupului
- pc_cluster$size: Numărul de observații din fiecare cluster
Veți folosi suma dintre suma pătratului (adică tot.withinss) pentru a calcula numărul optim de clustere k. Găsirea k este într-adevăr o sarcină substanțială.
Cum să găsești k-ul optim cu metoda cotului
O tehnică de a alege cel mai bun k se numește metoda cotului. Această metodă utilizează omogenitatea în interiorul grupului sau eterogenitatea în interiorul grupului pentru a evalua variabilitatea. Cu alte cuvinte, sunteți interesat de procentul de varianță explicat de fiecare cluster. Vă puteți aștepta ca variabilitatea să crească odată cu numărul de clustere, alternativ, eterogenitatea scade. Provocarea noastră este să găsim k care este dincolo de randamentele descrescătoare. Adăugarea unui cluster nou nu îmbunătățește variabilitatea datelor deoarece au rămas foarte puține informații de explicat.
În acest tutorial, găsim acest punct utilizând măsura eterogenității. Suma totală a pătratelor din clustere este tot.withinss din lista returnată de kmean().
Puteți construi graficul cotului și puteți găsi k optim după cum urmează:
- Pasul 1: Construiți o funcție pentru a calcula suma de pătrate totală în cadrul clusterelor
- Pasul 2: Rulați algoritmul pe un interval de k valori
- Pasul 3: Creați un cadru de date cu rezultatele algoritmului
- Pasul 4: Trasează rezultatele
Pas 1) Construiți o funcție pentru a calcula suma de pătrate în cadrul grupurilor
Creați funcția care rulează algoritmul k-mean și stocați totalul în clustere suma pătratelor
kmean_withinss <- function(k) { cluster <- kmeans(rescale_df, k) return (cluster$tot.withinss) }
Code Explicație
- function(k): Setați numărul de argumente din funcție
- kmeans(rescale_df, k): Rulați algoritmul pentru această valoare a lui k
- return(cluster$tot.withinss): Stocați totalul în grupuri suma de pătrate
Testați funcția cu k egal cu 2.
ieșire:
## Try with 2 cluster
kmean_withinss(2)
ieșire:
## [1] 27087.07
Pas 2) Rulați algoritmul de n ori
Veți folosi funcția sapply() pentru a rula algoritmul pe un interval de k. Această tehnică este mai rapidă decât crearea unei bucle și stocarea valorii.
# Set maximum cluster max_k <-20 # Run algorithm over a range of k wss <- sapply(2:max_k, kmean_withinss)
Code Explicație
- max_k <- 20: Setați valoarea maximă a lui k la 20
- sapply(2:max_k, kmean_withinss): Rulați funcția kmean_withinss() într-un interval 2:max_k, adică de la 2 la 20.
Pas 3) Creați un cadru de date cu rezultatele algoritmului
Cu funcția scrisă și testată, rulați-o în intervalul de la 2 la 20 și stocați fiecare valoare din tot.withinss.
# Create a data frame to plot the graph elbow <-data.frame(2:max_k, wss)
Code Explicație
- data.frame(2:max_k, wss): creează un cadru de date cu rezultatul magazinului de algoritmi în wss
Pas 4) Trasează rezultatele
Trasați graficul pentru a vizualiza unde este punctul cot
# Plot the graph with gglop ggplot(elbow, aes(x = X2.max_k, y = wss)) + geom_point() + geom_line() + scale_x_continuous(breaks = seq(1, 20, by = 1))
Din grafic, puteți vedea k optim este șapte, unde curba începe să aibă un randament descrescător.
Odată ce aveți k optimul nostru, rulați din nou algoritmul cu k egal cu 7 și evaluați clusterele.
Examinarea clusterelor
pc_cluster_2 <-kmeans(rescale_df, 7)
După cum am menționat anterior, puteți accesa informațiile interesante rămase în lista returnată de kmean().
pc_cluster_2$cluster pc_cluster_2$centers pc_cluster_2$size
Evaluarea este subiectivă și depinde de scopul clusterelor. Scopul aici este de a grupa computerele cu specificații similare. Un expert în domeniu ar putea face acest lucru manual, dar procesul ar fi lent și predispus la erori. K-means face gruparea...ping în mod obiectiv și lasă expertul să interpreteze și să denumească rezultatul.
Ca evaluare prealabilă, puteți examina dimensiunea clusterelor.
pc_cluster_2$size
ieșire:
## [1] 608 1596 1231 580 1003 699 542
Cel mai mare cluster, numărul 2, conține 1,596 de observații, în timp ce cel mai mic, numărul 7, conține doar 542 de computere. Ar putea fi util să existe omogenitate între clustere, dacă nu, ar putea fi necesară o pregătire mai puțin detaliată a datelor.
Veți obține o privire mai profundă asupra datelor cu ajutorul componentei centrale. Rândurile se referă la numerotarea clusterului, iar coloanele la variabilele utilizate de algoritm. Valorile reprezintă scorul mediu al fiecărui cluster pentru coloana interesată. Standardizarea facilitează interpretarea. Valorile pozitive indică faptul că scorul z pentru un anumit cluster este peste media generală. De exemplu, clusterul 4 are cel mai mare preț mediu (price_scal = 1.09), în timp ce clusterul 5 are cel mai mic (-0.82).
center <-pc_cluster_2$centers center
ieșire:
## price_scal hd_scal ram_scal screen_scal ads_scal trend_scal ## 1 -0.6372457 -0.7097995 -0.691520682 -0.4401632 0.6780366 -0.3379751 ## 2 -0.1323863 0.6299541 0.004786730 2.6419582 -0.8894946 1.2673184 ## 3 0.8745816 0.2574164 0.513105797 -0.2003237 0.6734261 -0.3300536 ## 4 1.0912296 -0.2401936 0.006526723 2.6419582 0.4704301 -0.4132057 ## 5 -0.8155183 0.2814882 -0.307621003 -0.3205176 -0.9052979 1.2177279 ## 6 0.8830191 2.1019454 2.168706085 0.4492922 -0.9035248 1.2069855 ## 7 0.2215678 -0.7132577 -0.318050275 -0.3878782 -1.3206229 -1.5490909
Puteți crea o hartă termică cu ggplot pentru a ne ajuta să evidențiem diferența dintre categorii.
Culorile implicite ale ggplot trebuie schimbate cu biblioteca RColorBrewer. Puteți folosi conda bibliotecă și codul de lansat în terminal:
conda install -c r r-rcolorbrewer
Pentru a crea o hartă termică, procedați în trei pași:
- Construiți un cadru de date cu valorile centrului și creați o variabilă cu numărul clusterului
- Reformați datele cu funcția gather() a bibliotecii tidyr. Doriți să transformați datele din largi în lungi.
- Creați paleta de culori cu culoareRampFuncția Palette().
Pas 1) Construiți un cadru de date
Să creăm setul de date de remodelare
library(tidyr) # create dataset with the cluster number cluster <- c(1: 7) center_df <- data.frame(cluster, center) # Reshape the data center_reshape <- gather(center_df, features, values, price_scal: trend_scal) head(center_reshape)
ieșire:
## cluster features values ## 1 1 price_scal -0.6372457 ## 2 2 price_scal -0.1323863 ## 3 3 price_scal 0.8745816 ## 4 4 price_scal 1.0912296 ## 5 5 price_scal -0.8155183 ## 6 6 price_scal 0.8830191
Pas 2) Creați paleta de culori
Codul de mai jos construiește paleta de culori utilizată de harta termică.
library(RColorBrewer) # Create the palette hm.palette <-colorRampPalette(rev(brewer.pal(10, 'RdYlGn')),space='Lab')
Pasul 3) Vizualizați
Puteți reprezenta graficul și puteți vedea cum arată clusterele.
# Plot the heat map ggplot(data = center_reshape, aes(x = features, y = cluster, fill = values)) + scale_y_continuous(breaks = seq(1, 7, by = 1)) + geom_tile() + coord_equal() + scale_fill_gradientn(colours = hm.palette(90)) + theme_classic()
Cum se obțin rezultate reproductibile K-Means cu set.seed() și nstart
Tutorialul menționează că k-means returnează grupuri diferite la fiecare rulare. Aceasta nu este o ciudățenie cu care să fim obișnuiți, ci o problemă cu două corecții standard și niciuna nu este utilizată în exemplele de mai sus.
1. Fixați punctul de pornire cu set.seed(). Centroizii inițiali sunt extrași aleatoriu, astfel încât același apel produce clustere diferite de fiecare dată. Setarea unei valori inițiale face ca întreaga analiză să fie reproductibilă:
set.seed(123)
pc_cluster_2 <- kmeans(rescale_df, 7)
2. Rulați mai multe porniri și păstrați cea mai bună cu nstart. Un singur început aleatoriu poate converge către un optim local slab. Argumentul nstart rulează algoritmul de mai multe ori de la începuturi aleatorii diferite și returnează cel cu cel mai mic total în cadrul sumei pătratelor:
set.seed(123)
pc_cluster_2 <- kmeans(rescale_df, centers = 7, nstart = 25)
Douăzeci și cinci de porniri este recomandarea obișnuită și costă foarte puțin pentru un set de date de această dimensiune. Fără aceasta, curba cotului în sine devine instabilă, deoarece fiecare punct de pe grafic provine dintr-un singur început ghinionist sau norocos. Prin urmare, funcția kmean_withinss() definită anterior ar trebui scrisă astfel:
kmean_withinss <- function(k) { cluster <- kmeans(rescale_df, centers = k, nstart = 25) return (cluster$tot.withinss) }
3. Creșteți iter.max dacă algoritmul avertizează. Dacă R raportează că „nu a convergut în 10 iterații”, se transmite iter.max = 50 pentru a-i oferi mai mult spațiu.
K-Means vs. Ierarhic Clusterîn R
K-means nu este singura metodă de grupare disponibilă, iar alegerea se reduce de obicei la dimensiunea datelor și la faptul dacă știți deja câte grupuri doriți.
| Criterii | K-înseamnă | Ierarhic |
|---|---|---|
| Numărul de clustere | Trebuie alese în avans | Ales după, prin tăierea dendrogramei |
| Stabilitatea rezultatelor | Variază în funcție de startul aleatoriu | Determinat |
| Scalabilitate | Gestionează seturi de date foarte mari | Dificultăți dincolo de câteva mii de rânduri |
| Cluster forma | Presupune grupuri aproximativ sferice, de dimensiuni similare | Mai flexibil |
| producție | Un set plat de etichete | O dendrogramă care prezintă o structură imbricată |
| Funcția R | medie km(dl, k) | hclust(dist(df)) |
# Hierarchical alternative on the same scaled data hc <- hclust(dist(rescale_df), method = "ward.D2") plot(hc) groups <- cutree(hc, k = 7)
Cu 6,259 de observații, gruparea ierarhică trebuie să construiască o matrice de distanță de aproximativ 19.6 milioane de perechi, motiv pentru care k-means este alegerea practică pentru acest set de date. Rețineți, de asemenea, că k-means presupune grupuri de dimensiuni similare și formă aproximativ sferică; acolo unde această presupunere eșuează, DBSCAN gestionează formele neregulate și identifică valorile aberante în loc să forțeze fiecare punct într-un grup.
K-înseamnă Clustering în R: Referință funcții
Fiecare funcție utilizată în acest tutorial este enumerată mai jos:
| Pachet | Obiectiv | Funcţie | Argument |
|---|---|---|---|
| de bază | Antrenează k-mean | km înseamnă() | df, k |
| Acces cluster | kmînseamnă()$cluster | ||
| Cluster centre de | kmînseamnă()$centre | ||
| Cluster dimensiuni | km înseamnă()$size | ||
| Total în limita sumei pătratelor | kmeans()$tot.withinss | Folosit prin metoda cotului | |
| Între suma pătratelor | kmeans()$betweenss | ||
| de bază | Rulare reproductibilă | set.seed() | valoarea semințelor |
| de bază | Stabilizați rezultatul | kmeans(dl, k, nstart = 25) | nstart |








