Ostateczny przewodnik po hierarchicznym klastrowaniu za pomocą Pythona i Scikit-Learn PlatoBlockchain Data Intelligence. Wyszukiwanie pionowe. AI.

Ostateczny przewodnik po hierarchicznym klastrowaniu za pomocą Pythona i Scikit-Learn

Wprowadzenie

W tym przewodniku skupimy się na wdrażaniu Hierarchiczny algorytm klastrowania z Scikit-Learn rozwiązać problem marketingowy.

Po przeczytaniu poradnika zrozumiesz:

  • Kiedy stosować klastrowanie hierarchiczne
  • Jak wizualizować zestaw danych, aby zrozumieć, czy nadaje się on do grupowania
  • Jak wstępnie przetwarzać funkcje i opracowywać nowe funkcje na podstawie zbioru danych?
  • Jak zmniejszyć wymiarowość zbioru danych za pomocą PCA?
  • Jak używać i odczytywać dendrogram dla osobnych grup
  • Jakie są różne metody łączenia i metryki odległości stosowane do dendrogramów i algorytmów grupowania
  • Jakie są aglomeracyjne i podziałowe strategie klastrowania i jak one działają?
  • Jak wdrożyć klaster aglomeracyjny hierarchiczny za pomocą Scikit-Learn
  • Jakie są najczęstsze problemy związane z algorytmami klastrowania i jak je rozwiązać?

Uwaga: Możesz pobrać notatnik zawierający cały kod z tego przewodnika tutaj.

Motywacja

Wyobraź sobie scenariusz, w którym jesteś częścią zespołu ds. analizy danych, który współpracuje z działem marketingu. Marketing od jakiegoś czasu zbiera dane o zakupach klientów i chcą zrozumieć, na podstawie zebranych danych, czy są podobieństwa między klientami. Te podobieństwa dzielą klientów na grupy, a posiadanie grup klientów pomaga w ukierunkowaniu kampanii, promocji, konwersji i budowaniu lepszych relacji z klientami.

Czy możesz pomóc w ustaleniu, którzy klienci są podobni? Ilu z nich należy do tej samej grupy? A ile jest różnych grup?

Jednym ze sposobów odpowiedzi na te pytania jest użycie a klastrowanie algorytm, taki jak K-Means, DBSCAN, klastrowanie hierarchiczne itp. Ogólnie rzecz biorąc, algorytmy klastrowania znajdują podobieństwa między punktami danych i grupują je.

W tym przypadku nasze dane marketingowe są dość małe. Posiadamy informacje tylko o 200 klientach. Biorąc pod uwagę zespół marketingowy, ważne jest, abyśmy mogli jasno wytłumaczyć im, w jaki sposób podejmowano decyzje na podstawie liczby klastrów, a tym samym wyjaśnić im, jak faktycznie działa algorytm.

Ponieważ nasze dane są niewielkie, a wytłumaczenie jest głównym czynnikiem, możemy wykorzystać Klastrowanie hierarchiczne by rozwiązać ten problem. Ten proces jest również znany jako Hierarchiczna analiza klastrów (HCA).

Jedną z zalet HCA jest to, że można ją interpretować i działa dobrze na małych zestawach danych.

Inną rzeczą, którą należy wziąć pod uwagę w tym scenariuszu, jest to, że HCA jest bez nadzoru algorytm. Podczas grupowania danych nie będziemy mieli możliwości sprawdzenia, czy poprawnie identyfikujemy, czy użytkownik należy do określonej grupy (nie znamy grup). Nie ma etykiet, z którymi moglibyśmy porównać nasze wyniki. Jeśli poprawnie zidentyfikujemy grupy, zostanie to później potwierdzone przez dział marketingu na co dzień (mierzone za pomocą wskaźników takich jak ROI, współczynniki konwersji itp.).

Teraz, gdy zrozumieliśmy problem, który próbujemy rozwiązać i jak go rozwiązać, możemy zacząć przyglądać się naszym danym!

Krótka eksploracyjna analiza danych

Uwaga: Możesz pobrać zestaw danych użyty w tym przewodniku tutaj.

Po pobraniu zestawu danych zwróć uwagę, że jest to CSV (wartości rozdzielone przecinkami) plik o nazwie shopping-data.csv. Aby ułatwić eksplorację danych i manipulowanie nimi, załadujemy je do DataFrame za pomocą Pand:

import pandas as pd


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

Marketing powiedział, że zebrał 200 rekordów klientów. Możemy sprawdzić, czy pobrane dane są kompletne z 200 wierszami, używając shape atrybut. Powie nam, ile mamy odpowiednio wierszy i kolumn:

customer_data.shape

To skutkuje:

(200, 5)

Świetny! Nasze dane zawierają 200 wierszy (rekordy klientów) i mamy też 5 kolumn (cechy). Aby zobaczyć, jakie cechy dział marketingu zebrał od klientów, możemy zobaczyć nazwy kolumn z columns atrybut. Aby to zrobić, wykonaj:

customer_data.columns

Powyższy skrypt zwraca:

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

Tutaj widzimy, że marketing wygenerował CustomerID, zebrał Genre, Age, Annual Income (w tysiącach dolarów) i Spending Score od 1 do 100 dla każdego z 200 klientów. Zapytani o wyjaśnienie, powiedzieli, że wartości w Spending Score kolumna wskazuje, jak często dana osoba wydaje pieniądze w centrum handlowym w skali od 1 do 100. Innymi słowy, jeśli klient ma wynik 0, ta osoba nigdy nie wydaje pieniędzy, a jeśli wynik wynosi 100, właśnie zauważyliśmy najwięcej wydających.

Rzućmy okiem na rozkład tego wyniku, aby sprawdzić nawyki związane z wydatkami użytkowników w naszym zbiorze danych. To tam Pandy hist() metoda przychodzi z pomocą:

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

img

Patrząc na histogram widzimy, że ponad 35 klientów ma wyniki między 40 i 60, to mniej niż 25 punktów ma wynik między 70 i 80. Więc większość naszych klientów to zrównoważonych wydatków, a następnie wydający od umiarkowanych do wysokich. Widzimy też, że za linią jest linia 0, po lewej stronie rozkładu i kolejny wiersz przed 100, po prawej stronie rozkładu. Te puste miejsca prawdopodobnie oznaczają, że dystrybucja nie zawiera osób nie wydających, które miałyby wynik 0, oraz że nie ma również osób wysoko wydających z wynikiem 100.

Aby sprawdzić, czy to prawda, możemy spojrzeć na minimalne i maksymalne wartości rozkładu. Wartości te można łatwo znaleźć w ramach statystyk opisowych, dzięki czemu możemy wykorzystać describe() sposób na zrozumienie innych rozkładów wartości liczbowych:


customer_data.describe().transpose()

To da nam tabelę, z której możemy odczytać rozkłady innych wartości naszego zbioru danych:

 						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

Nasza hipoteza jest potwierdzona. The min wartość Spending Score is 1 a maksimum to 99. Więc nie mamy 0 or 100 punkty wydające. Przyjrzyjmy się zatem pozostałym kolumnom transpozycji describe stół. Patrząc na mean i std kolumny, widzimy to dla Age dotychczasowy mean is 38.85 oraz std około 13.97. To samo dzieje się z Annual Income, Z mean of 60.56 i std 26.26, A na Spending Score z mean of 50 i std of 25.82. W przypadku wszystkich funkcji mean jest daleka od odchylenia standardowego, co wskazuje nasze dane charakteryzują się dużą zmiennością.

Aby lepiej zrozumieć, jak zmieniają się nasze dane, wykreślmy Annual Income dystrybucja:

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

Co da nam:

img

Zauważ na histogramie, że większość naszych danych, ponad 35 klientów, koncentruje się w pobliżu tej liczby 60, na naszym mean, w osi poziomej. Ale co się dzieje, gdy zbliżamy się do końca dystrybucji? Idąc w lewo, od średniej 60.560 USD, następną wartością, jaką napotkamy, jest 34.300 USD – średnia (60.560 USD) minus standardowa odmiana (26.260 USD). Jeśli pójdziemy dalej na lewo od naszego rozkładu danych, obowiązuje podobna reguła, odejmujemy standardową odmianę (26.260 USD) od bieżącej wartości (34.300 USD). W związku z tym napotkamy wartość 8.040 USD. Zwróć uwagę, jak szybko nasze dane wzrosły z 60 tys. do 8 tys. To „skacze” za każdym razem 26.260 $ – bardzo się różni i dlatego mamy tak dużą zmienność.

img

Zmienność i rozmiar danych są ważne w analizie skupień, ponieważ pomiary odległości większości algorytmów grupowania są wrażliwe na wielkości danych. Różnica w rozmiarze może zmienić wyniki grupowania, sprawiając, że jeden punkt wydaje się bliższy lub bardziej oddalony od drugiego niż w rzeczywistości, zniekształcając faktyczne grupowanie danych.

Do tej pory widzieliśmy kształt naszych danych, niektóre ich rozkłady i statystyki opisowe. W przypadku Pand możemy również wyświetlić listę naszych typów danych i sprawdzić, czy wszystkie nasze 200 wierszy są wypełnione, czy mają jakieś null wartości:

customer_data.info()

To skutkuje:

<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

Tutaj widzimy, że nie ma null wartości w danych i że mamy tylko jedną kolumnę kategoryczną – Genre. Na tym etapie ważne jest, abyśmy pamiętali o tym, jakie funkcje warto dodać do modelu grupowania. Jeśli chcemy dodać kolumnę Gatunek do naszego modelu, będziemy musieli przekształcić jej wartości z kategoryczny do liczbowy.

Zobaczmy, jak Genre jest wypełniany poprzez szybki rzut oka na pierwsze 5 wartości naszych danych:

customer_data.head() 

To skutkuje:

    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

Wygląda na to, że ma tylko Female i Male kategorie. Możemy być tego pewni, przyglądając się jego wyjątkowym wartościom z unique:

customer_data['Genre'].unique()

Potwierdza to nasze przypuszczenie:

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

Jak na razie wiemy, że mamy tylko dwa gatunki, jeśli planujemy wykorzystać tę funkcję w naszym modelu, Male można przekształcić w 0 i Female do 1. Ważne jest również, aby sprawdzić proporcje między gatunkami, aby zobaczyć, czy są one zrównoważone. Możemy to zrobić za pomocą value_counts() metoda i jej argument normalize=True aby pokazać procent między Male i Female:

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

To daje:

Female    0.56
Male      0.44
Name: Genre, dtype: float64

Mamy 56% kobiet w zbiorze danych i 44% mężczyzn. Różnica między nimi wynosi tylko 16%, a nasze dane to nie 50/50, ale wystarczająco zrównoważony nie sprawiać kłopotów. Jeśli wyniki byłyby 70/30, 60/40, to mogło być potrzebne albo zebranie większej ilości danych, albo zastosowanie jakiejś techniki wzbogacania danych, aby ten stosunek był bardziej zrównoważony.

Do tej pory wszystkie funkcje, ale Age, zostały krótko zbadane. W co dotyczy Age, zwykle interesujące jest podzielenie go na kosze, aby móc segmentować klientów na podstawie ich grup wiekowych. Jeśli to zrobimy, będziemy musieli przekształcić kategorie wiekowe w jedną liczbę przed dodaniem ich do naszego modelu. W ten sposób zamiast posługiwać się kategorią 15-20 lat, policzylibyśmy, ilu klientów jest w 15-20 kategorii i będzie to liczba w nowej kolumnie o nazwie 15-20.

Rada: W niniejszym poradniku przedstawiamy jedynie krótką eksploracyjną analizę danych. Ale możesz iść dalej i powinieneś iść dalej. Możesz sprawdzić, czy istnieją różnice w dochodach i różnice w punktacji w zależności od gatunku i wieku. To nie tylko wzbogaca analizę, ale prowadzi do lepszych wyników modelu. Aby zagłębić się w eksploracyjną analizę danych, sprawdź Rozdział EDA w „Praktyczne przewidywanie cen domów – uczenie maszynowe w Pythonie" Projekt z przewodnikiem.

Po domysłach, co można zrobić z kategorycznym – lub kategorycznym – być Genre i Age kolumn, zastosujmy to, co zostało omówione.

Kodowanie zmiennych i inżynieria funkcji

Zacznijmy od podzielenia Age na grupy, które różnią się po 10, tak że mamy 20-30, 30-40, 40-50 i tak dalej. Ponieważ nasz najmłodszy klient ma 15 lat, możemy zacząć od 15, a skończyć na 70, czyli wieku najstarszego klienta w danych. Zaczynając od 15, a kończąc na 70, mielibyśmy interwały 15-20, 20-30, 30-40, 40-50, 50-60 i 60-70.

Do grupy lub kosz Age wartości do tych przedziałów, możemy użyć Pandy cut() metoda na pocięcie ich na pojemniki, a następnie przypisanie pojemników do nowych Age Groups kolumna:

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'] 

To skutkuje:

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]]

Zwróć uwagę, że patrząc na wartości kolumn, istnieje również wiersz, który określa, że ​​mamy 6 kategorii i wyświetla wszystkie przedziały danych z przedziału. W ten sposób skategoryzowaliśmy nasze poprzednie dane liczbowe i stworzyliśmy nowe Age Groups cecha.

A ilu klientów mamy w każdej kategorii? Szybko możemy się o tym przekonać, grupując kolumnę i licząc wartości za pomocą groupby() i count():

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

To skutkuje:

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

Łatwo zauważyć, że większość klientów jest w wieku od 30 do 40 lat, następnie klienci od 20 do 30, a następnie klienci w wieku od 40 do 50 lat. Jest to również dobra informacja dla działu marketingu.

W tej chwili mamy dwie zmienne kategoryczne, Age i Genre, które musimy przekształcić w liczby, aby móc użyć w naszym modelu. Istnieje wiele różnych sposobów na dokonanie tej transformacji – użyjemy Pandy get_dummies() metoda, która tworzy nową kolumnę dla każdego przedziału i gatunku, a następnie wypełnia jej wartości zerami i jedynkami – taki rodzaj operacji nazywa się kodowanie na gorąco. Zobaczmy jak to wygląda:


customer_data_oh = pd.get_dummies(customer_data)

customer_data_oh 

To da nam podgląd wynikowej tabeli:

img

Dzięki wynikom łatwo zauważyć, że kolumna Genre został podzielony na kolumny – Genre_Female i Genre_Male. Gdy klientem jest kobieta, Genre_Female jest równe 1, a gdy klientem jest mężczyzna, to równa się 0.

Również Age Groups kolumna została podzielona na 6 kolumn, po jednej na każdy przedział, np. Age Groups_(15, 20], Age Groups_(20, 30], i tak dalej. W taki sam sposób jak Genre, gdy klient ma 18 lat, Age Groups_(15, 20] wartosc jest 1 a wartość wszystkich pozostałych kolumn to 0.

Połączenia korzyść kodowania one-hot to prostota w reprezentowaniu wartości kolumn, łatwo jest zrozumieć, co się dzieje – podczas gdy niekorzyść jest to, że utworzyliśmy teraz 8 dodatkowych kolumn, aby podsumować kolumny, które już mieliśmy.

ostrzeżenie: jeśli masz zestaw danych, w którym liczba kolumn zakodowanych na gorąco przekracza liczbę wierszy, najlepiej jest zastosować inną metodę kodowania, aby uniknąć problemów z wymiarami danych.

Kodowanie „one-hot” dodaje również zera do naszych danych, czyniąc je bardziej rzadkimi, co może stanowić problem dla niektórych algorytmów, które są wrażliwe na rzadkość danych.

W przypadku naszych potrzeb w zakresie klastrowania wydaje się, że działa kodowanie na gorąco. Ale możemy wykreślić dane, aby zobaczyć, czy naprawdę istnieją odrębne grupy, które można zgrupować.

Podstawowe kreślenie i redukcja wymiarów

Nasz zestaw danych składa się z 11 kolumn i istnieje kilka sposobów wizualizacji tych danych. Pierwszym z nich jest wykreślenie go w 10 wymiarach (powodzenia). Dziesięć, ponieważ Customer_ID kolumna nie jest brana pod uwagę. Druga polega na wykreśleniu naszych początkowych cech liczbowych, a trzecia polega na przekształceniu naszych 10 cech w 2 – a zatem na przeprowadzeniu redukcji wymiarowości.

Wykreślanie każdej pary danych

Ponieważ narysowanie 10 wymiarów jest trochę niemożliwe, zdecydujemy się na drugie podejście – narysujemy nasze początkowe cechy. Do naszej analizy skupień możemy wybrać dwa z nich. Jednym ze sposobów, w jaki możemy zobaczyć wszystkie nasze pary danych w połączeniu, jest Seaborn pairplot():

import seaborn as sns


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

sns.pairplot(customer_data)

Który wyświetla:

img

Na pierwszy rzut oka możemy dostrzec wykresy rozrzutu, które wydają się zawierać grupy danych. Jeden, który wydaje się interesujący, to wykres rozrzutu, który łączy Annual Income i Spending Score. Zauważ, że nie ma wyraźnej separacji między innymi zmiennymi wykresami rozrzutu. Co najwyżej możemy powiedzieć, że istnieją dwie różne koncentracje punktów w Spending Score vs Age wykres punktowy.

Oba wykresy rozrzutu składające się z Annual Income i Spending Score są zasadniczo takie same. Widać to dwukrotnie, ponieważ zamieniono osie x i y. Patrząc na którąkolwiek z nich, możemy zobaczyć, co wydaje się być pięcioma różnymi grupami. Wykreślmy tylko te dwie funkcje za pomocą Seaborn scatterplot() przyjrzeć się bliżej:

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

img

Przyglądając się bliżej, zdecydowanie możemy wyróżnić 5 różnych grup danych. Wygląda na to, że naszych klientów można pogrupować na podstawie tego, ile zarabiają w ciągu roku i ile wydają. To kolejny istotny punkt naszej analizy. Ważne jest, że przy grupowaniu naszych klientów bierzemy pod uwagę tylko dwie cechy. Wszelkie inne informacje, które posiadamy na ich temat, nie wchodzą do równania. Nadaje to sens analizie – jeśli wiemy, ile klient zarabia i wydaje, możemy łatwo znaleźć potrzebne nam podobieństwa.

img

To wspaniale! Do tej pory mamy już dwie zmienne do zbudowania naszego modelu. Poza tym, co to reprezentuje, sprawia również, że model jest prostszy, oszczędniejszy i łatwiejszy do wyjaśnienia.

Zapoznaj się z naszym praktycznym, praktycznym przewodnikiem dotyczącym nauki Git, zawierającym najlepsze praktyki, standardy przyjęte w branży i dołączoną ściągawkę. Zatrzymaj polecenia Google Git, a właściwie uczyć się to!

Uwaga: Data Science zazwyczaj preferuje tak proste podejścia, jak to tylko możliwe. Nie tylko dlatego, że jest to łatwiejsze do wyjaśnienia dla biznesu, ale także dlatego, że jest bardziej bezpośrednie – dzięki dwóm funkcjom i dającemu się wyjaśnić modelowi jest jasne, co ten model robi i jak działa.

Wykreślanie danych po użyciu PCA

Wygląda na to, że nasze drugie podejście jest prawdopodobnie najlepsze, ale spójrzmy również na nasze trzecie podejście. Może to być przydatne, gdy nie możemy wykreślić danych, ponieważ mają zbyt wiele wymiarów lub gdy nie ma koncentracji danych lub wyraźnego rozdziału w grupach. W takich sytuacjach zaleca się zmniejszenie wymiarów danych za pomocą metody o nazwie Analiza głównych składników (PCA).

Uwaga: Większość ludzi używa PCA do redukcji wymiarów przed wizualizacją. Istnieją inne metody, które pomagają w wizualizacji danych przed grupowaniem, takie jak: Przestrzenne klastrowanie aplikacji z szumem na podstawie gęstości (DBSCAN) i Mapy samoorganizujące się (SOM) grupowanie. Oba są algorytmami grupowania, ale można je również wykorzystać do wizualizacji danych. Ponieważ analiza skupień nie ma złotego standardu, ważne jest porównywanie różnych wizualizacji i różnych algorytmów.

PCA zmniejszy rozmiary naszych danych, starając się zachować jak najwięcej informacji. Najpierw zorientujmy się, jak działa PCA, a następnie możemy wybrać, do ilu wymiarów danych zredukujemy nasze dane.

Dla każdej pary cech PCA sprawdza, czy większe wartości jednej zmiennej odpowiadają większym wartościom drugiej zmiennej i robi to samo dla wartości mniejszych. Tak więc zasadniczo oblicza, jak bardzo wartości cech różnią się względem siebie – nazywamy to ich kowariancja. Wyniki te są następnie uporządkowane w macierz, uzyskując a macierz kowariancji.

Po uzyskaniu macierzy kowariancji PCA próbuje znaleźć liniową kombinację cech, która najlepiej to wyjaśnia – pasuje do modeli liniowych, dopóki nie zidentyfikuje tego, który wyjaśnia maksymalny ilość wariancji.

Note: PCA to transformacja liniowa, a liniowość jest wrażliwa na skalę danych. Dlatego PCA działa najlepiej, gdy wszystkie wartości danych są na tej samej skali. Można to zrobić, odejmując kolumnę oznaczać od jego wartości i dzieląc wynik przez jego odchylenie standardowe. To nazywa się standaryzacja danych. Przed użyciem PCA upewnij się, że dane są przeskalowane! Jeśli nie wiesz, jak, przeczytaj nasze „Feature Scaling Data with Scikit-Learn do uczenia maszynowego w Pythonie”!

Przy najlepszej znalezionej linii (kombinacji liniowej), PCA otrzymuje kierunki swoich osi, zwane wektory własne, i jego współczynniki liniowe, the wartości własne. Kombinacja wektorów własnych i wartości własnych – lub kierunków osi i współczynników – to Główne składniki PCA. I wtedy możemy wybrać naszą liczbę wymiarów w oparciu o wyjaśnioną wariancję każdej cechy, rozumiejąc, które główne składniki chcemy zachować, a które odrzucić na podstawie tego, ile wyjaśniają wariancji.

Po uzyskaniu głównych składowych PCA używa wektorów własnych do utworzenia wektora cech, które zmieniają orientację danych z oryginalnych osi na te reprezentowane przez główne składowe – w ten sposób zmniejszane są wymiary danych.

Uwaga: Ważnym szczegółem, który należy tutaj wziąć pod uwagę, jest to, że ze względu na swój liniowy charakter PCA skupi większość wyjaśnionej wariancji w pierwszych głównych składnikach. Tak więc, patrząc na wyjaśnioną wariancję, zwykle wystarczą nasze pierwsze dwie składowe. Ale w niektórych przypadkach może to być mylące – dlatego staraj się porównywać różne wykresy i algorytmy podczas grupowania, aby sprawdzić, czy mają podobne wyniki.

Przed zastosowaniem PCA musimy wybrać między Age kolumna lub Age Groups kolumny w naszych wcześniej zakodowanych w jednym czasie danych. Ponieważ obie kolumny reprezentują te same informacje, wprowadzenie ich dwukrotnie wpływa na wariancję danych. Jeśli Age Groups kolumna jest wybrana, po prostu usuń Age kolumna za pomocą Pandy drop() metodę i przypisz ją do customer_data_oh zmienna:

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

Teraz nasze dane mają 10 kolumn, co oznacza, że ​​możemy uzyskać jeden główny składnik po kolumnie i wybrać, ile z nich użyjemy, mierząc, jak bardzo wprowadzenie jednego nowego wymiaru wyjaśnia więcej naszej wariancji danych.

Zróbmy to z Scikit-Learn PCA. Obliczymy wyjaśnioną wariancję każdego wymiaru, podaną przez explained_variance_ratio_ , a następnie spójrz na ich skumulowaną sumę z cumsum() :

from sklearn.decomposition import PCA

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

Nasze skumulowane wyjaśnione wariancje to:

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

Widzimy, że pierwszy wymiar wyjaśnia 50% danych, a w połączeniu z drugim wymiarem wyjaśniają 99% procent. Oznacza to, że pierwsze 2 wymiary wyjaśniają już 99% naszych danych. Możemy więc zastosować PCA z 2 składnikami, uzyskać nasze główne składniki i wykreślić je:

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

Wykres danych po PCA jest bardzo podobny do wykresu, który wykorzystuje tylko dwie kolumny danych bez PCA. Zauważ, że punkty tworzące grupy są bliżej i nieco bardziej skoncentrowane po PCA niż przed.

img

Wizualizacja struktury hierarchicznej za pomocą dendrogramów

Do tej pory zbadaliśmy dane, zakodowane na gorąco kolumny kategorialne, zdecydowaliśmy, które kolumny nadają się do grupowania i zmniejszyliśmy wymiarowość danych. Wykresy wskazują, że w naszych danych mamy 5 skupień, ale jest też inny sposób na wizualizację zależności między naszymi punktami i pomoc w określeniu liczby skupień – poprzez utworzenie dendrogram (często błędnie pisany jako dendogram). dendro znaczy drzewo po łacinie.

Połączenia dendrogram jest wynikiem połączenia punktów w zbiorze danych. Jest to wizualna reprezentacja hierarchicznego procesu grupowania. A jak działa hierarchiczny proces grupowania? Cóż… to zależy – prawdopodobnie odpowiedź, którą już wiele słyszałeś w Data Science.

Zrozumienie klastrowania hierarchicznego

Podczas Hierarchiczny algorytm klastrowania (HCA) zaczyna łączyć punkty i znajdować klastry, może najpierw podzielić punkty na 2 duże grupy, a następnie podzielić każdą z tych dwóch grup na mniejsze 2 grupy, mające łącznie 4 grupy, co jest dzielący i top-down podejście.

Alternatywnie może zrobić coś przeciwnego – może spojrzeć na wszystkie punkty danych, znaleźć 2 punkty, które są bliżej siebie, połączyć je, a następnie znaleźć inne punkty, które są najbliżej tych połączonych punktów i dalej budować 2 grupy od oddolne. Który jest aglomeracyjny podejście, które będziemy rozwijać.

Kroki do wykonania aglomeracyjnego klastrowania hierarchicznego

Aby podejście aglomeracyjne było jeszcze jasne, istnieją kroki Aglomeracyjne klastrowanie hierarchiczne (AHC) algorytm:

  1. Na początku traktuj każdy punkt danych jako jeden klaster. Dlatego liczba klastrów na początku będzie wynosić K – podczas gdy K jest liczbą całkowitą reprezentującą liczbę punktów danych.
  2. Utwórz klaster, łącząc dwa najbliższe punkty danych, w wyniku czego powstają klastry K-1.
  3. Utwórz więcej klastrów, łącząc dwa najbliższe klastry, w wyniku czego powstają klastry K-2.
  4. Powtarzaj powyższe trzy kroki, aż utworzy się jedna duża grupa.

Note: Dla uproszczenia mówimy „dwa najbliższe” punkty danych w krokach 2 i 3. Ale jest więcej sposobów łączenia punktów, jak zobaczymy za chwilę.

Jeśli odwrócisz kroki algorytmu ACH, przechodząc od 4 do 1 – to byłyby kroki do *Podziałowe klastrowanie hierarchiczne (DHC)*.

Zauważ, że HCA mogą być dzielące i odgórne lub aglomeracyjne i oddolne. Podejście odgórne DHC działa najlepiej, gdy masz mniej, ale większych klastrów, dlatego jest bardziej kosztowne obliczeniowo. Z drugiej strony podejście oddolne AHC jest odpowiednie w przypadku wielu mniejszych klastrów. Jest prostszy obliczeniowo, częściej używany i bardziej dostępny.

Uwaga: Odgórna lub oddolna reprezentacja procesu grupowania na dendrogramie zawsze zaczyna się od podziału na dwie części, a kończy na odróżnieniu każdego pojedynczego punktu, gdy jego podstawowa struktura jest w postaci drzewa binarnego.

Narysujmy nasz dendrogram danych klienta, aby zwizualizować hierarchiczne relacje danych. Tym razem użyjemy scipy biblioteka do tworzenia dendrogramu dla naszego zbioru danych:

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()

Wynik działania skryptu wygląda tak:

img

W powyższym skrypcie wygenerowaliśmy klastry i podgrupy z naszymi punktami, zdefiniowaliśmy sposób łączenia naszych punktów (poprzez zastosowanie ward metody) i jak zmierzyć odległość między punktami (za pomocą euclidean metryczny).

Za pomocą wykresu dendrogramu można zwizualizować opisane procesy DHC i AHC. Aby zwizualizować podejście odgórne, zacznij od góry dendrogramu i zejdź w dół, a następnie zrób odwrotnie, zaczynając w dół i poruszając się w górę, aby zwizualizować podejście oddolne.

Metody łączenia

Istnieje wiele innych metod powiązania, dzięki lepszemu zrozumieniu ich działania, będziesz mógł wybrać odpowiednią dla swoich potrzeb. Poza tym każdy z nich przyniesie inne rezultaty po zastosowaniu. Nie ma ustalonej zasady w analizie skupień, jeśli to możliwe, zbadaj naturę problemu, aby zobaczyć, która pasuje najlepiej, przetestuj różne metody i sprawdź wyniki.

Niektóre z metod łączenia to:

  • Pojedynczy łącznik: określany również jako Najbliższy sąsiad (NN). Odległość między klastrami określa odległość między ich najbliższymi członkami.

img

  • Kompletne połączenie: określany również jako Najdalszy sąsiad (FN), Algorytm najdalszego punktulub Algorytm Voor Hees. Odległość między skupiskami jest określona przez odległość między ich najdalszymi członkami. Ta metoda jest kosztowna obliczeniowo.

img

  • Średnie połączenie: znany również jako UPGMA (Metoda grup nieważonych par ze średnią arytmetyczną). Procent liczby punktów każdego klastra jest obliczany w odniesieniu do liczby punktów dwóch klastrów, jeśli zostały połączone.

img

  • Powiązanie ważone: znany również jako WPGMA (Metoda grup ważonych par ze średnią arytmetyczną). Poszczególne punkty obu skupień przyczyniają się do zagregowanej odległości między mniejszym i większym skupieniem.
  • Połączenie centroid: określany również jako UPGMC (Metoda grup nieważonych par przy użyciu centroidów). Punkt zdefiniowany przez średnią wszystkich punktów (centroid) jest obliczany dla każdego skupienia, a odległość między skupieniami jest odległością pomiędzy ich odpowiednimi centroidami.

img

  • Połączenie totemu: Znany również jako MISSQ (Minimalny wzrost sumy kwadratów). Określa odległość między dwoma klastrami, oblicza sumę błędu kwadratów (ESS) i sukcesywnie wybiera kolejne klastry na podstawie mniejszego ESS. Metoda Warda stara się zminimalizować wzrost ESS na każdym etapie. Dlatego minimalizując błąd.

img

Metryki odległości

Oprócz powiązania możemy również określić niektóre z najczęściej używanych mierników odległości:

  • Euklidesa: określany również jako pitagorejski lub prostoliniowy dystans. Oblicza odległość między dwoma punktami w przestrzeni, mierząc długość odcinka linii, który przechodzi między nimi. Wykorzystuje twierdzenie Pitagorasa, a wynikiem jest wartość odległości (C) równania:

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

  • Manhattan: nazywany również Blok miejski, taksówka dystans. Jest to suma bezwzględnych różnic między miarami we wszystkich wymiarach dwóch punktów. Jeśli te wymiary to dwa, jest to analogiczne do robienia w prawo, a następnie w lewo podczas chodzenia po jednym klocku.

img

  • Minkowskiego: jest to uogólnienie odległości euklidesowych i manhattańskich. Jest to sposób obliczania odległości na podstawie bezwzględnych różnic do rzędu metryki Minkowskiego p. Chociaż jest zdefiniowany dla każdego p> 0, jest rzadko używany dla wartości innych niż 1, 2 i ∞ (nieskończony). Odległość Minkowskiego jest taka sama jak odległość Manhattanu, gdy p = 1, i tak samo jak odległość euklidesowa, gdy p = 2.

$$
Dleft(X,Yright) = lewo(sum_{i=1}^n |x_i-y_i|^prawo)^{frac{1}{p}}
$$

img

  • Czebyszewa: znany również jako Szachownica dystans. To skrajny przypadek odległości Minkowskiego. Kiedy używamy nieskończoności jako wartości parametru p (p = ), otrzymujemy metrykę, która definiuje odległość jako maksymalną bezwzględną różnicę między współrzędnymi.
  • cosinus: jest to odległość kątowa cosinus między dwoma sekwencjami punktów lub wektorów. Podobieństwo cosinusowe to iloczyn skalarny wektorów podzielony przez iloczyn ich długości.
  • Żakard: mierzy podobieństwo między skończonymi zbiorami punktów. Definiuje się ją jako całkowitą liczbę punktów (liczność) we wspólnych punktach w każdym zbiorze (przecięcie), podzieloną przez całkowitą liczbę punktów (liczność) sumy punktów obu zbiorów (łączność).
  • Jensena-Shannona: na podstawie rozbieżności Kullbacka-Leiblera. Uwzględnia rozkłady prawdopodobieństwa punktów i mierzy podobieństwo między tymi rozkładami. Jest to popularna metoda teorii prawdopodobieństwa i statystyki.

Wybraliśmy Wychowanek i Euklidesa dla dendrogramu, ponieważ są one najczęściej stosowaną metodą i metryką. Zwykle dają dobre wyniki, ponieważ Ward łączy punkty w oparciu o minimalizację błędów, a Euclidean działa dobrze w niższych wymiarach.

W tym przykładzie pracujemy z dwiema funkcjami (kolumnami) danych marketingowych i 200 obserwacjami lub wierszami. Ponieważ liczba obserwacji jest większa niż liczba cech (200 > 2), pracujemy w przestrzeni niskowymiarowej.

Kiedy liczba funkcji (fa) jest większa niż liczba obserwacji (N) – głównie pisane jako f >> N, to znaczy, że mamy plik wysoka przestrzeń wymiarowa.

Gdybyśmy mieli uwzględnić więcej atrybutów, a więc mielibyśmy ponad 200 obiektów, odległość euklidesowa mogłaby nie działać zbyt dobrze, ponieważ miałaby trudności z pomiarem wszystkich małych odległości w bardzo dużej przestrzeni, która tylko się powiększa. Innymi słowy, podejście odległości euklidesowej ma trudności w pracy z danymi rzadkość. To jest problem, który nazywa się przekleństwo wymiarowości. Wartości odległości stałyby się tak małe, jakby były „rozcieńczone” w większej przestrzeni, zniekształcone do wartości 0.

Uwaga: Jeśli kiedykolwiek napotkasz zbiór danych z f >> p, prawdopodobnie użyjesz innych wskaźników odległości, takich jak Mahalanobisa dystans. Alternatywnie możesz również zmniejszyć wymiary zbioru danych, używając Analiza głównych składników (PCA). Problem ten jest częsty, zwłaszcza w przypadku grupowania danych z sekwencjonowania biologicznego.

Omówiliśmy już wskaźniki, powiązania i sposób, w jaki każdy z nich może wpłynąć na nasze wyniki. Kontynuujmy teraz analizę dendrogramu i zobaczmy, w jaki sposób może ona wskazać nam liczbę klastrów w naszym zbiorze danych.

Znalezienie interesującej liczby skupisk w dendrogramie jest tym samym, co znalezienie największej przestrzeni poziomej, która nie ma żadnych linii pionowych (przestrzeni z najdłuższymi liniami pionowymi). Oznacza to, że istnieje większa separacja między klastrami.

Możemy narysować poziomą linię, która przechodzi przez najdłuższą odległość:

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

Po zlokalizowaniu linii poziomej liczymy, ile razy nasze linie pionowe zostały przez nią przekroczone – w tym przykładzie 5 razy. Tak więc 5 wydaje się dobrym wskaźnikiem liczby klastrów, które mają między sobą największą odległość.

Note: Dendrogram należy traktować wyłącznie jako odniesienie przy wyborze liczby skupień. Może łatwo zejść z tej liczby i jest całkowicie uzależniony od rodzaju powiązania i metryk odległości. Przeprowadzając dogłębną analizę skupień, zaleca się przyjrzenie się dendrogramom z różnymi powiązaniami i metrykami oraz przyjrzenie się wynikom wygenerowanym za pomocą pierwszych trzech linii, w których klastry mają między sobą największą odległość.

Wdrażanie aglomeracyjnego klastrowania hierarchicznego

Korzystanie z oryginalnych danych

Do tej pory obliczyliśmy sugerowaną liczbę klastrów dla naszego zbioru danych, które potwierdzają naszą wstępną analizę i naszą analizę PCA. Teraz możemy stworzyć nasz aglomeracyjny hierarchiczny model klastrowania za pomocą Scikit-Learn AgglomerativeClustering i poznaj etykiety punktów marketingowych 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_

To skutkuje:

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])

Wiele zbadaliśmy, aby dojść do tego punktu. A co oznaczają te etykiety? Tutaj mamy każdy punkt naszych danych oznaczony jako grupa 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 są nasze ostatnie dane klastrowe. Możesz zobaczyć oznaczone kolorami punkty danych w postaci pięciu klastrów.

Punkty danych w prawym dolnym rogu (etykieta: 0, fioletowe punkty danych) należą do klientów o wysokich zarobkach, ale niskich wydatkach. To klienci, którzy ostrożnie wydają pieniądze.

Podobnie klienci w prawym górnym rogu (etykieta: 2, zielone punkty danych), to klienci o wysokich zarobkach i wysokich wydatkach. Są to rodzaje klientów, do których kierują firmy.

Klienci w środku (etykieta: 1, niebieskie punkty danych) to te, które mają średnie dochody i średnie wydatki. Do tej kategorii należy najwięcej klientów. Firmy mogą również kierować reklamy do tych klientów, biorąc pod uwagę fakt, że jest ich bardzo wielu.

Klienci w lewym dolnym rogu (etykieta: 4, czerwony) to klienci, którzy mają niskie zarobki i niskie wydatki, mogą zostać przyciągnięci przez oferowanie promocji.

I wreszcie klienci w lewym górnym rogu (etykieta: 3, pomarańczowe punkty danych) to te o wysokich dochodach i niskich wydatkach, które są idealnym celem marketingowym.

Korzystanie z wyniku z PCA

Gdybyśmy byli w innym scenariuszu, w którym musielibyśmy zmniejszyć wymiarowość danych. Moglibyśmy również łatwo wykreślić klastrowane wyniki PCA. Można to zrobić, tworząc kolejny model grupowania aglomeracyjnego i uzyskując etykietę danych dla każdego głównego komponentu:

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

Zauważ, że oba wyniki są bardzo podobne. Główna różnica polega na tym, że pierwszy wynik z oryginalnymi danymi jest znacznie łatwiejszy do wyjaśnienia. Widać wyraźnie, że klientów można podzielić na pięć grup według ich rocznych dochodów i wydatków. Chociaż w podejściu PCA bierzemy pod uwagę wszystkie nasze funkcje, o ile możemy spojrzeć na wariancję wyjaśnianą przez każdą z nich, jest to trudniejsze do zrozumienia pojęcie, szczególnie podczas raportowania do działu marketingu.

Im najmniej musimy przekształcić nasze dane, tym lepiej.

Jeśli masz bardzo duży i złożony zbiór danych, w którym przed grupowaniem musisz wykonać redukcję wymiarowości – spróbuj przeanalizować liniowe relacje między każdą z funkcji i ich pozostałościami, aby wykonać kopię zapasową użycia PCA i zwiększyć wyjaśnialność procesu. Tworząc model liniowy na parę elementów, będziesz w stanie zrozumieć, w jaki sposób te elementy oddziałują.

Jeśli ilość danych jest tak duża, niemożliwe staje się wykreślenie par cech, wybierz próbkę danych, tak zrównoważoną i bliską normalnemu rozkładowi, jak to możliwe, i najpierw przeprowadź analizę na próbce, zrozum to, dostosuj go – i zastosuj później do całego zbioru danych.

Zawsze możesz wybrać różne techniki wizualizacji grupowania w zależności od charakteru danych (liniowe, nieliniowe) i w razie potrzeby połączyć lub przetestować je wszystkie.

Wnioski

Technika grupowania może być bardzo przydatna w przypadku danych nieoznakowanych. Ponieważ większość danych w świecie rzeczywistym jest nieoznakowana, a dodawanie adnotacji do danych wiąże się z wyższymi kosztami, do oznaczania danych nieoznakowanych można użyć technik grupowania.

W tym przewodniku przedstawiliśmy prawdziwy problem związany z nauką o danych, ponieważ techniki grupowania są w dużej mierze wykorzystywane w analizie marketingowej (a także w analizie biologicznej). Wyjaśniliśmy również wiele kroków dochodzenia, aby uzyskać dobry hierarchiczny model grupowania i jak czytać dendrogramy oraz zakwestionowaliśmy, czy PCA jest koniecznym krokiem. Naszym głównym celem jest uwzględnienie niektórych pułapek i różnych scenariuszy, w których możemy znaleźć hierarchiczne grupowanie.

Miłego klastrowania!

Znak czasu:

Więcej z Nadużycie stosu