Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Definitiv guide till K-Means Clustering med Scikit-Learn

Beskrivning

K-betyder kluster är en av de mest använda oövervakade maskininlärningsalgoritmerna som bildar kluster av data baserat på likheten mellan datainstanser.

I den här guiden kommer vi först att ta en titt på ett enkelt exempel för att förstå hur K-Means-algoritmen fungerar innan vi implementerar den med Scikit-Learn. Sedan kommer vi att diskutera hur man bestämmer antalet kluster (Ks) i K-Means, och även täcker avståndsmått, varians och K-Means för- och nackdelar.

Motivation

Föreställ dig följande situation. En dag, när du gick runt i grannskapet, märkte du att det fanns 10 närbutiker och började undra vilka butiker som liknade varandra – närmare varandra i närheten. När du letat efter sätt att svara på den frågan har du stött på ett intressant tillvägagångssätt som delar in butikerna i grupper baserat på deras koordinater på en karta.

Till exempel, om en butik var belägen 5 km västerut och 3 km norr – skulle du tilldela (5, 3) koordinater till den och representerar den i en graf. Låt oss rita denna första punkt för att visualisera vad som händer:

import matplotlib.pyplot as plt

plt.title("Store With Coordinates (5, 3)")
plt.scatter(x=5, y=3)

Detta är bara den första punkten, så vi kan få en uppfattning om hur vi kan representera en butik. Säg att vi redan har 10 koordinater till de 10 insamlade butikerna. Efter att ha organiserat dem i en numpy array kan vi också plotta deras platser:

import numpy as np

points = np.array([[5, 3], [10, 15], [15, 12], [24, 10], [30, 45], [85, 70], [71, 80], [60, 78], [55, 52],[80, 91]])

xs = points[:,0] 
ys = points[:,1]  

plt.title("10 Stores Coordinates")
plt.scatter(x=xs, y=ys)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Hur man manuellt implementerar K-Means Algorithm

Nu kan vi titta på de 10 butikerna på en graf, och huvudproblemet är att hitta är det ett sätt att de kan delas in i olika grupper baserat på närhet? Bara genom att ta en snabb titt på grafen kommer vi förmodligen att märka två grupper av butiker – en är de nedre punkterna längst ner till vänster och den andra är de övre högra punkterna. Kanske kan vi till och med särskilja de två punkterna i mitten som en separat grupp – och därför skapa tre olika grupper.

I det här avsnittet kommer vi att gå igenom processen att manuellt gruppera punkter – dela upp dem i det givna antalet grupper. På så sätt går vi i princip noggrant igenom alla steg i K-Means klustringsalgoritm. I slutet av det här avsnittet kommer du att få både en intuitiv och praktisk förståelse för alla steg som utförs under K-Means-klustringen. Efter det kommer vi att delegera det till Scikit-Learn.

Vad skulle vara det bästa sättet att avgöra om det finns två eller tre grupper av poäng? Ett enkelt sätt skulle vara att helt enkelt välja ett antal grupper – till exempel två – och sedan försöka gruppera poäng baserat på det valet.

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Låt oss säga att vi har bestämt att det finns två grupper av våra butiker (poäng). Nu måste vi hitta ett sätt att förstå vilka punkter som tillhör vilken grupp. Detta kan göras genom att välja en punkt att representera grupp 1 och en att representera grupp 2. Dessa punkter kommer att användas som referens när man mäter avståndet från alla andra punkter till varje grupp.

På det sättet, säg punkt (5, 3) hamnar i grupp 1, och peka (79, 60) till grupp 2. När du försöker tilldela en ny punkt (6, 3) till grupper måste vi mäta dess avstånd till dessa två punkter. När det gäller punkten (6, 3) is närmare till (5, 3), därför tillhör den den grupp som representeras av den punkten – grupp 1. På så sätt kan vi enkelt gruppera alla punkter i motsvarande grupper.

I detta exempel, förutom att bestämma antalet grupper (kluster) – vi väljer också några punkter att vara en referens avstånd för nya poäng i varje grupp.

Det är den allmänna idén att förstå likheter mellan våra butiker. Låt oss omsätta det i praktiken – vi kan först välja de två referenspunkterna vid slumpmässig. Referenspunkten för grupp 1 kommer vara (5, 3) och referenspunkten för grupp 2 kommer vara (10, 15). Vi kan välja båda våra punkter numpy array av [0] och [1] indexerar och lagrar dem i g1 (grupp 1) och g2 (grupp 2) variabler:

g1 = points[0]
g2 = points[1]

Efter att ha gjort detta måste vi beräkna avståndet från alla andra punkter till dessa referenspunkter. Detta väcker en viktig fråga – hur man mäter det avståndet. Vi kan i princip använda vilket avståndsmått som helst, men för syftet med denna guide, låt oss använda Euklidiskt avstånd_.

Det kan vara användbart att veta att euklidiskt avståndsmått är baserat på Pythagoras sats:

$$
c^2 = a^2 + b^2
$$

När den är anpassad till punkter i ett plan – (a1, b1) och (a2, b2), den föregående formeln blir:

$$
c^2 = (a2-a1)^2 + (b2-b1)^2
$$

Avståndet kommer att vara kvadratroten av c, så vi kan också skriva formeln som:

$$
euklidisk_{avstånd} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2)]
$$

Notera: Du kan också generalisera den euklidiska avståndsformeln för flerdimensionella punkter. Till exempel, i ett tredimensionellt utrymme har punkter tre koordinater – vår formel speglar det på följande sätt:
$$
euklidisk_{avstånd} = sqrt[2][(a2 – a1)^2 + (b2 – b1) ^2 + (c2 – c1) ^2)]
$$
Samma princip följs oavsett antalet dimensioner av utrymmet vi verkar i.

Hittills har vi valt de punkter som ska representera grupper, och vi vet hur man beräknar avstånd. Låt oss nu sätta ihop avstånden och grupperna genom att tilldela var och en av våra insamlade butikspoäng till en grupp.

För att bättre visualisera det kommer vi att deklarera tre listor. Den första som lagrar poäng i den första gruppen – points_in_g1. Den andra för att lagra poäng från grupp 2 – points_in_g2, och den sista - group, Till etikett punkterna som antingen 1 (tillhör grupp 1) eller 2 (tillhör grupp 2):

points_in_g1 = []
points_in_g2 = []
group = []

Vi kan nu iterera genom våra punkter och beräkna det euklidiska avståndet mellan dem och var och en av våra gruppreferenser. Varje punkt kommer att vara närmare till en av två grupper – baserat på vilken grupp som är närmast, tilldelar vi varje punkt till motsvarande lista, samtidigt som vi lägger till 1 or 2 till group lista:

for p in points:
    x1, y1 = p[0], p[1]
    euclidean_distance_g1 = np.sqrt((g1[0] - x1)**2 + (g1[1] - y1)**2)
    euclidean_distance_g2 = np.sqrt((g2[0] - x1)**2 + (g2[1] - y1)**2)
    if euclidean_distance_g1 < euclidean_distance_g2:
        points_in_g1.append(p)
        group.append('1')
    else:
        points_in_g2.append(p)
        group.append('2')

Låt oss titta på resultaten av denna iteration för att se vad som hände:

print(f'points_in_g1:{points_in_g1}n 
npoints_in_g2:{points_in_g2}n 
ngroup:{group}')

Vilket resulterar i:

points_in_g1:[array([5, 3])]
 
points_in_g2:[array([10, 15]), array([15, 12]), 
              array([24, 10]), array([30, 45]), 
              array([85, 70]), array([71, 80]),
              array([60, 78]), array([55, 52]), 
              array([80, 91])]
 
group:[1, 2, 2, 2, 2, 2, 2, 2, 2, 2] 

Vi kan också plotta klustringsresultatet, med olika färger baserat på de tilldelade grupperna, med hjälp av Seaborns scatterplot() med group som en hue argument:

import seaborn as sns

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Det är tydligt att endast vår första poäng tilldelas grupp 1, och alla andra poäng tilldelades grupp 2. Det resultatet skiljer sig från vad vi hade tänkt oss i början. Med tanke på skillnaden mellan våra resultat och våra initiala förväntningar – finns det något sätt vi kan ändra på det? Det verkar finnas!

Ett tillvägagångssätt är att upprepa processen och välja olika punkter som referenser för grupperna. Detta kommer att förändra våra resultat, förhoppningsvis, mer i linje med vad vi hade tänkt oss i början. Den här andra gången kunde vi välja dem inte slumpmässigt som vi tidigare gjorde, utan genom att få en betyda av alla våra redan grupperade punkter. På så sätt kan de nya punkterna placeras i mitten av motsvarande grupper.

Till exempel om den andra gruppen bara hade poäng (10, 15), (30, 45). Den nya centrala poängen skulle vara (10 + 30)/2 och (15+45)/2 – som är lika med (20, 30).

Eftersom vi har lagt våra resultat i listor kan vi konvertera dem först till numpy matriser, välj deras xs, ys och erhåll sedan betyda:

g1_center = [np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()]
g2_center = [np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()]
g1_center, g2_center

Råd: Försök använda numpy och NumPy-arrayer så mycket som möjligt. De är optimerade för bättre prestanda och förenklar många linjära algebraoperationer. När du försöker lösa något linjärt algebraproblem, bör du definitivt ta en titt på numpy dokumentation för att kontrollera om det finns någon numpy metod utformad för att lösa ditt problem. Chansen är att det finns!

För att hjälpa till att upprepa processen med våra nya mittpunkter, låt oss omvandla vår tidigare kod till en funktion, exekvera den och se om det har skett några förändringar i hur punkterna är grupperade:

def assigns_points_to_two_groups(g1_center, g2_center):
    points_in_g1 = []
    points_in_g2 = []
    group = []

    for p in points:
        x1, y1 = p[0], p[1]
        euclidean_distance_g1 = np.sqrt((g1_center[0] - x1)**2 + (g1_center[1] - y1)**2)
        euclidean_distance_g2 = np.sqrt((g2_center[0] - x1)**2 + (g2_center[1] - y1)**2)
        if euclidean_distance_g1 < euclidean_distance_g2:
            points_in_g1.append(p)
            group.append(1)
        else:
            points_in_g2.append(p)
            group.append(2)
    return points_in_g1, points_in_g2, group

Notera: Om du märker att du fortsätter att upprepa samma kod om och om igen, bör du slå in den koden i en separat funktion. Det anses vara en bästa praxis att organisera kod i funktioner, speciellt för att de underlättar testning. Det är lättare att testa och isolerad kodbit än en hel kod utan några funktioner.

Låt oss anropa funktionen och lagra dess resultat i points_in_g1, points_in_g2och group variabler:

points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
points_in_g1, points_in_g2, group

Och rita även spridningsdiagrammet med de färgade punkterna för att visualisera gruppindelningen:

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Det verkar som om klustringen av våra poäng är blir bättre. Men ändå finns det två punkter i mitten av grafen som kan tilldelas båda grupperna när man överväger deras närhet till båda grupperna. Algoritmen vi har utvecklat hittills tilldelar båda dessa poäng till den andra gruppen.

Detta betyder att vi förmodligen kan upprepa processen en gång till genom att använda hjälpen av X och Y och skapa två nya centrala punkter (tyngdpunkter) till våra grupper och omfördela dem baserat på avstånd.

Låt oss också skapa en funktion för att uppdatera tyngdpunkterna. Hela processen kan nu reduceras till flera anrop av den funktionen:

def updates_centroids(points_in_g1, points_in_g2):
    g1_center = np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()
    g2_center = np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()
    return g1_center, g2_center

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Lägg märke till att efter denna tredje iteration tillhör var och en av punkterna nu olika kluster. Det verkar som om resultaten blir bättre – låt oss göra det igen. Går nu till fjärde iterationen av vår metod:

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Denna fjärde gången fick vi samma resultat som den föregående. Så det verkar som om våra poäng inte kommer att byta grupp längre, vårt resultat har nått någon form av stabilitet – det har kommit till ett oföränderligt tillstånd, eller konvergerat. Utöver det har vi exakt samma resultat som vi hade tänkt oss för de 2 grupperna. Vi kan också se om denna nådda uppdelning är vettig.

Låt oss bara snabbt sammanfatta vad vi har gjort hittills. Vi har delat upp våra 10 butiker geografiskt i två sektioner – en i de nedre sydvästra regionerna och andra i nordost. Det kan vara intressant att samla in mer data utöver vad vi redan har – intäkter, det dagliga antalet kunder och många fler. På så sätt kan vi göra en rikare analys och eventuellt generera mer intressanta resultat.

Klustringsstudier som denna kan göras när ett redan etablerat varumärke vill välja ett område för att öppna en ny butik. I så fall finns det många fler variabler som tas i beaktande förutom plats.

Vad har allt detta med K-Means-algoritmen att göra?

Medan du följde dessa steg kanske du undrat vad de har med K-Means-algoritmen att göra. Processen vi har genomfört hittills är K-Means algoritm. Kort sagt, vi har bestämt antalet grupper/kluster, slumpmässigt valt initiala punkter och uppdaterat tyngdpunkter i varje iteration tills kluster konvergerat. Vi har i princip utfört hela algoritmen för hand - noggrant genomfört varje steg.

Smakämnen K i K-Means kommer från antal kluster som måste ställas in innan du startar iterationsprocessen. I vårat fall K = 2. Denna egenskap ses ibland som negativ med tanke på att det finns andra klustermetoder, såsom Hierarchical Clustering, som inte behöver ha ett fast antal kluster i förväg.

På grund av dess användning av medel blir även K-medel känslig för extremvärden och extremvärden – de förbättrar variabiliteten och gör det svårare för våra tyngdpunkter att spela sin roll. Så var medveten om behovet av att prestera extrema värden och extremvärdesanalys innan du utför en klustring med K-Means-algoritmen.

Observera också att våra punkter var segmenterade i raka delar, det finns inga kurvor när du skapar klustren. Det kan också vara en nackdel med K-Means-algoritmen.

Notera: När du behöver att den ska vara mer flexibel och anpassningsbar till ellipser och andra former, prova att använda en generaliserad K-medel Gaussisk blandningsmodell. Denna modell kan anpassa sig till elliptiska segmenteringskluster.

K-Means har också många fördelar! Den fungerar bra på stora datamängder vilket kan bli svårt att hantera om du använder vissa typer av hierarkiska klustringsalgoritmer. Det är också garanterar konvergens, och kan enkelt generalisera och anpassa. Förutom det är det förmodligen den mest använda klustringsalgoritmen.

Nu när vi har gått igenom alla steg som utförs i K-Means-algoritmen och förstått alla dess för- och nackdelar, kan vi äntligen implementera K-Means med hjälp av Scikit-Learn-biblioteket.

Hur man implementerar K-Means-algoritmen med hjälp av Scikit-Lär dig

För att dubbelkolla vårt resultat, låt oss göra den här processen igen, men nu använder vi 3 rader kod med sklearn:

from sklearn.cluster import KMeans


kmeans = KMeans(n_clusters=2, random_state=42) 
kmeans.fit(points)
kmeans.labels_

Här är etiketterna desamma som våra tidigare grupper. Låt oss bara snabbt plotta resultatet:

sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Den resulterande plotten är densamma som den från föregående avsnitt.

Kolla in vår praktiska, praktiska guide för att lära dig Git, med bästa praxis, branschaccepterade standarder och medföljande fuskblad. Sluta googla Git-kommandon och faktiskt lära Det!

Notera: Att bara titta på hur vi har utfört K-Means-algoritmen med Scikit-Learn kan ge dig intrycket av att det är enkelt och att du inte behöver oroa dig så mycket för det. Bara 3 rader kod utför alla steg som vi har diskuterat i föregående avsnitt när vi har gått igenom K-Means-algoritmen steg-för-steg. Men, djävulen är i detaljerna I detta fall! Om du inte förstår alla steg och begränsningar av algoritmen kommer du troligen att möta situationen där K-Means-algoritmen ger dig resultat du inte förväntade dig.

Med Scikit-Learn kan du också initiera K-Means för snabbare konvergens genom att ställa in init='k-means++' argument. I bredare termer, K-Means++ väljer fortfarande k initiala kluster centreras slumpmässigt efter en enhetlig fördelning. Sedan väljs varje efterföljande klustercentrum från de återstående datapunkterna, inte genom att bara beräkna ett avståndsmått – utan genom att använda sannolikhet. Att använda sannolikheten snabbar upp algoritmen och det är användbart när man hanterar mycket stora datamängder.

Armbågsmetoden – att välja det bästa antalet grupper

Än så länge är allt bra! Vi har samlat 10 butiker baserat på det euklidiska avståndet mellan punkter och tyngdpunkter. Men hur är det med de två punkterna i mitten av grafen som är lite svårare att gruppera? Kunde de inte bilda en separat grupp också? Har vi faktiskt gjort ett misstag genom att välja K = 2 grupper? Det kanske vi faktiskt hade K = 3 grupper? Vi kunde till och med ha mer än tre grupper och inte vara medvetna om det.

Frågan som ställs här är hur man bestämmer antalet grupper (K) i K-Means. För att svara på den frågan måste vi förstå om det skulle finnas ett "bättre" kluster för ett annat värde på K.

Det naiva sättet att ta reda på det är genom att gruppera punkter med olika värden på K, så för K=2, K=3, K=4 och så vidare:

for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 

Men klustringspunkter för olika Ks ensam kommer inte räcka till att förstå om vi har valt det idealiska värdet för K. Vi behöver ett sätt att utvärdera klustringskvaliteten för var och en K vi har valt.

Manuell beräkning av Inom klustersumman av kvadrater (WCSS)

Här är den idealiska platsen att introducera ett mått på hur mycket våra klustrade punkter är nära varandra. Det beskriver i huvudsak hur mycket variation vi har inuti ett enda kluster. Denna åtgärd kallas Inom kluster Summan av kvadrater, eller WCSS för korta. Ju mindre WCSS är, desto närmare är våra punkter, därför har vi ett mer välformat kluster. WCSS-formeln kan användas för valfritt antal kluster:

$$
WCSS = summa(Pi_1 – Centroid_1)^2 + cdots + summa(Pi_n – Centroid_n)^2
$$

Notera: I den här guiden använder vi Euklidiskt avstånd för att erhålla tyngdpunkterna, men andra avståndsmått, såsom Manhattan, kunde också användas.

Nu kan vi anta att vi har valt att ha två kluster och försöka implementera WCSS för att bättre förstå vad WCSS är och hur man använder det. Som formeln säger måste vi summera skillnaderna i kvadrat mellan alla klusterpunkter och tyngdpunkter. Så, om vår första punkt från den första gruppen är (5, 3) och vår sista tyngdpunkt (efter konvergens) i den första gruppen är (16.8, 17.0), WCSS kommer att vara:

$$
WCSS = summa((5,3) – (16.8, 17.0))^2
$$

$$
WCSS = summa((5-16.8) + (3-17.0))^2
$$

$$
WCSS = summa((-11.8) + (-14.0))^2
$$

$$
WCSS = summa((-25.8))^2
$$

$$
WCSS = 335.24
$$

Detta exempel illustrerar hur vi beräknar WCSS för en punkt från klustret. Men klustret innehåller vanligtvis mer än en punkt, och vi måste ta hänsyn till dem alla när vi beräknar WCSS. Vi kommer att göra det genom att definiera en funktion som tar emot ett kluster av punkter och tyngdpunkter, och returnerar summan av kvadrater:

def sum_of_squares(cluster, centroid):
    squares = []
    for p in cluster:
        squares.append((p - centroid)**2)
        ss = np.array(squares).sum()
    return ss

Nu kan vi få summan av kvadrater för varje kluster:

g1 = sum_of_squares(points_in_g1, g1_center)
g2 = sum_of_squares(points_in_g2, g2_center)

Och summera resultaten för att få summan WCSS:

g1 + g2

Detta resulterar i:

2964.3999999999996

Så, i vårt fall, när K är lika med 2, är den totala WCSS 2964.39. Nu kan vi byta K och beräkna WCSS för dem alla. På så sätt kan vi få en inblick i vad K vi bör välja att få vår klustring att prestera bäst.

beräkning WCSS Använda Scikit-Lär dig

Lyckligtvis behöver vi inte manuellt beräkna WCSS för varje K. Efter att ha utfört K-Means-klustringen för det givna antalet kluster kan vi erhålla dess WCSS genom att använda inertia_ attribut. Nu kan vi gå tillbaka till våra K-medel for loop, använd den för att ändra antalet kluster och lista motsvarande WCSS-värden:

wcss = [] 
for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 
    wcss.append(kmeans.inertia_)
wcss

Lägg märke till att det andra värdet i listan är exakt detsamma som vi tidigare har beräknat för K = 2:

[18272.9, # For k=1 
 2964.3999999999996, # For k=2
 1198.75, # For k=3
 861.75,
 570.5,
 337.5,
 175.83333333333334,
 79.5,
 17.0,
 0.0]

För att visualisera dessa resultat, låt oss plotta våra Ks tillsammans med WCSS-värdena:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Det är ett avbrott på en tomt när x = 2, en låg punkt i linjen och en ännu lägre när x = 3. Lägg märke till att det påminner oss om formen av en armbåge. Genom att plotta Ks tillsammans med WCSS använder vi Armbågsmetod för att välja antalet Ks. Och den valt K är exakt den lägsta armbågspunkten, så skulle det vara 3 istället för 2, i vårat fall:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss);
plt.axvline(3, linestyle='--', color='r')

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Vi kan köra K-Means klusteralgoritm igen, för att se hur vår data skulle se ut med tre kluster:

kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(points)
sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Vi var redan nöjda med två kluster, men enligt armbågsmetoden skulle tre kluster passa bättre för våra data. I det här fallet skulle vi ha tre sorters butiker istället för två. Innan vi använde armbågsmetoden tänkte vi på sydvästra och nordöstra kluster av butiker, nu har vi även butiker i centrum. Kanske kan det vara en bra plats att öppna en annan butik eftersom det skulle ha mindre konkurrens i närheten.

Alternativa klusterkvalitetsmått

Det finns även andra mått som kan användas vid utvärdering av klusterkvalitet:

  • Silhouette Betyg – analyserar inte bara avståndet mellan punkter inom kluster utan även mellan kluster själva
  • Mellan kluster Summan av kvadrater (BCSS) – mått som kompletterar WCSS
  • Summa av kvadrater fel (SSE)
  • Maximal radie – mäter det största avståndet från en punkt till dess tyngdpunkt
  • Genomsnittlig radie – summan av det största avståndet från en punkt till dess tyngdpunkt dividerat med antalet kluster.

Det rekommenderas att experimentera och lära känna var och en av dem eftersom beroende på problemet kan några av alternativen vara mer tillämpliga än de mest använda måtten (WCSS och Silhouette Score).

I slutändan, som med många datavetenskapliga algoritmer, vill vi minska variansen inuti varje kluster och maximera variansen mellan olika kluster. Så vi har mer definierade och separerbara kluster.

Använda K-Means på en annan datamängd

Låt oss använda det vi har lärt oss på en annan datamängd. Den här gången ska vi försöka hitta grupper av liknande viner.

Notera: Du kan ladda ner datasetet här..

Vi börjar med att importera pandas att läsa wine-clustering CSV (Kommaseparerade värden) fil i en Dataframe strukturera:

import pandas as pd

df = pd.read_csv('wine-clustering.csv')

Efter att ha laddat den, låt oss ta en titt på de första fem posterna med data med head() metod:

df.head()

Detta resulterar i:

	Alcohol 	Malic_Acid 	Ash 	Ash_Alcanity 	Magnesium 	Total_Phenols 	Flavanoids 	Nonflavanoid_Phenols 	Proanthocyanins 	Color_Intensity 	Hue 	OD280 	Proline
0 	14.23 		1.71 		2.43 	15.6 			127 		2.80 			3.06 		0.28 					2.29 				5.64 				1.04 	3.92 	1065
1 	13.20 		1.78 		2.14 	11.2 			100 		2.65 			2.76 		0.26 					1.28 				4.38 				1.05 	3.40 	1050
2 	13.16 		2.36 		2.67 	18.6 			101 		2.80 			3.24 		0.30 					2.81 				5.68 				1.03 	3.17 	1185
3 	14.37 		1.95 		2.50 	16.8 			113 		3.85 			3.49 		0.24 					2.18 				7.80 				0.86 	3.45 	1480
4 	13.24 		2.59 		2.87 	21.0 			118 		2.80 			2.69 		0.39 					1.82 				4.32 				1.04 	2.93 	735

Vi har många mätningar av ämnen som finns i viner. Här behöver vi inte heller transformera kategoriska kolumner eftersom alla är numeriska. Låt oss nu ta en titt på den beskrivande statistiken med describe() metod:

df.describe().T 

Beskrivningstabellen:

 						count 	mean 		std 		min 	25% 	50% 	75% 		max
Alcohol 				178.0 	13.000618 	0.811827 	11.03 	12.3625 13.050 	13.6775 	14.83
Malic_Acid 				178.0 	2.336348 	1.117146 	0.74 	1.6025 	1.865 	3.0825 		5.80
Ash 					178.0 	2.366517 	0.274344 	1.36 	2.2100 	2.360 	2.5575 		3.23
Ash_Alcanity 			178.0 	19.494944 	3.339564 	10.60 	17.2000 19.500 	21.5000 	30.00
Magnesium 				178.0 	99.741573 	14.282484 	70.00 	88.0000 98.000 	107.0000 	162.00
Total_Phenols 			178.0 	2.295112 	0.625851 	0.98 	1.7425 	2.355 	2.8000 		3.88
Flavanoids 				178.0 	2.029270 	0.998859 	0.34 	1.2050 	2.135 	2.8750 		5.08
Nonflavanoid_Phenols 	178.0 	0.361854 	0.124453 	0.13 	0.2700 	0.340 	0.4375 		0.66
Proanthocyanins 		178.0 	1.590899 	0.572359 	0.41 	1.2500 	1.555 	1.9500 		3.58
Color_Intensity 		178.0 	5.058090 	2.318286 	1.28 	3.2200 	4.690 	6.2000 		13.00
Hue 					178.0 	0.957449 	0.228572 	0.48 	0.7825 	0.965 	1.1200 		1.71
OD280 					178.0 	2.611685 	0.709990 	1.27 	1.9375 	2.780 	3.1700 		4.00
Proline 				178.0 	746.893258 	314.907474 	278.00 	500.500 673.500 985.0000 	1680.00

Genom att titta på tabellen är det tydligt att det finns några variationer i uppgifterna – för vissa kolumner som t.ex Alchool det finns mer, och för andra, som t.ex Malic_Acid, mindre. Nu kan vi kolla om det finns några null, eller NaN värden i vår datauppsättning:

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 13 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   Alcohol               178 non-null    float64
 1   Malic_Acid            178 non-null    float64
 2   Ash                   178 non-null    float64
 3   Ash_Alcanity          178 non-null    float64
 4   Magnesium             178 non-null    int64  
 5   Total_Phenols         178 non-null    float64
 6   Flavanoids            178 non-null    float64
 7   Nonflavanoid_Phenols  178 non-null    float64
 8   Proanthocyanins       178 non-null    float64
 9   Color_Intensity       178 non-null    float64
 10  Hue                   178 non-null    float64
 11  OD280                 178 non-null    float64
 12  Proline               178 non-null    int64  
dtypes: float64(11), int64(2)
memory usage: 18.2 KB

Det finns inget behov av att släppa eller mata in data, med tanke på att det inte finns tomma värden i datamängden. Vi kan använda en Seaborn pairplot() för att se datafördelningen och kontrollera om datamängden bildar kolumnpar som kan vara intressanta för klustring:

sns.pairplot(df)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Genom att titta på pardiagrammet verkar två kolumner lovande för klustringsändamål – Alcohol och OD280 (vilket är en metod för att bestämma proteinkoncentrationen i viner). Det verkar som att det finns 3 distinkta kluster på tomter som kombinerar två av dem.

Det finns andra kolumner som verkar vara i korrelation också. Mest anmärkningsvärt Alcohol och Total_Phenolsoch Alcohol och Flavanoids. De har stora linjära samband som kan observeras i pardiagrammet.

Eftersom vårt fokus är klustring med K-Means, låt oss välja ett par kolumner, till exempel Alcohol och OD280, och testa armbågsmetoden för denna datauppsättning.

Notera: När du använder fler kolumner i datamängden kommer det att finnas ett behov av att antingen plotta i 3 dimensioner eller reducera data till huvudkomponenter (användning av PCA). Detta är ett giltigt och vanligare tillvägagångssätt, se bara till att välja huvudkomponenterna baserat på hur mycket de förklarar och tänk på att när du minskar datadimensionerna, finns det viss informationsförlust – så handlingen är en approximation av den verkliga datan, inte hur den verkligen är.

Låt oss plotta spridningsdiagrammet med de två kolumnerna inställda som dess axel för att ta en närmare titt på punkterna vi vill dela in i grupper:

sns.scatterplot(data=df, x='OD280', y='Alcohol')

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Nu kan vi definiera våra kolumner och använda armbågsmetoden för att bestämma antalet kluster. Vi kommer också att initiera algoritmen med kmeans++ bara för att se till att det konvergerar snabbare:

values = df[['OD280', 'Alcohol']]

wcss_wine = [] 
for i in range(1, 11): 
    kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
    kmeans.fit(values) 
    wcss_wine.append(kmeans.inertia_)

Vi har beräknat WCSS, så vi kan plotta resultaten:

clusters_wine = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
plt.plot(clusters_wine, wcss_wine)
plt.axvline(3, linestyle='--', color='r')

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Enligt armbågsmetoden ska vi ha 3 kluster här. För det sista steget, låt oss gruppera våra punkter i 3 kluster och rita de kluster som identifieras av färger:

kmeans_wine = KMeans(n_clusters=3, random_state=42)
kmeans_wine.fit(values)
sns.scatterplot(x = values['OD280'], y = values['Alcohol'], hue=kmeans_wine.labels_)

Definitiv guide till K-Means Clustering med Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Vi kan se kluster 0, 1och 2 i grafen. Baserat på vår analys, grupp 0 har viner med högre proteinhalt och lägre alkohol, grupp 1 har viner med högre alkoholhalt och lågt protein, och grupp 2 har både högt protein och hög alkohol i sina viner.

Detta är en mycket intressant datauppsättning och jag uppmuntrar dig att gå vidare in i analysen genom att klustera data efter normalisering och PCA – även genom att tolka resultaten och hitta nya samband.

Slutsats

K-medel klustring är en enkel men mycket effektiv oövervakad maskininlärningsalgoritm för dataklustring. Det kluster data baserat på det euklidiska avståndet mellan datapunkter. K-Means klustringsalgoritm har många användningsområden för att gruppera textdokument, bilder, videor och mycket mer.

Tidsstämpel:

Mer från Stackabuse