Granularne grupowanie danych w jedną grupę
Analiza tematu granularnego grupowania danych w jedną grupę
Celem projektu jest stworzenie narzędzia umożliwiającego eksplorację i ocenę algorytmów grupowania danych, szczególnie w kontekście wykrywania jednej spójnej grupy przy jednoczesnym odseparowaniu szumu. Platforma wspiera analizę metod klastrowania w zastosowaniach, gdzie priorytetem jest precyzyjne rozróżnienie istotnej struktury od przypadkowych danych, zgodnie z ideą uzasadnionej granulacji.
Kluczowe informacje
W badaniu porównano algorytmy DBSCAN oraz hierarchiczne (Single i Complete Linkage), skupiając się na ich zdolności do wyodrębnienia jednej grupy danych i identyfikacji szumu. Dla DBSCAN dobierano parametry umożliwiające jednoczesne wykrycie grupy i szumu, natomiast dla metod hierarchicznych analizowano moment przerwania oraz relacje między rozmiarami klastrów w celu identyfikacji szumu. Wszystkie eksperymenty uruchamiano automatycznie dla różnych zestawów parametrów, a ich wyniki zapisywano w formie plików CSV i PNG, wraz z pomiarem czasu działania algorytmów.
📁 Struktura projektu
/granular_clustering/
├── main.py
├── dbscan_module.py
├── hierarchical.py
├── knn_utils.py
├── results.csv
/data_analysis/
├── clustering/
│ ├── dbscan_optimizer.py
│ ├── hierarchical.py
│ └── metrics_calculator.py
├── datasets/
│ ├── generators/
│ │ ├── circles.py
│ │ └── custom_shapes.py
│ └── noise_injector.py
└── visualization/
├── plotter.py
└── results_exporter.py
Algorytmy klasteryzacji
Automatyczny dobór parametrów ε i MinPts
Wykrywanie kształtów nieregularnych
Praca na dendrogramach
Metryki oceny
15 kryteriów granulacji
Walidacja na 7 typach zbiorów
Analiza odporności na szum
Stos technologiczny
Konfiguracja i uruchomienie
- Środowisko: Python >=3.8, wymagane biblioteki w
requirements.txt. - Uruchomienie eksperymentów:
python main.py - Wyniki zapisywane w plikach CSV.
Generator określa kształt danych, które będą używane do testowania algorytmów. Przykład generatora:
generators = {
"circle_A" : (pg.generate_points_circle, None),
"circle_B" : (pg.generate_points_mises, None),
"circle_C" : (pg.generate_points_normal, None),
"ring" : (pg.generate_points_ring, None),
# "shape_A" : (pg.generate_points_in_shape, "drawn_figure_A.txt"),
# "shape_B" : (pg.generate_points_in_shape, "drawn_figure_B.txt"),
# "shape_C" : (pg.generate_points_in_shape, "drawn_figure_C.txt"),}
Opis algorytmów
Poniżej przedstawiono zwięzłe opisy trzech głównych podejść do grupowania danych zastosowanych w badaniu: aglomeracyjne, gęstościowe (DBSCAN) oraz oparte na najbliższych sąsiadach (KNN).
Klasyczne klastrowanie aglomeracyjne zaczyna od traktowania każdego punktu jako osobnego klastra i iteracyjne łączy najbliższe pary klastrów, aż do osiągnięcia żądanej liczby klastrów. W badaniu zastosowano dwa warianty: Single Linkage (minimalny dystans między klastrami) i Complete Linkage (maksymalny dystans między klastrami).
function AGGLOMERATIVE(data, target_k):
initialize clusters ← {x} for x in data
compute D[i,j] ← distance between clusters i and j
while |clusters| > target_k:
(i, j) ← argmin_{p,q} linkage_distance(clusters[p], clusters[q])
merge clusters[i] and clusters[j]
update distances D for new cluster
return clusters
DBSCAN identyfikuje obszary o wysokiej gęstości punktów. Dwa kluczowe parametry to ε – promień sąsiedztwa oraz MinPts – minimalna liczba punktów w otoczeniu. Algorytm oznacza punkty rdzeniowe, brzegowe i szum, tworząc klastry bez potrzeby określania ich liczby z góry.
function DBSCAN(D, eps, MinPts):
C ← 0
for each point p in D:
if p not visited:
mark p visited
N ← regionQuery(p, eps)
if |N| < MinPts:
label p as noise
else:
C ← C + 1
expandCluster(p, N, C, eps, MinPts)
return cluster labels
function expandCluster(p, N, C, eps, MinPts):
add p to cluster C
for each point q in N:
if q not visited:
mark q visited
N' ← regionQuery(q, eps)
if |N'| ≥ MinPts:
N ← N ∪ N'
if q not yet member of any cluster:
add q to cluster C
function regionQuery(p, eps):
return {q in D | distance(p, q) ≤ eps}
Algorytm k najbliższych sąsiadów (KNN) w kontekście tego badania służył do oceny średnich odległości między punktami w klastrze. Wyznaczone wartości dₖ stanowią jedną z miar jakości klasteryzacji.
function KNN_distance(data, k):
distances_list ← []
for each point x in data:
D_x ← sort([distance(x, y) for y ≠ x])
d_x ← average(D_x[1..k])
distances_list.append(d_x)
return mean(distances_list)
Parametryzacja algorytmów
W celu doboru optymalnych parametrów każdego z algorytmów zastosowano podejście iteracyjne wraz z miarami jakości klasteryzacji (P1–P3,k). Poniżej przedstawiono szczegóły parametrów i procedury wyboru.
Dla klastrowania aglomeracyjnego decydującym parametrem była liczba klastrów (target_k = 2). Na podstawie dendrogramu określono próg cięcia tak, aby utworzyć dwa klastry, a następnie oceniono jakość za pomocą miar P1–P3,k, traktując mniejszy klaster jako szum.
Do dobrania ε oraz MinPts zaimplementowano funkcję dbscanLoop, która przeszukuje ε z zakresu [2, 20] co 0.2 oraz MinPts z zakresu [20, 150] co 1. Dla każdej pary parametrów obliczane są miary jakości klasteryzacji, a najlepszy zestaw wybierany jest na podstawie maksymalnej wartości kryteriów P1–P3,k.
W ramach analizy granularnego grupowania opracowano zestaw 15 miar oceny jakości skupienia, które łączą ze sobą informacje o liczbie punktów w największym klastrze oraz miary odległości między tymi punktami. Podstawowe trzy miary (P1, P2, P3) opierają się na średniej odległości między wszystkimi punktami w klastrze (d̄):
- P1 = liczba punktów × (1 / d̄)
- P2 = liczba punktów × (1 / d̄)2
- P3 = √(liczba punktów) × (1 / d̄)2
Kolejne 12 miar to rozszerzenia powyższych z wykorzystaniem odległości do k najbliższych sąsiadów (dk) dla k = 3, 5, 7, 9. Dla każdego k obliczane są trzy warianty:
- P1k = liczba punktów × (1 / dk)
- P2k = liczba punktów × (1 / dk)2
- P3k = √(liczba punktów) × (1 / dk)2
Miary te różnią się poziomem agresywności względem wartości odległości — metryki z kwadratem (P2, P3) są bardziej czułe na zmiany rozproszenia, co pozwala lepiej wykrywać spójność dużych i zwartych skupień. Dzięki ujęciu w formie odwrotności, wartości miar rosną w kierunku bardziej jednorodnych klastrów.
Wyniki badań
Zbiory danych
W badaniach wykorzystano 7 różnych zbiorów danych, które różnią się kształtem i rozkładem punktów. Zbiory te obejmują zarówno klasyczne kształty (np. okręgi, pierścienie), jak i bardziej złożone struktury (np. rozkład von Misesa, kształty niestandardowe). Każdy zbiór danych został poddany analizie w celu oceny skuteczności algorytmów klasteryzacji w wykrywaniu jednego klastra oraz identyfikacji szumu.
# TO DO: Obrazki kształtów zbiorów danych
Wpływ kryteriów P₁–P₁₅
Wartości w progress barach i listach podane są w η [%] i oznaczają dokładność klasteryzacji.
📏 Complete Linkage
Dla wszystkich kryteriów P₁…P₁₅ algorytm wybierał identyczne d (próg przerwania), co w praktyce dało stałą dokładność:
- Pierścień: 56 η [%]
- Półksiężyc: 48 η [%]
- Litera “X”: 58.5 η [%]
- Grzyb: 53–57.7 η [%]
🔗 Single Linkage
Dokładność zależy od kryterium Pᵢ (i=1…15), ale dla każdego zbioru utrzymuje się w granicach:
- Pierścień: 81 η [%] → 89.2 η [%]
- Półksiężyc: 50 η [%] → 60.8 η [%]
- Litera “X”: 53 η [%] → 84.5 η [%]
- Grzyb: 68 η [%] → 87.9 η [%]
🌀 DBSCAN
DBSCAN wykazuje umiarkowaną zmienność wg kryteriów Pᵢ oraz generalnie najwyższe dokładności:
- Pierścień: 88 η [%] → 92 η [%]
- Półksiężyc: 65.6 η [%] (P₂,k₅ najlepsze)
- Litera “X”: 81.5 η [%] (P₅,P₆,P₈,P₉)
- Grzyb: 88.8 η [%] (P₄–P₉)
Analiza wyników dla różnych kształtów i algorytmów pokazuje, że wybór kryterium P ma istotny wpływ przede wszystkim na algorytmy Single Linkage i DBSCAN, natomiast Complete Linkage jest na ogół niewrażliwy na zmianę kryterium (zawsze generując tę samą wartość progu d i takie same wyniki).
Wrażliwość na szum
🍄 Single Linkage – grzyb
Algorytm radzi sobie doskonale przy szumie do 60 % – dokładność > 90 %. Przy 70 % szumu dokładność spada drastycznie do ~34 %.
🍄 DBSCAN – grzyb
DBSCAN jest nieco bardziej odporny na szum – 90 % przy 40 %, 88 % przy 50 %, 86 % przy 60 %. Przy 70 % dokładność spada do ~32 %.
⭕ Single Linkage – koło
Bardzo wysoka skuteczność do 60 % szumu – ok. 88–89 %. Pomiędzy 60 % a 70 % następuje silny spadek z ~84 % do ~~32 %.
Zarówno Single Linkage, jak i DBSCAN są odporne na dodatek szumu do poziomu około 60 %, przy czym DBSCAN w większości przypadków osiąga wyższą dokładność. Przy przekroczeniu 60 % szumu dochodzi do istotnego pogorszenia jakości grupowania, a przy 70 % oba algorytmy nie radzą sobie z wykryciem prawidłowych klastrów.
Single Linkage: we wszystkich analizowanych zbiorach (koło jednorodne, von Mises, normalne, pierścień, półksiężyc, „X”, grzyb) algorytm utrzymuje wysoką dokładność (>80 %) przy poziomach szumu do 60 %. Najbardziej stabilne wyniki (powyżej 88 %) uzyskano dla koła i pierścienia, natomiast najtrudniejszym przypadkiem był półksiężyc – dokładność spadała do 54 % przy 60 % szumu. W każdym zestawie gwałtowny spadek poniżej 35 % obserwujemy przy 70 % szumu, co pokazuje granicę tolerancji Single Linkage.
DBSCAN: również radzi sobie dobrze do 60 % szumu, często osiągając bardzo wysoką dokładność (np. 90 % dla koła, 92 % dla pierścienia, 90 % dla grzyba). Interesującym wyjątkiem jest rozkład von Mises, gdzie dokładność wzrasta z 50 % przy 40 % szumu do 80 % przy 70 % szumu, co wynika z premiowania gęstych, zwartch klastrów. Podobnie jak Single Linkage, DBSCAN traci skuteczność przy 70 % szumu (dokładność spada do ok. 30–37 % w większości przypadków).
Complete Linkage: nie wykazuje istotnej wrażliwości na szum (zawsze wybiera ten sam próg przerwania i uzyskuje jednolite, niskie wyniki), dlatego jego prezentacja została pominięta.
Czas wykonywania obliczeń
⭕ Koła (Tabela 4.1)
DBSCAN: od ~377 s (koło von Mises, średnica 30) do ~172 s (koło jednorodne, średnica 70)
Single Linkage: stabilnie ~45–58 s, rośnie nieco z rozmiarem zbioru
Complete Linkage: najkrócej ~40–48 s, do 16 % szybciej od Single Linkage
🔵 Rozkład kołowy Gaussa vs Pierścień (Tabela 4.2)
DBSCAN: ~265 s → ~178 s (malejący z rozmiarem, niezależnie od kształtu)
Single Linkage: ~44–52 s, minimalna różnica między kołem a pierścieniem
Complete Linkage: ~40–48 s, także stabilny niezależnie od kształtu
🌀 Nieregularne (Tabela 4.3)
DBSCAN: ~150–200 s, najwolniejszy we wszystkich przypadkach
Single Linkage: ~42–60 s, wzrost przy kształcie “grzyb”
Complete Linkage: ~39–44 s, najszybszy, choć czasem problemy z grupowaniem
- DBSCAN jest 4-6 razy wolniejszy od metod hierarchicznych we wszystkich testowanych konfiguracjach
- Hierarchiczne metody aglomeracyjne wykazują stabilny czas wykonania niezależnie od kształtu danych
- Complete Linkage konsekwentnie przewyższa Single Linkage o 3-16% w szybkości
- Wzrost średnicy koła zmniejsza czas wykonania DBSCAN nawet o 30%
Wnioski
Głównym celem było wyodrębnienie jednego dużego klastra, który będzie zarówno wewnętrznie spójny, jak i wyraźnie odseparowany od pozostałego szumu w danych. Wdrożone kryteria oparte na uzasadnionej granulacji zapewniają, że klaster musi mieć dużą liczbę punktów oraz niską średnią odległość między nimi, co minimalizuje wpływ szumu i podkreśla rzeczywiste skupienia.
W badaniach porównano algorytmy DBSCAN, Single Linkage i Complete Linkage. Określono własne metryki oceny, pozwalające ustalić optymalne parametry dla każdego podejścia, zwłaszcza ε i MinPts w DBSCAN oraz moment przerwania scalania w hierarchicznych algorytmach.
Analiza wpływu szumu wykazała, że zwiększający się udział zakłóceń systematycznie obniża dokładność grupowania, ze znaczącym spadkiem przy 70% szumu. Szczególnym wyzwaniem okazało się wykrywanie klastrów w rozkładzie von Misesa (kształt kołowy), gdzie Single Linkage przewyższył DBSCAN.