Dokončni vodnik za hierarhično združevanje v gruče s Pythonom in Scikit-Learn PlatoBlockchain Data Intelligence. Navpično iskanje. Ai.

Dokončni vodnik za hierarhično združevanje v gruče s Pythonom in Scikit-Learn

Predstavitev

V tem priročniku se bomo osredotočili na izvajanje Hierarhični algoritem združevanja v gruče s Scikit-Learn rešiti marketinški problem.

Po branju vodnika boste razumeli:

  • Kdaj uporabiti hierarhično združevanje v gruče
  • Kako vizualizirati nabor podatkov, da razumete, ali je primeren za združevanje v gruče
  • Kako predhodno obdelati funkcije in načrtovati nove funkcije na podlagi nabora podatkov
  • Kako zmanjšati dimenzionalnost nabora podatkov z uporabo PCA
  • Kako uporabljati in brati dendrogram za ločevanje skupin
  • Katere so različne metode povezovanja in metrike razdalje, ki se uporabljajo za dendrograme in algoritme združevanja v gruče
  • Kakšne so aglomerativne in delitvene strategije grozdenja in kako delujejo
  • Kako implementirati aglomerativno hierarhično združevanje v gruče s Scikit-Learn
  • Katere so najpogostejše težave pri algoritmih združevanja v gruče in kako jih rešiti

Opomba: Prenesete lahko zvezek, ki vsebuje vso kodo v tem priročniku tukaj.

Motivacija

Predstavljajte si scenarij, v katerem ste del ekipe za podatkovno znanost, ki je povezana z oddelkom za trženje. Marketing že nekaj časa zbira podatke o nakupovanju strank in želi na podlagi zbranih podatkov ugotoviti, ali obstajajo podobnosti med strankami. Te podobnosti delijo stranke v skupine in skupine strank pomagajo pri ciljanju kampanj, promocij, konverzij in vzpostavljanju boljših odnosov s strankami.

Ali lahko kako pomagate ugotoviti, katere stranke so si podobne? Koliko jih pripada isti skupini? In koliko različnih skupin obstaja?

Eden od načinov odgovora na ta vprašanja je uporaba a grozdenje algoritmi, kot so K-Means, DBSCAN, Hierarchical Clustering itd. Na splošno algoritmi za združevanje v gruče najdejo podobnosti med podatkovnimi točkami in jih združijo.

V tem primeru je naših marketinških podatkov dokaj malo. Podatke imamo le o 200 strankah. Za marketinško ekipo je pomembno, da jim lahko jasno razložimo, kako so se odločali glede na število grozdov in jim torej razložimo, kako algoritem dejansko deluje.

Ker je naših podatkov malo in je razložljivost pomemben dejavnik, lahko izkoristimo Hierarhično združevanje rešiti to težavo. Ta postopek je znan tudi kot Hierarhična analiza združevanja v gruče (HCA).

Ena od prednosti HCA je, da ga je mogoče interpretirati in dobro deluje na majhnih zbirkah podatkov.

Druga stvar, ki jo je treba upoštevati v tem scenariju, je, da je HCA nenadzorovan algoritem. Pri združevanju podatkov v skupine ne bomo mogli preveriti, ali pravilno identificiramo, ali uporabnik pripada določeni skupini (skupin ne poznamo). Ni oznak, s katerimi bi lahko primerjali naše rezultate. Če smo skupine pravilno identificirali, bo to pozneje potrdil oddelek za trženje na dnevni osnovi (merjeno z metrikami, kot so ROI, stopnje konverzije itd.).

Zdaj, ko smo razumeli problem, ki ga poskušamo rešiti, in kako ga rešiti, lahko začnemo gledati naše podatke!

Kratka raziskovalna analiza podatkov

Opomba: Nabor podatkov, uporabljen v tem priročniku, lahko prenesete tukaj.

Po prenosu nabora podatkov opazite, da je a CSV (vrednosti, ločene z vejico) imenovana datoteka shopping-data.csv. Da bi olajšali raziskovanje in obdelavo podatkov, jih bomo naložili v a DataFrame z uporabo Pande:

import pandas as pd


path_to_file = 'home/projects/datasets/shopping-data.csv'
customer_data = pd.read_csv(path_to_file)

Marketing je povedal, da je zbral 200 zapisov strank. Lahko preverimo, ali so preneseni podatki popolni z 200 vrsticami z uporabo shape atribut. Povedal nam bo, koliko vrstic oziroma stolpcev imamo:

customer_data.shape

Rezultat tega je:

(200, 5)

Super! Naši podatki so popolni z 200 vrsticami (evidence strank) in imamo tudi 5 stolpcev (Lastnosti). Če želite videti, katere značilnosti je oddelek za trženje zbral od strank, lahko vidimo imena stolpcev z columns atribut. Če želite to narediti, izvedite:

customer_data.columns

Zgornji skript vrne:

Index(['CustomerID', 'Genre', 'Age', 'Annual Income (k$)',
       'Spending Score (1-100)'],
      dtype='object')

Tukaj vidimo, da je marketing ustvaril a CustomerID, zbral Genre, Age, Annual Income (v tisočih dolarjev) in a Spending Score od 1 do 100 za vsako od 200 strank. Na vprašanje za pojasnila dejali, da vrednosti v Spending Score označujejo, kako pogosto oseba porabi denar v nakupovalnem središču na lestvici od 1 do 100. Z drugimi besedami, če ima stranka rezultat 0, ta oseba nikoli ne porabi denarja, in če je rezultat 100, smo pravkar opazili največji porabnik.

Oglejmo si na hitro porazdelitev tega rezultata, da pregledamo potrošniške navade uporabnikov v našem naboru podatkov. Tam so pande hist() Na pomoč pride metoda:

customer_data['Spending Score (1-100)'].hist()

img

Če pogledamo histogram, vidimo, da ima več kot 35 strank rezultate med 40 in 60, potem ima manj kot 25 rezultatov med 70 in 80. Tako je večina naših strank uravnoteženi porabniki, ki mu sledijo zmerni do visoki zapravljalci. Vidimo lahko tudi, da je za njim vrstica 0, levo od porazdelitve, in še eno vrstico pred 100, desno od porazdelitve. Ti prazni prostori verjetno pomenijo, da distribucija ne vsebuje neporabnikov, ki bi imeli oceno 0, in da tudi ni porabnikov z oceno 100.

Če želite preveriti, ali je to res, lahko pogledamo najmanjšo in največjo vrednost porazdelitve. Te vrednosti je mogoče zlahka najti kot del opisne statistike, tako da lahko uporabimo describe() metoda za razumevanje drugih porazdelitev številskih vrednosti:


customer_data.describe().transpose()

To nam bo dalo tabelo, iz katere lahko beremo porazdelitve drugih vrednosti našega nabora podatkov:

 						count 	mean 	std 		min 	25% 	50% 	75% 	max
CustomerID 				200.0 	100.50 	57.879185 	1.0 	50.75 	100.5 	150.25 	200.0
Age 					200.0 	38.85 	13.969007 	18.0 	28.75 	36.0 	49.00 	70.0
Annual Income (k$) 		200.0 	60.56 	26.264721 	15.0 	41.50 	61.5 	78.00 	137.0
Spending Score (1-100) 	200.0 	50.20 	25.823522 	1.0 	34.75 	50.0 	73.00 	99.0

Naša hipoteza je potrjena. The min vrednost Spending Score is 1 in max je 99. Torej nimamo 0 or 100 porabniki točk. Nato si poglejmo še druge stolpce transponiranega describe tabela. Ob pogledu na mean in std stolpce, lahko vidimo, da za Age o mean is 38.85 in std približno 13.97. Enako se zgodi za Annual Income, S mean of 60.56 in std 26.26In za Spending Score z mean of 50 in std of 25.82. Za vse funkcije, mean je daleč od standardnega odklona, ​​ki kaže naši podatki imajo veliko variabilnost.

Da bi bolje razumeli, kako se naši podatki spreminjajo, narišite Annual Income distribucija:

customer_data['Annual Income (k$)'].hist()

Kar nam bo dalo:

img

V histogramu opazite, da je večina naših podatkov, več kot 35 strank, skoncentrirana blizu številke 60, na našem mean, v vodoravni osi. Toda kaj se zgodi, ko se pomikamo proti koncem distribucije? Ko gremo proti levi, od povprečja 60.560 $, bo naslednja vrednost, na katero bomo naleteli, 34.300 $ – povprečje (60.560 $) minus standardna različica (26.260 $). Če gremo bolj levo od naše distribucije podatkov, velja podobno pravilo, od trenutne vrednosti (26.260 $) odštejemo standardno variacijo (34.300 $). Zato bomo naleteli na vrednost 8.040 USD. Opazite, kako so naši podatki hitro šli s 60 $ na 8 $. Vsakič »poskoči« za 26.260 $ – zelo se spreminja in zato imamo tako visoko variabilnost.

img

Spremenljivost in velikost podatkov sta pomembni pri analizi združevanja v gruče, ker so meritve razdalje pri večini algoritmov za združevanje v gruče občutljive na velikosti podatkov. Razlika v velikosti lahko spremeni rezultate združevanja v gruče, tako da se ena točka zdi bližje ali bolj oddaljena od druge, kot je v resnici, kar popači dejansko združevanje podatkov.

Doslej smo videli obliko naših podatkov, nekatere njihove porazdelitve in opisno statistiko. S programom Pandas lahko navedemo tudi naše vrste podatkov in preverimo, ali je vseh naših 200 vrstic izpolnjenih ali jih je nekaj null vrednote:

customer_data.info()

Rezultat tega je:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 5 columns):
 #   Column                  Non-Null Count  Dtype 
---  ------                  --------------  ----- 
 0   CustomerID              200 non-null    int64 
 1   Genre                   200 non-null    object
 2   Age                     200 non-null    int64 
 3   Annual Income (k$)      200 non-null    int64 
 4   Spending Score (1-100)  200 non-null    int64 
dtypes: int64(4), object(1)
memory usage: 7.9+ KB

Tukaj lahko vidimo, da jih ni null vrednosti v podatkih in da imamo samo en kategorični stolpec – Genre. Na tej stopnji je pomembno, da imamo v mislih, katere funkcije se zdijo zanimive za dodajanje modelu združevanja v gruče. Če želimo našemu modelu dodati stolpec Žanr, bomo morali transformirati njegove vrednosti iz kategorično do numerično.

Poglejmo, kako Genre se izpolni s hitrim pregledom prvih 5 vrednosti naših podatkov:

customer_data.head() 

Rezultat tega je:

    CustomerID 	Genre 	Age 	Annual Income (k$) 	Spending Score (1-100)
0 	1 			Male 	19 		15 					39
1 	2 			Male 	21 		15 					81
2 	3 			Female 	20 		16 					6
3 	4 			Female 	23 		16 					77
4 	5 			Female 	31 		17 					40

Zdi se, da ima samo Female in Male kategorije. O tem se lahko prepričamo, če si ogledamo njegove edinstvene vrednosti unique:

customer_data['Genre'].unique()

To potrjuje našo domnevo:

array(['Male', 'Female'], dtype=object)

Zaenkrat vemo, da imamo samo dve zvrsti, če nameravamo to funkcijo uporabiti na našem modelu, Male bi lahko preoblikovali v 0 in Female do 1. Pomembno je tudi preveriti razmerje med žanri, ali so uravnoteženi. To lahko naredimo z value_counts() metoda in njen argument normalize=True za prikaz odstotka med Male in Female:

customer_data['Genre'].value_counts(normalize=True)

To ustvari:

Female    0.56
Male      0.44
Name: Genre, dtype: float64

V naboru podatkov imamo 56 % žensk in 44 % moških. Razlika med njima je le 16 %, naši podatki pa niso 50/50, ampak so dovolj uravnoteženo da ne povzroča težav. Če bi bili rezultati 70/30, 60/40, bi bilo morda potrebno zbrati več podatkov ali uporabiti nekakšno tehniko povečanja podatkov, da bi bilo to razmerje bolj uravnoteženo.

Do zdaj vse funkcije, vendar Age, so bili na kratko raziskani. V čem skrbi Age, je običajno zanimivo, če ga razdelimo v koše, da lahko stranke segmentiramo glede na njihove starostne skupine. Če to storimo, bi morali starostne kategorije pretvoriti v eno številko, preden jih dodamo v naš model. Tako bi namesto kategorije 15-20 let prešteli, koliko strank je v 15-20 kategorija, in to bi bila številka v novem stolpcu, imenovanem 15-20.

Nasvet: V tem vodniku predstavljamo le kratko raziskovalno analizo podatkov. Toda lahko greš dlje in moraš iti dlje. Vidite lahko, ali obstajajo razlike v dohodku in točkovanju glede na žanr in starost. To ne le obogati analizo, ampak vodi do boljših rezultatov modela. Če se želite poglobiti v raziskovalno analizo podatkov, si oglejte poglavje EDA v "Praktična napoved cen nepremičnin – strojno učenje v Pythonu" Vodeni projekt.

Po domnevah o tem, kaj bi lahko storili z obema kategoričnima – ali kategorično, da bi bila – Genre in Age stolpce, uporabimo, kar je bilo obravnavano.

Spremenljivke kodiranja in inženiring funkcij

Začnimo z delitvijo Age v skupine, ki se razlikujejo po 10, tako da imamo 20-30, 30-40, 40-50 itd. Ker je naša najmlajša stranka stara 15 let, lahko začnemo pri 15 in končamo pri 70, kar je starost najstarejše stranke v podatkih. Začenši pri 15 in konča pri 70, bi imeli intervale 15-20, 20-30, 30-40, 40-50, 50-60 in 60-70.

Za skupino oz bin Age vrednosti v te intervale, lahko uporabimo Pande cut() način, da jih razrežete v koše in nato dodelite koše novemu Age Groups stolpec:

intervals = [15, 20, 30, 40, 50, 60, 70]
col = customer_data['Age']
customer_data['Age Groups'] = pd.cut(x=col, bins=intervals)


customer_data['Age Groups'] 

Rezultat tega je:

0      (15, 20]
1      (20, 30]
2      (15, 20]
3      (20, 30]
4      (30, 40]
         ...   
195    (30, 40]
196    (40, 50]
197    (30, 40]
198    (30, 40]
199    (20, 30]
Name: Age Groups, Length: 200, dtype: category
Categories (6, interval[int64, right]): [(15, 20] < (20, 30] < (30, 40] < (40, 50] < (50, 60] < (60, 70]]

Upoštevajte, da je pri ogledu vrednosti stolpcev tudi vrstica, ki določa, da imamo 6 kategorij, in prikazuje vse razporejene intervale podatkov. Na ta način smo naše prejšnje numerične podatke kategorizirali in ustvarili nove Age Groups lastnost.

In koliko strank imamo v vsaki kategoriji? To lahko hitro ugotovimo tako, da združimo stolpec in preštejemo vrednosti z njim groupby() in count():

customer_data.groupby('Age Groups')['Age Groups'].count()

Rezultat tega je:

Age Groups
(15, 20]    17
(20, 30]    45
(30, 40]    60
(40, 50]    38
(50, 60]    23
(60, 70]    17
Name: Age Groups, dtype: int64

Preprosto opazimo, da je večina strank starih med 30 in 40 let, sledijo stranke med 20 in 30 in nato stranke med 40 in 50. To je dober podatek tudi za oddelek marketinga.

Trenutno imamo dve kategorični spremenljivki, Age in Genre, ki jih moramo pretvoriti v števila, da jih lahko uporabimo v našem modelu. Obstaja veliko različnih načinov za to preobrazbo – uporabili bomo Pande get_dummies() metoda, ki ustvari nov stolpec za vsak interval in zvrst in nato zapolni njegove vrednosti z 0 in 1 - ta vrsta operacije se imenuje enkratno kodiranje. Poglejmo, kako izgleda:


customer_data_oh = pd.get_dummies(customer_data)

customer_data_oh 

To nam bo dalo predogled nastale tabele:

img

Z rezultatom je enostavno videti, da stolpec Genre je bil razdeljen na stolpce – Genre_Female in Genre_Male. Ko je stranka ženska, Genre_Female je enako 1, in ko je stranka moški, je enako 0.

Prav tako je Age Groups stolpec je bil razdeljen na 6 stolpcev, enega za vsak interval, kot npr Age Groups_(15, 20], Age Groups_(20, 30], in tako naprej. Na enak način kot Genre, ko je stranka stara 18 let, se Age Groups_(15, 20] vrednost je 1 in vrednost vseh drugih stolpcev je 0.

O Prednost enovročega kodiranja je preprostost pri predstavljanju vrednosti stolpcev, preprosto je razumeti, kaj se dogaja – medtem ko pomanjkljivost je, da smo zdaj ustvarili 8 dodatnih stolpcev, če povzamemo stolpce, ki smo jih že imeli.

Opozorilo: Če imate nabor podatkov, v katerem število enkratno kodiranih stolpcev presega število vrstic, je najbolje, da uporabite drugo metodo kodiranja, da se izognete težavam z dimenzionalnostjo podatkov.

Enkratno kodiranje našim podatkom doda tudi ničle, zaradi česar so bolj redki, kar je lahko težava za nekatere algoritme, ki so občutljivi na redkost podatkov.

Zdi se, da za naše potrebe združevanja v gruče deluje enkratno kodiranje. Lahko pa narišemo podatke, da vidimo, ali res obstajajo različne skupine, ki jih lahko združimo.

Osnovno risanje in zmanjšanje dimenzionalnosti

Naš nabor podatkov ima 11 stolpcev in obstaja nekaj načinov, na katere lahko te podatke vizualiziramo. Prvi je tako, da ga narišete v 10 dimenzijah (vso srečo s tem). Deset, ker Customer_ID stolpec se ne upošteva. Drugi je z izrisom naših začetnih numeričnih značilnosti, tretji pa s preoblikovanjem naših 10 značilnosti v 2 – torej z zmanjšanjem dimenzionalnosti.

Izris vsakega para podatkov

Ker je risanje 10 dimenzij nekoliko nemogoče, se bomo odločili za drugi pristop – izrisali bomo svoje začetne značilnosti. Za našo analizo grozdenja lahko izberemo dva. Eden od načinov, kako lahko vidimo vse naše podatkovne pare skupaj, je Seaborn pairplot():

import seaborn as sns


customer_data = customer_data.drop('CustomerID', axis=1)

sns.pairplot(customer_data)

Kateri prikazuje:

img

Na prvi pogled lahko opazimo razpršene diagrame, za katere se zdi, da imajo skupine podatkov. Ena, ki se zdi zanimiva, je razpršena ploskev, ki združuje Annual Income in Spending Score. Upoštevajte, da ni jasne ločitve med drugimi spremenljivkami razpršitve. Morda lahko povemo največ, da obstajata dve različni koncentraciji točk v Spending Score vs Age graf raztrosa.

Obe razpršilni ploskvi, sestavljeni iz Annual Income in Spending Score sta v bistvu enaka. Vidimo ga lahko dvakrat, ker sta bili osi x in y zamenjani. Če pogledamo katero koli od njih, lahko vidimo, kar se zdi pet različnih skupin. Načrtujmo samo ti dve lastnosti s Seabornom scatterplot() da pogledam pobližje:

sns.scatterplot(x=customer_data['Annual Income (k$)'],
                y=customer_data['Spending Score (1-100)'])

img

Če pogledamo podrobneje, lahko zagotovo ločimo 5 različnih skupin podatkov. Zdi se, da je naše stranke mogoče razvrstiti v skupine glede na to, koliko zaslužijo na leto in koliko porabijo. To je še ena pomembna točka v naši analizi. Pomembno je, da pri združevanju naših strank upoštevamo le dve lastnosti. Druge informacije, ki jih imamo o njih, ne sodijo v enačbo. To daje analizi smisel – če vemo, koliko stranka zasluži in porabi, zlahka najdemo podobnosti, ki jih potrebujemo.

img

To je super! Zaenkrat že imamo dve spremenljivki za izdelavo našega modela. Poleg tega, kar to predstavlja, naredi model tudi enostavnejši, skromnejši in bolj razložljiv.

Oglejte si naš praktični, praktični vodnik za učenje Gita z najboljšimi praksami, standardi, sprejetimi v panogi, in priloženo goljufijo. Nehajte Googlati ukaze Git in pravzaprav naučiti it!

Opomba: Data Science običajno daje prednost čim bolj preprostim pristopom. Ne le zato, ker je lažje razložiti za podjetje, ampak tudi zato, ker je bolj neposreden – z 2 funkcijama in razložljivim modelom je jasno, kaj model počne in kako deluje.

Izris podatkov po uporabi PCA

Zdi se, da je naš drugi pristop verjetno najboljši, a poglejmo tudi naš tretji pristop. Uporabno je lahko, kadar podatkov ne moremo izrisati, ker imajo preveč razsežnosti, ali ko ni koncentracij podatkov ali jasnega ločevanja v skupinah. Ko pride do teh situacij, je priporočljivo poskusiti zmanjšati dimenzije podatkov z metodo, imenovano Analiza glavne komponente (PCA).

Opomba: Večina ljudi uporablja PCA za zmanjšanje dimenzionalnosti pred vizualizacijo. Obstajajo tudi druge metode, ki pomagajo pri vizualizaciji podatkov pred združevanjem v gruče, kot npr Prostorsko združevanje aplikacij s šumom na podlagi gostote (DBSCAN) in Samoorganizirajoči se zemljevidi (SOM) grozdenje. Oba sta algoritma za združevanje v gruče, vendar ju je mogoče uporabiti tudi za vizualizacijo podatkov. Ker analiza združevanja v gruče nima zlatega standarda, je pomembno primerjati različne vizualizacije in različne algoritme.

PCA bo zmanjšal dimenzije naših podatkov, obenem pa poskušal ohraniti čim več svojih informacij. Najprej si oglejmo, kako deluje PCA, nato pa lahko izberemo, na koliko dimenzij podatkov bomo zmanjšali svoje podatke.

Za vsak par funkcij PCA ugotovi, ali se večje vrednosti ene spremenljivke ujemajo z večjimi vrednostmi druge spremenljivke, in stori enako za nižje vrednosti. Torej v bistvu izračuna, koliko se vrednosti lastnosti razlikujejo ena proti drugi – temu pravimo njihove kovarijance. Ti rezultati so nato organizirani v matriko, pri čemer dobimo a kovariančno matriko.

Po pridobitvi kovariančne matrike poskuša PCA najti linearno kombinacijo funkcij, ki to najbolje razloži – prilega se linearnim modelom, dokler ne identificira tistega, ki pojasnjuje največja znesek variance.

Opombe: PCA je linearna transformacija, linearnost pa je občutljiva na obseg podatkov. Zato PCA najbolje deluje, če so vse vrednosti podatkov na isti lestvici. To lahko storite z odštevanjem stolpca pomeni od njenih vrednosti in rezultat delite s standardnim odklonom. To se imenuje standardizacija podatkov. Pred uporabo PCA preverite, ali so podatki prilagojeni! Če niste prepričani, kako, preberite naše »Feature Scaling Data s Scikit-Learn za strojno učenje v Pythonu«!

Z najdeno najboljšo črto (linearno kombinacijo) PCA dobi smeri svojih osi, imenovanih lastni vektorji, in njegovi linearni koeficienti, the lastne vrednosti. Kombinacija lastnih vektorjev in lastnih vrednosti – ali smeri osi in koeficientov – so Glavne komponente PCA. In takrat lahko izberemo svoje število dimenzij na podlagi razložene variance vsake lastnosti, tako da razumemo, katere glavne komponente želimo obdržati ali zavreči glede na to, koliko variance pojasnjujejo.

Po pridobitvi glavnih komponent PCA uporabi lastne vektorje za oblikovanje vektorja funkcij, ki preusmerijo podatke iz prvotnih osi na tiste, ki jih predstavljajo glavne komponente – tako se zmanjšajo dimenzije podatkov.

Opomba: Ena pomembna podrobnost, ki jo je treba tukaj upoštevati, je, da bo PCA zaradi svoje linearne narave koncentriral večino razložene variance v prvih glavnih komponentah. Če pogledamo razloženo varianco, bosta običajno zadostovali prvi dve komponenti. Toda to je lahko v nekaterih primerih zavajajoče – zato poskušajte pri združevanju v gruče še naprej primerjati različne diagrame in algoritme, da vidite, ali imajo podobne rezultate.

Preden uporabimo PCA, moramo izbrati med Age stolpec ali Age Groups stolpcev v naših predhodno enkratno kodiranih podatkih. Ker oba stolpca predstavljata iste informacije, dvakratna uvedba vpliva na našo varianco podatkov. Če je Age Groups izbran stolpec, preprosto odstranite Age stolpec z uporabo pand drop() in jo znova dodelite customer_data_oh spremenljivka:

customer_data_oh = customer_data_oh.drop(['Age'], axis=1)
customer_data_oh.shape 

Zdaj imajo naši podatki 10 stolpcev, kar pomeni, da lahko pridobimo eno glavno komponento za stolpcem in izberemo, koliko jih bomo uporabili, tako da izmerimo, v kolikšni meri uvedba ene nove dimenzije pojasni več naše variance podatkov.

Naredimo to s Scikit-Learn PCA. Izračunali bomo razloženo varianco vsake dimenzije, podano z explained_variance_ratio_ , nato pa si oglejte njihovo kumulativno vsoto z cumsum() :

from sklearn.decomposition import PCA

pca = PCA(n_components=10)
pca.fit_transform(customer_data_oh)
pca.explained_variance_ratio_.cumsum()

Naše kumulativne razložene razlike so:

array([0.509337  , 0.99909504, 0.99946364, 0.99965506, 0.99977937,
       0.99986848, 0.99993716, 1.        , 1.        , 1.        ])

Vidimo lahko, da prva dimenzija pojasni 50 % podatkov, v kombinaciji z drugo dimenzijo pa 99 % odstotkov. To pomeni, da prvi 2 dimenziji pojasnjujeta že 99 % naših podatkov. Tako lahko uporabimo PCA z 2 komponentama, pridobimo naše glavne komponente in jih narišemo:

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
pcs = pca.fit_transform(customer_data_oh)

pc1_values = pcs[:,0]
pc2_values = pcs[:,1]
sns.scatterplot(x=pc1_values, y=pc2_values)

img

Graf podatkov po PCA je zelo podoben grafu, ki uporablja samo dva stolpca podatkov brez PCA. Opazite, da so točke, ki tvorijo skupine, bližje in malo bolj koncentrirane po PCA kot prej.

img

Vizualizacija hierarhične strukture z dendrogrami

Doslej smo raziskali podatke, enkratno kodirane kategorične stolpce, se odločili, kateri stolpci so primerni za združevanje v gruče, in zmanjšali dimenzionalnost podatkov. Grafi kažejo, da imamo v naših podatkih 5 gruč, vendar obstaja tudi drug način za vizualizacijo odnosov med našimi točkami in pomoč pri določanju števila gruč – z ustvarjanjem dendrogram (pogosto napačno črkovano kot dendogram). dendro pomeni Drevo v latinščini.

O dendrogram je rezultat povezovanja točk v nizu podatkov. Je vizualna predstavitev hierarhičnega procesa združevanja v gruče. In kako deluje hierarhični proces združevanja v gruče? No ... odvisno – verjetno odgovor, ki ste ga že veliko slišali v Data Science.

Razumevanje hierarhičnega združevanja v gruče

Ko Hierarhični algoritem združevanja v gruče (HCA) začne povezovati točke in iskati skupine, lahko najprej razdeli točke v 2 veliki skupini, nato pa vsako od teh dveh skupin razdeli na 2 manjši skupini, ki ima skupaj 4 skupine, kar je ločljiv in od zgoraj navzdol pristop.

Druga možnost je, da lahko naredi nasprotno – pogleda lahko vse podatkovne točke, poišče 2 točki, ki sta bližje druga drugi, ju poveže in nato najde druge točke, ki so najbližje tem povezanim točkam, in nadaljuje z gradnjo 2 skupini Iz Od spodaj navzgor. Kar je aglomerativni pristop, ki ga bomo razvili.

Koraki za izvedbo aglomerativnega hierarhičnega združevanja v gruče

Da bi bil aglomeracijski pristop še bolj jasen, obstajajo koraki Aglomerativno hierarhično združevanje (AHC) algoritem:

  1. Na začetku vsako podatkovno točko obravnavajte kot eno gručo. Zato bo število gruč na začetku K – medtem ko je K celo število, ki predstavlja število podatkovnih točk.
  2. Oblikujte gručo tako, da združite dve najbližji podatkovni točki, kar povzroči gruče K-1.
  3. Oblikujte več grozdov tako, da združite dva najbližja grozda, kar ima za posledico grozde K-2.
  4. Ponavljajte zgornje tri korake, dokler ne nastane en velik grozd.

Opombe: Za poenostavitev govorimo o "dveh najbližjih" podatkovnih točkah v 2. in 3. koraku. Obstaja pa več načinov za povezovanje točk, kot bomo videli čez nekaj časa.

Če korake algoritma ACH obrnete s 4 na 1 – to bi bili koraki do *Razdeljujoče hierarhično združevanje (DHC)*.

Upoštevajte, da so HCA lahko razdelilni in usmerjeni od zgoraj navzdol ali aglomerativni in usmerjeni od spodaj navzgor. Pristop DHC od zgoraj navzdol najbolje deluje, če imate manj, a večje gruče, zato je računsko dražji. Po drugi strani pa je pristop AHC od spodaj navzgor primeren, ko imate veliko manjših grozdov. Je računsko preprostejši, bolj uporaben in bolj dostopen.

Opomba: Bodisi od zgoraj navzdol bodisi od spodaj navzgor se bo dendrogramska predstavitev procesa združevanja v gruče vedno začela z delitvijo na dvoje in končala z razlikovanjem vsake posamezne točke, ko je njena osnovna struktura binarno drevo.

Narišite naš dendrogram podatkov o strankah, da vizualiziramo hierarhične odnose podatkov. Tokrat bomo uporabili scipy knjižnica za ustvarjanje dendrograma za naš nabor podatkov:

import scipy.cluster.hierarchy as shc
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 7))
plt.title("Customers Dendrogram")


selected_data = customer_data_oh.iloc[:, 1:3]
clusters = shc.linkage(selected_data, 
            method='ward', 
            metric="euclidean")
shc.dendrogram(Z=clusters)
plt.show()

Izhod skripta izgleda takole:

img

V zgornjem skriptu smo ustvarili gruče in podgruče z našimi točkami, definirali, kako naj se naše točke povezujejo (z uporabo ward metoda) in kako izmeriti razdaljo med točkami (z uporabo euclidean metrika).

Z izrisom dendrograma je mogoče vizualizirati opisane procese DHC in AHC. Za vizualizacijo pristopa od zgoraj navzdol začnite z vrha dendrograma in se spustite navzdol ter naredite nasprotno, začnite navzdol in se pomaknite navzgor, da vizualizirate pristop od spodaj navzgor.

Metode povezovanja

Obstaja veliko drugih načinov povezovanja, če boste bolje razumeli, kako delujejo, boste lahko izbrali ustreznega za svoje potrebe. Poleg tega bo vsaka od njih ob uporabi prinesla različne rezultate. Pri analizi združevanja v gruče ni fiksnega pravila, če je mogoče, preučite naravo problema, da vidite, katera najbolj ustreza, preizkusite različne metode in preglejte rezultate.

Nekatere metode povezovanja so:

  • Enojna povezava: imenovan tudi kot Najbližji sosed (NN). Razdalja med grozdi je določena z razdaljo med njihovimi najbližjimi členi.

img

  • Popolna povezava: imenovan tudi kot Najdaljši sosed (FN), Algoritem za najdaljšo točkoali Algoritem Voor Hees. Razdalja med grozdi je določena z razdaljo med njihovimi najbolj oddaljenimi členi. Ta metoda je računsko draga.

img

  • Povprečna povezava: poznan tudi kot UPGMA (metoda neobtežene skupine parov z aritmetično sredino). Odstotek števila točk vsakega grozda se izračuna glede na število točk obeh grozdov, če bi bili združeni.

img

  • Utežena povezava: poznan tudi kot WPGMA (Metoda utežene skupine parov z aritmetično sredino). Posamezne točke obeh grozdov prispevajo k skupni razdalji med manjšim in večjim grozdom.
  • Centroidna povezava: imenovan tudi kot UPGMC (metoda neobtežene skupine parov z uporabo centroidov). Točka, definirana s povprečjem vseh točk (centroid), se izračuna za vsako gručo, razdalja med grozdi pa je razdalja med njihovimi težišči.

img

  • Wardova povezava: Poznan tudi kot MISSQ (Minimalno povečanje vsote kvadratov). Določa razdaljo med dvema grozdoma, izračuna napako vsote kvadratov (ESS) in zaporedno izbere naslednje grozde na podlagi manjšega ESS. Wardova metoda poskuša minimizirati povečanje ESS na vsakem koraku. Zato zmanjšanje napake.

img

Meritve razdalje

Poleg povezave lahko določimo tudi nekaj najpogosteje uporabljenih meritev razdalje:

  • evklidsko: imenovan tudi kot Pitagorejska ali ravna črta razdalja. Izračuna razdaljo med dvema točkama v prostoru z merjenjem dolžine črte, ki poteka med njima. Uporablja Pitagorov izrek in vrednost razdalje je rezultat (C) enačbe:

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

  • Manhattan: imenovan tudi Mestna ulica, taksi razdalja. Je vsota absolutnih razlik med merami v vseh dimenzijah dveh točk. Če sta ti razsežnosti dve, je to podobno, kot da naredite desno in nato levo, ko hodite en blok.

img

  • Minkowski: je posplošitev evklidske in manhattanske razdalje. To je način za izračun razdalj na podlagi absolutnih razlik v vrstnem redu metrike Minkowskega p. Čeprav je opredeljen za katero koli p> 0, se redko uporablja za vrednosti, ki niso 1, 2 in ∞ (neskončno). Razdalja Minkowskega je enaka razdalji Manhattna, ko p = 1, in enako kot evklidska razdalja, ko p = 2.

$$
Dlevo(X,Ydesno) = levo(vsota_{i=1}^n |x_i-y_i|^pravo)^{frac{1}{p}}
$$

img

  • Chebyshev: poznan tudi kot Šahovnica razdalja. To je skrajni primer razdalje Minkowskega. Ko kot vrednost parametra uporabimo neskončnost p (p = ∞), na koncu dobimo metriko, ki definira razdaljo kot največjo absolutno razliko med koordinatami.
  • Cosine: je kotna kosinusna razdalja med dvema zaporedjema točk ali vektorjev. Kosinusna podobnost je pikčasti produkt vektorjev, deljen s produktom njihovih dolžin.
  • Jaccard: meri podobnost med končnimi množicami točk. Definiran je kot skupno število točk (kardinalnost) v skupnih točkah v vsakem nizu (presek), deljeno s skupnim številom točk (kardinalnost) skupnih točk obeh nizov (unija).
  • Jensen-Shannon: temelji na divergenci Kullback-Leibler. Upošteva porazdelitve verjetnosti točk in meri podobnost med temi porazdelitvami. Je priljubljena metoda teorije verjetnosti in statistike.

Izbrali smo Ward in evklidsko za dendrogram, ker sta najpogosteje uporabljena metoda in metrika. Običajno dajejo dobre rezultate, saj Ward povezuje točke na podlagi minimiziranja napak, Euclidean pa dobro deluje v nižjih dimenzijah.

V tem primeru delamo z dvema funkcijama (stolpcema) trženjskih podatkov in 200 opazovanji ali vrsticami. Ker je število opazovanj večje od števila značilnosti (200 > 2), delamo v nizkodimenzionalnem prostoru.

Ko število funkcij (F) je večje od števila opazovanj (N) – večinoma napisana kot f >> N, to pomeni, da imamo a prostor visokih dimenzij.

Če bi vključili več atributov, tako da imamo več kot 200 funkcij, evklidska razdalja morda ne bi delovala dobro, saj bi imela težave pri merjenju vseh majhnih razdalj v zelo velikem prostoru, ki se samo povečuje. Z drugimi besedami, pristop evklidske razdalje ima težave pri delu s podatki redkost. To je vprašanje, ki se imenuje prekletstvo dimenzionalnosti. Vrednosti razdalje bi postale tako majhne, ​​kot da bi postale "razredčene" v večjem prostoru, popačene, dokler ne bi postale 0.

Opomba: Če kdaj naletite na nabor podatkov z f >> str, boste verjetno uporabili druge meritve razdalje, kot je Mahalanobis razdalja. Lahko pa tudi zmanjšate dimenzije nabora podatkov z uporabo Analiza glavne komponente (PCA). Ta težava je pogosta zlasti pri združevanju podatkov o biološkem zaporedju.

Razpravljali smo že o meritvah, povezavah in o tem, kako lahko vsaka od njih vpliva na naše rezultate. Nadaljujmo z analizo dendrograma in poglejmo, kako nam lahko da navedbo števila gruč v našem naboru podatkov.

Iskanje zanimivega števila grozdov v dendrogramu je enako kot iskanje največjega vodoravnega prostora, ki nima navpičnih črt (prostor z najdaljšimi navpičnimi črtami). To pomeni, da je večja ločitev med grozdi.

Lahko narišemo vodoravno črto, ki poteka skozi to najdaljšo razdaljo:

plt.figure(figsize=(10, 7))
plt.title("Customers Dendogram with line")
clusters = shc.linkage(selected_data, 
            method='ward', 
            metric="euclidean")
shc.dendrogram(clusters)
plt.axhline(y = 125, color = 'r', linestyle = '-')

img

Ko lociramo vodoravno črto, preštejemo, kolikokrat je prečkala naše navpične črte – v tem primeru 5-krat. Torej se zdi, da je 5 dober pokazatelj števila gruč, med katerimi je največja razdalja.

Opombe: Dendrogram je treba obravnavati le kot referenco, ko se uporablja za izbiro števila grozdov. Z lahkoto se lahko zelo znebi te številke, nanjo pa popolnoma vplivata vrsta povezave in metrika razdalje. Pri izvajanju poglobljene analize grozdov je priporočljivo pogledati dendrograme z različnimi povezavami in metrikami ter pogledati rezultate, ustvarjene s prvimi tremi vrsticami, v katerih imajo grozdi največjo razdaljo med seboj.

Implementacija aglomerativne hierarhične gruče

Uporaba izvirnih podatkov

Doslej smo izračunali predlagano število grozdov za naš nabor podatkov, ki potrjujejo našo prvotno analizo in analizo PCA. Zdaj lahko ustvarimo naš aglomerativni hierarhični model združevanja v gruče z uporabo Scikit-Learn AgglomerativeClustering in poiščite oznake tržnih točk z labels_:

from sklearn.cluster import AgglomerativeClustering

clustering_model = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model.fit(selected_data)
clustering_model.labels_

Rezultat tega je:

array([4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3,
       4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 1,
       4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 0, 2, 0, 2,
       1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2,
       0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
       0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
       0, 2])

Veliko smo preiskali, da smo prišli do te točke. In kaj te oznake pomenijo? Tu imamo vsako točko naših podatkov označeno kot skupina od 0 do 4:

data_labels = clustering_model.labels_
sns.scatterplot(x='Annual Income (k$)', 
                y='Spending Score (1-100)', 
                data=selected_data, 
                hue=data_labels,
                pallete="rainbow").set_title('Labeled Customer Data')

img

To so naši končni gručasti podatki. Vidite lahko barvno označene podatkovne točke v obliki petih skupin.

Podatkovne točke spodaj desno (oznaka: 0, vijolične podatkovne točke) pripadajo strankam z visokimi plačami, a nizko porabo. To so stranke, ki skrbno trošijo svoj denar.

Podobno stranke zgoraj desno (oznaka: 2, zelene podatkovne točke), so stranke z visokimi plačami in visoko porabo. To so vrste strank, na katere ciljajo podjetja.

Stranke na sredini (oznaka: 1, modre podatkovne točke) so tisti s povprečnim dohodkom in povprečno porabo. V to kategorijo sodi največ strank. Podjetja lahko ciljajo tudi na te stranke, saj jih je ogromno.

Stranke spodaj levo (oznaka: 4, rdeča) so kupci z nizkimi plačami in nizko porabo, bi jih lahko pritegnili s promocijami.

In končno, stranke v zgornjem levem kotu (oznaka: 3, oranžne podatkovne točke) so tiste z visokim dohodkom in nizko porabo, na katere trženje najbolje cilja.

Uporaba rezultata PCA

Če bi bili v drugačnem scenariju, v katerem bi morali zmanjšati dimenzionalnost podatkov. Z lahkoto bi lahko narisali tudi rezultate PCA v skupinah. To lahko storite tako, da ustvarite drug aglomerativni model združevanja v gruče in pridobite podatkovno oznako za vsako glavno komponento:

clustering_model_pca = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model_pca.fit(pcs)

data_labels_pca = clustering_model_pca.labels_

sns.scatterplot(x=pc1_values, 
                y=pc2_values,
                hue=data_labels_pca,
                palette="rainbow").set_title('Labeled Customer Data Reduced with PCA')

img

Upoštevajte, da sta si oba rezultata zelo podobna. Glavna razlika je v tem, da je prvi rezultat z izvirnimi podatki veliko lažje razložiti. Jasno je videti, da lahko stranke razdelimo v pet skupin glede na njihov letni prihodek in porabo. Medtem ko pri pristopu PCA upoštevamo vse naše lastnosti, je to koncept težje razumeti, zlasti če poročamo oddelku za trženje, ne glede na to, ali lahko pogledamo varianco, ki jo pojasnjuje vsaka od njih.

Čim manj moramo preoblikovati svoje podatke, tem bolje.

Če imate zelo velik in zapleten nabor podatkov, v katerem morate pred združevanjem v gruče izvesti zmanjšanje dimenzionalnosti – poskusite analizirati linearna razmerja med vsako od funkcij in njihovimi ostanki, da podprete uporabo PCA in povečate razložljivost postopka. Če naredite linearni model na par funkcij, boste lahko razumeli, kako funkcije medsebojno delujejo.

Če je količina podatkov tako velika, postane nemogoče narisati pare funkcij, izbrati vzorec vaših podatkov, čim bolj uravnotežen in bližje normalni porazdelitvi, in najprej izvesti analizo vzorca, ga razumeti, natančno prilagoditi in ga pozneje uporabite za celoten nabor podatkov.

Vedno lahko izberete različne tehnike vizualizacije združevanja v gruče glede na naravo svojih podatkov (linearni, nelinearni) in jih po potrebi združite ali preizkusite.

zaključek

Tehnika združevanja v gruče je lahko zelo priročna, ko gre za neoznačene podatke. Ker je večina podatkov v realnem svetu neoznačenih in ima označevanje podatkov višje stroške, je mogoče uporabiti tehnike združevanja v gruče za označevanje neoznačenih podatkov.

V tem priročniku smo predstavili resnično težavo podatkovne znanosti, saj se tehnike združevanja v gruče v veliki meri uporabljajo v tržni analizi (in tudi v biološki analizi). Razložili smo tudi številne korake preiskave, da pridemo do dobrega hierarhičnega modela združevanja v gruče in kako brati dendrograme, ter se vprašali, ali je PCA potreben korak. Naš glavni cilj je pokriti nekatere pasti in različne scenarije, v katerih lahko najdemo hierarhično združevanje v gruče.

Veselo združevanje!

Časovni žig:

Več od Stackabuse