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

DBSCAN Single Linkage Complete Linkage

Automatyczny dobór parametrów ε i MinPts

Wykrywanie kształtów nieregularnych

Praca na dendrogramach

📊

Metryki oceny

P1–P3 KNN: 3, 5, 7, 9 Średnia odległość Dokładność

15 kryteriów granulacji

Walidacja na 7 typach zbiorów

Analiza odporności na szum

Stos technologiczny

Python 3.10+
NumPy
scikit-learn
Matplotlib
Pandas
Jupyter

Konfiguracja i uruchomienie

  • Środowisko: Python >=3.8, wymagane biblioteki w requirements.txt.
  • Uruchomienie eksperymentów: python main.py
  • Wyniki zapisywane w plikach CSV.
Przykład konfiguracji
W pliku main.py można ustawić parametry eksperymentu, takie jak liczba iteracji, poziom szumu i inne.
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).

Aglomeracyjne

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
            
Gęstościowe (DBSCAN)

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}
            
KNN

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.

Aglomeracyjne

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.

Gęstościowe (DBSCAN)

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.

Miary jakości skupienia

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

  • 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.

Przykładowe kształty zbiorów

# 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 η [%]
zmienność 0 η [%]

🔗 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 η [%]
zakres ~20–31 pp (η [%])

🌀 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₉)
zakres ~26 pp (η [%])

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

Podsumowanie wpływu kryteriów P na wyniki
# TO DO: Obrazki wykresów z wynikami dla różnych kryteriów P

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 %.

40 % szumu – 92 %
50 % szumu – 90 %
60 % szumu – 91 %
70 % szumu – 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 %.

40 % szumu – 90 %
50 % szumu – 88 %
60 % szumu – 86 %
70 % szumu – 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 %.

40 % szumu – 89 %
50 % szumu – 88 %
60 % szumu – 84 %
70 % szumu – 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.

Podsumowanie wpływu szumu na klasteryzację

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

DBSCAN (średnio ~280 s)
Single Linkage (średnio ~48 s)
Complete Linkage (średnio ~44 s)

🔵 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

DBSCAN (średnio ~225 s)
Single Linkage (średnio ~47 s)
Complete Linkage (średnio ~42 s)

🌀 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 (średnio ~170 s)
Single Linkage (średnio ~48 s)
Complete Linkage (średnio ~41 s)

  • 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%

Podsumowanie wyników czasowych algorytmów

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.

Testowane kształty
7
różne formy skupisk
Metryki jakości
15
własne miary oceny
Algorytmy
3
DBSCAN, Single i Complete Linkage
Konfiguracje
300+
łacznie konfiguracji

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.

DBSCAN osiągnął wysoką dokładność w 6/7 przypadków

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.