svd_mpsic/kmedoids.ipynb

185 KiB
Raw Blame History

import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA
from IPython.display import Image

Analiza skupień metodą k-medoids

Co to jest klasteryzacja?

Analiza skupień lub klasteryzacja to zadanie polegające na grupowaniu zbioru obiektów w taki sposób, aby obiekty w tej samej grupie lub klastrze były do siebie bardziej podobne niż obiekty w innych grupach lub klastrach.

Idea algorytmu klastrowania:

Image("algorithm.png")

Sama analiza skupień nie jest jednym konkretnym algorytmem, lecz ogólnym zadaniem do rozwiązania. Można je zrealizować za pomocą różnych algorytmów (algorytm $k-średnich$, algorytm $k-medoid$), które różnią się znacznie w rozumieniu tego, czym jest klaster i jak skutecznie je znaleźć. Popularne pojęcia klastrów obejmują grupy o małych odległościach między elementami klastra. Klastrowanie można zatem sformułować jako wieloprzedmiotowy problem optymalizacyjny. Wybór odpowiedniego algorytmu grupowania i ustawień parametrów zależy od indywidualnego zbioru danych i przeznaczenia wyników. Analiza skupień jako taka nie jest zadaniem automatycznym, lecz iteracyjnym procesem odkrywania wiedzy lub interaktywnej optymalizacji wieloprzedmiotowej, który wymaga prób i błędów. Często konieczne jest modyfikowanie wstępnego przetwarzania danych i parametrów modelu, aż do uzyskania pożądanych właściwości.

W naszym projekcie przedstawimy metodę $k-medoid$ i porównamy ją z metodą $k-średnich$.

Algorytm k-średnich

W uczeniu maszynowym występują głównie dwa rodzaje algorytmów uczenia. Są to algorytm uczenia nadzorowanego i algorytm uczenia nienadzorowanego. Klastrowanie metodą $k-średnich$ jest algorytmem uczenia nienadzorowanego, który grupuje nieoznakowane zbiory danych w różne klastry lub grupy. W algorytmie $k-średnich$ $k$ określa liczbę wstępnie zdefiniowanych klastrów lub grup, które należy utworzyć w danym zbiorze danych. Na przykład jeśli $k = 3$, powstaną trzy klastry, dla $k = 5$ będzie pięć klastrów itd.

Algorytm $k-średnich$ pomaga grupować dane w różne klastry w sposób konwencjonalny, umożliwiając samodzielne odkrywanie kategorii grup w nieoznakowanym zbiorze danych bez konieczności uczenia. Algorytm klasteryzacji $k-średnich$ jest algorytmem opartym na centroidach, w którym każdy klaster jest powiązany z centroidem. Głównym celem tego algorytmu jest zminimalizowanie sumy odległości wewnętrznych punktów danych w odpowiadających im klastrach. Algorytm przyjmuje jako dane wejściowe nieuporządkowany zbiór danych i dzieli go na $k$ grup, a następnie powtarza ten proces aż do uzyskania najlepszych klastrów. Wartość $k$ jest zawsze określona z góry.

Główne zadanie algorytmu $k-średnich$ jest następujące:

$1.$ Wybierz liczbę klastrów $k$.
$2.$ Wybierz losowo $k$ punktów z zestawu danych jako centroidy.
$3.$ Przypisz każdy punkt danych do najbliższego mu centroida.
$4.$ Oblicz wariancję i umieść nowy centroid dla każdego klastra.
$5.$ Powtórz $krok 3$, czyli ponownie przypisz każdy punkt danych do nowego najbliższego centroidu.

Rozwiązanie: Implementacja algorytmu $k-średnich$ przy użyciu Pythona. Do wykonania algorytmu $k-średnich$ potrzebne jest wstępne przetwarzanie danych. W naszym rozwiązaniu przeprowadziliśmy wstępne przetwarzanie danych w celu zaimplementowania algorytmu. Dodatkowo oceniliśmy jaka jest jakość naszego grupowania. Posłużyliśmy się tzw. sylwetką (ang. silhouette) $s(x_i)$ obliczaną dla każdego obiektu $x_i$. Najpierw dla $x_i$ znajduje się jego średnią odległość $a(x_i)$ od pozostałych obiektów grupy, do której został przydzielony, a następnie wybiera się minimalną wartość $b(x_i)$ spośród obliczonych odległości od $x_i$ do każdej spośród pozostałych grup osobno. Odległość $x_i$ od danej grupy oblicza się jako średnią odległość od $x_i$ do wszystkich elementów tej grupy. Obie wielkości zestawia się we wzorze:

$s(x_i) = \frac{b(x_i)-a(x_i)}{max(a(x_i),b(x_i))}$

otrzymując wartość sylwetki dla danego obiektu $x_i$. Jej zbiór wartości to $[-1, 1]$. Zatem ma ona prostą interpretację: obiekty, dla których wskaźnik jest bliski $1$, zostały trafnie zgrupowane, pozostałe (o wartości ok. $0$ i $ujemnej$) prawdopodobnie trafiły do złych grup.

class TrainModel_means:
    def __init__(self, data, k_value, max_iteration):
        self.data = data
        scaler = MinMaxScaler()
        self.data = scaler.fit_transform(self.data)
        self.k_value = k_value
        self.max_iteration = max_iteration
        self.centroids = []
        self.final_clusters, self.silhouette = self.data_cluster()

    def generate_column(self, col, data):
        values = []
        for i in range(len(data)):
            values.append(data[i][col])
        return values

    def calculateDistance(self, x, y):
        return np.linalg.norm(x-y)

    def get_closest_centroid(self, points, centroids):
        closest_centroids = []
        for i in points:
            distance = []
            for c in centroids:
                dis = self.calculateDistance(i, c)
                distance.append(dis)
            closest_centroids.append(np.argmin(distance))
        return closest_centroids

    def calculate_new_centroids(self, clusters, X):
        new_centroids = []
        new_df = pd.concat([pd.DataFrame(X), pd.DataFrame(clusters, columns=['cluster'])], axis=1)
        for c in set(new_df['cluster']):
            current_cluster = new_df[new_df['cluster'] == c][new_df.columns[:-1]]
            cluster_mean = current_cluster.mean(axis=0)
            new_centroids.append(cluster_mean)
        return new_centroids

    def get_clustered_data(self, points, centroids):
        closest_centroids = self.get_closest_centroid(points, centroids)
        clustered_data = {}
        for i in range(self.k_value):
            clustered_data[i] = []
        for i in range(len(points)):
            clustered_data[closest_centroids[i]].append(points[i])
        return clustered_data

    def get_clusters_label(self, data_points, clusters):
        labels = []
        for i in range(len(data_points)):
            labels.append(0)
        for i in clusters.keys():
            cluster = clusters[i]
            for j in range(len(cluster)):
                for k in range(len(data_points)):
                    if (cluster[j] == data_points[k]).all():
                        labels[k] = i
                        break
        return labels

    def data_cluster(self):
        centroid_points = random.sample(range(0, len(self.data)), self.k_value)
        for i in centroid_points:
            self.centroids.append(self.data[i])
        for i in range(self.max_iteration):
            closest_centroids = self.get_closest_centroid(self.data, self.centroids)
            self.centroids = self.calculate_new_centroids(closest_centroids, np.array(self.data))
        final_clusters = self.get_clustered_data(self.data, self.centroids)
        cluster_labels = self.get_clusters_label(self.data, final_clusters)
        silhouette_avg = silhouette_score(self.data, cluster_labels)
        print("Sylwetka (ang.silhouette) dla metody k-medoid i dla k =", self.k_value, round(silhouette_avg,2))
        
        return final_clusters, round(silhouette_avg,2)
        
    def return_values(self):
        return self.centroids, self.final_clusters, self.silhouette
# iris
dataset = pd.read_csv('iris.csv')
dataset = dataset.iloc[: , 1:-1]
dataset = dataset.values
model = TrainModel_means(dataset, 3, 10)
centroids, final_clusters, silhouette = model.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 3 0.44
# glass
dataset2= pd.read_csv('glass.csv')
dataset2 = dataset2.iloc[:,:-1]
dataset2 = dataset2.values
model2 = TrainModel_means(dataset2, 4, 10)
centroids2, final_clusters2, silhouette2 = model2.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 4 0.28
# wine
dataset3= pd.read_csv('wine.csv')
dataset3 = dataset3.values
model3 = TrainModel_means(dataset3, 3, 10)
centroids3, final_clusters3, silhouette3 = model3.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 3 0.3

Algorytm k-medoid

$1.$ Inicjalizacja: wybierz $k$ losowych punktów spośród $n$ punktów danych jako medoidy.
$2.$ Przyporządkuj każdy punkt danych do najbliższego medoidu, używając dowolnych popularnych metod metryki odległości.
$3.$ Podczas gdy koszt maleje:
Dla każdej medoidy $m$, dla każdego punktu danych $o$, który nie jest medoidą:
$i.$ Zamień punkty $m$ i $o$, przyporządkuj każdy punkt danych do najbliższej medoidy, ponownie oblicz koszt.
$ii.$ Jeśli całkowity koszt jest większy niż w poprzednim kroku, cofnij zamianę.

Rozwiązanie: Implementacja algorytmu k-medoid w Pythonie. Do wykonania algorytmu k-medoidy potrzebne jest wstępne przetworzenie danych. W naszym rozwiązaniu przeprowadziliśmy wstępne przetwarzanie danych w celu zaimplementowania algorytmu k-medoid.

class TrainModel_medoids:
    def __init__(self, data, k_value):
        self.data = data
        scaler = MinMaxScaler()
        self.data = scaler.fit_transform(self.data)
        self.k_value = k_value
        self.medoids, self.res_cluster, self.cluster_labels, self.silhouette = self.kmedoids(self.data)

    def get_random_medoids(self, data):
        points = random.sample(range(0, len(data)), self.k_value)
        medoids = []
        for i in points:
            medoids.append(data[i])
        return medoids

    def get_closest_medoids(self, sample_point, medoids):
        min_distance = float('inf')
        closest_medoid = None
        for i in range(len(medoids)):
            distance = self.calculateDistance(sample_point, medoids[i])
            if distance < min_distance:
                min_distance = distance
                closest_medoid = i
        return closest_medoid

    def get_clusters(self, data_points, medoids):
        clusters = [[] for _ in range(self.k_value)]
        for i in range(len(data_points)):
            x = self.get_closest_medoids(data_points[i], medoids)
            clusters[x].append(data_points[i])
        return clusters

    def calculate_cost(self, data_points, clusters, medoids):
        cost = 0
        for i in range(len(clusters)):
            for j in range(len(clusters[i])):
                cost += self.calculateDistance(medoids[i], clusters[i][j])
        return cost

    def get_non_medoids(self, data_points, medoids):
        non_medoids = []
        for sample in data_points:
            flag = False
            for m in medoids:
                if (sample == m).all():
                    flag = True
            if flag == False:
                non_medoids.append(sample)
        return non_medoids

    def get_clusters_label(self, data_points, clusters):
        labels = []
        for i in range(len(data_points)):
            labels.append(0)
        for i in range(len(clusters)):
            cluster = clusters[i]
            for j in range(len(cluster)):
                for k in range(len(data_points)):
                    if (cluster[j] == data_points[k]).all():
                        labels[k] = i
                        break
        return labels

    def kmedoids(self, data):
        medoids = self.get_random_medoids(data)
        clusters = self.get_clusters(data, medoids)
        initial_cost = self.calculate_cost(data, clusters, medoids)
        while True:
            best_medoids = medoids
            lowest_cost = initial_cost
            for i in range(len(medoids)):
                non_medoids = self.get_non_medoids(data, medoids)
                for j in range(len(non_medoids)):
                    new_medoids = medoids.copy()
                    for k in range(len(new_medoids)):
                        if (new_medoids[k] == medoids[i]).all():
                            new_medoids[k] = non_medoids[j]
                    new_clusters = self.get_clusters(data, new_medoids)
                    new_cost = self.calculate_cost(data, new_clusters, new_medoids)
                    if new_cost < lowest_cost:
                        lowest_cost = new_cost
                        best_medoids = new_medoids
            if lowest_cost < initial_cost:
                initial_cost = lowest_cost
                medoids = best_medoids
            else:
                break
        final_clusters = self.get_clusters(data, medoids)
        cluster_labels = self.get_clusters_label(data, final_clusters)
        silhouette_avg = silhouette_score(data, cluster_labels)

        print("Sylwetka (ang.silhouette) dla metody k-medoid i dla k =", self.k_value, round(silhouette_avg,2))

        res_cluster = []
        for i in range(0, self.k_value):
            res_cluster.append([data[s] for s in range(0, len(data)) if cluster_labels[s] == i])
        return medoids, res_cluster, cluster_labels, round(silhouette_avg,2)

    def calculateDistance(self, x, y):
        return np.linalg.norm(x-y)

    def return_values(self):
        return self.medoids, self.res_cluster, self.cluster_labels, self.silhouette

Uruchomienie algorytmu k-medoid dla zbioru danych iris

# iris
model4 = TrainModel_medoids(dataset, 3)
medoids4, res_cluster4, cluster_labels4, silhouette4 = model4.return_values()

res = res_cluster4[0] + res_cluster4[1] + res_cluster4[2]

data = {'Długość kielicha': [round(res[i][0],2) for i in range(0, len(res))],
        'Szerokość kielicha': [round(res[i][1],2) for i in range(0, len(res))],
        'Długość płatka': [round(res[i][2],2) for i in range(0, len(res))],
        'Szerokość płatka': [round(res[i][3],2) for i in range(0, len(res))],
        'Wartość medoidu 0': [(round(medoids4[0][0],2),round(medoids4[0][1],2), round(medoids4[0][2],2), round(medoids4[0][3],2)) for i in range(150)],
        'Wartość medoidu 1': [(round(medoids4[1][0],2), round(medoids4[1][1],2), round(medoids4[1][2],2), round(medoids4[1][3],2)) for i in range(150)],
        'Wartość medoidu 2': [(round(medoids4[2][0],2), round(medoids4[2][1],2), round(medoids4[2][2],2), round(medoids4[2][3],2)) for i in range(150)],
        'Medoid': cluster_labels4}
df = pd.DataFrame(data)
df.to_csv('iris_data.csv')

pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 10)
pd.set_option('display.colheader_justify', 'center')
pd.set_option('display.precision', 5)
display(df)
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 3 0.48
Długość kielicha Szerokość kielicha Długość płatka Szerokość płatka Wartość medoidu 0 Wartość medoidu 1 Wartość medoidu 2 Medoid
0 0.17 0.46 0.08 0.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
1 0.17 0.46 0.08 0.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
2 0.75 0.50 0.63 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
3 0.58 0.50 0.59 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
4 0.72 0.46 0.66 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
5 0.33 0.12 0.51 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
6 0.61 0.33 0.61 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
7 0.39 0.33 0.59 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
8 0.56 0.54 0.63 0.63 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
9 0.17 0.17 0.39 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
10 0.64 0.38 0.61 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
11 0.25 0.29 0.49 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
12 0.19 0.00 0.42 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
13 0.44 0.42 0.54 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
14 0.47 0.08 0.51 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
15 0.50 0.38 0.63 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
16 0.36 0.38 0.44 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
17 0.67 0.46 0.58 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
18 0.36 0.42 0.59 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
19 0.42 0.29 0.53 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
20 0.53 0.08 0.59 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
21 0.36 0.21 0.49 0.42 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
22 0.44 0.50 0.64 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
23 0.50 0.33 0.51 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
24 0.56 0.21 0.66 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
25 0.50 0.33 0.63 0.46 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
26 0.58 0.38 0.56 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
27 0.64 0.42 0.58 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
28 0.69 0.33 0.64 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
29 0.47 0.38 0.59 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
30 0.39 0.25 0.42 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
31 0.33 0.17 0.47 0.42 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
32 0.33 0.17 0.46 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
33 0.42 0.29 0.49 0.46 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
34 0.47 0.29 0.69 0.63 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
35 0.31 0.42 0.59 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
36 0.47 0.58 0.59 0.63 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
37 0.67 0.46 0.63 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
38 0.56 0.12 0.58 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
39 0.36 0.42 0.53 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
40 0.33 0.21 0.51 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
41 0.33 0.25 0.58 0.46 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
42 0.50 0.42 0.61 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
43 0.42 0.25 0.51 0.46 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
44 0.19 0.12 0.39 0.38 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
45 0.36 0.29 0.54 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
46 0.39 0.42 0.54 0.46 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
47 0.39 0.38 0.54 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
48 0.53 0.38 0.56 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
49 0.22 0.21 0.34 0.42 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 2
50 0.39 0.33 0.53 0.50 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
51 0.42 0.29 0.69 0.75 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
52 0.17 0.21 0.59 0.67 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
53 0.39 0.21 0.68 0.79 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
54 0.47 0.08 0.68 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
55 0.36 0.33 0.66 0.79 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
56 0.56 0.29 0.66 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
57 0.53 0.33 0.64 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
58 0.50 0.42 0.66 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
59 0.56 0.33 0.69 0.58 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
60 0.50 0.25 0.78 0.54 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
61 0.47 0.42 0.64 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
62 0.42 0.29 0.69 0.75 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
63 0.56 0.21 0.68 0.75 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
64 0.44 0.42 0.69 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
65 0.67 0.42 0.68 0.67 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
66 0.56 0.54 0.85 1.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
67 0.78 0.42 0.83 0.83 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
68 0.56 0.38 0.78 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
69 0.61 0.42 0.81 0.88 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
70 0.92 0.42 0.95 0.83 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
71 0.83 0.38 0.90 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
72 0.67 0.21 0.81 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
73 0.81 0.67 0.86 1.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
74 0.61 0.50 0.69 0.79 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
75 0.58 0.29 0.73 0.75 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
76 0.69 0.42 0.76 0.83 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
77 0.42 0.33 0.69 0.96 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
78 0.58 0.50 0.73 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
79 0.61 0.42 0.76 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
80 0.94 0.75 0.97 0.88 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
81 0.94 0.25 1.00 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
82 0.72 0.50 0.80 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
83 0.94 0.33 0.97 0.79 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
84 0.67 0.54 0.80 0.83 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
85 0.81 0.50 0.85 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
86 0.58 0.33 0.78 0.83 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
87 0.81 0.42 0.81 0.63 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
88 0.86 0.33 0.86 0.75 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
89 1.00 0.75 0.92 0.79 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
90 0.58 0.33 0.78 0.88 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
91 0.94 0.42 0.86 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
92 0.56 0.58 0.78 0.96 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
93 0.58 0.46 0.76 0.71 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
94 0.72 0.46 0.75 0.83 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
95 0.67 0.46 0.78 0.96 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
96 0.72 0.46 0.69 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
97 0.69 0.50 0.83 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
98 0.67 0.54 0.80 1.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
99 0.67 0.42 0.71 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
100 0.61 0.42 0.71 0.79 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
101 0.53 0.58 0.75 0.92 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
102 0.22 0.62 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
103 0.17 0.42 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
104 0.11 0.50 0.05 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
105 0.08 0.46 0.08 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
106 0.19 0.67 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
107 0.31 0.79 0.12 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
108 0.08 0.58 0.07 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
109 0.19 0.58 0.08 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
110 0.03 0.38 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
111 0.17 0.46 0.08 0.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
112 0.31 0.71 0.08 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
113 0.14 0.58 0.10 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
114 0.14 0.42 0.07 0.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
115 0.00 0.42 0.02 0.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
116 0.42 0.83 0.03 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
117 0.39 1.00 0.08 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
118 0.31 0.79 0.05 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
119 0.22 0.62 0.07 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
120 0.39 0.75 0.12 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
121 0.22 0.75 0.08 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
122 0.31 0.58 0.12 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
123 0.22 0.71 0.08 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
124 0.08 0.67 0.00 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
125 0.22 0.54 0.12 0.17 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
126 0.14 0.58 0.15 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
127 0.19 0.42 0.10 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
128 0.19 0.58 0.10 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
129 0.25 0.62 0.08 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
130 0.25 0.58 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
131 0.11 0.50 0.10 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
132 0.14 0.46 0.10 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
133 0.31 0.58 0.08 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
134 0.25 0.87 0.08 0.00 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
135 0.33 0.92 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
136 0.19 0.50 0.03 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
137 0.33 0.62 0.05 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
138 0.03 0.42 0.05 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
139 0.22 0.58 0.08 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
140 0.19 0.62 0.05 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
141 0.06 0.12 0.05 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
142 0.03 0.50 0.05 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
143 0.19 0.62 0.10 0.21 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
144 0.22 0.75 0.15 0.12 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
145 0.14 0.42 0.07 0.08 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
146 0.22 0.75 0.10 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0
147 0.08 0.50 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
148 0.28 0.71 0.08 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 1
149 0.19 0.54 0.07 0.04 (0.47, 0.38, 0.59, 0.58) (0.69, 0.42, 0.76, 0.83) (0.19, 0.58, 0.08, 0.04) 0

Uruchomienie algorytmu k-medoid dla zbioru danych glass

# glass
model5 = TrainModel_medoids(dataset2, 4)
medoids5, res_cluster5, cluster_labels5, silhouette5 = model5.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 4 0.35

Uruchomienie algorytmu k-medoid dla zbioru danych wine

# wine
model6 = TrainModel_medoids(dataset3, 3)
medoids6, res_cluster6, cluster_labels6, silhouette6 = model6.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 3 0.28

Algorytm k-medoid + PCA

pca = PCA(n_components=2)

Redukcja wymiaru z 4 do 2 przy pomocy PCA na zbiorze danych iris

pca.fit(dataset)
dataset_pca = pca.transform(dataset)
# iris
model7 = TrainModel_medoids(dataset_pca, 3)
medoids7, res_cluster7, cluster_labels7, silhouette7 = model7.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 3 0.5

Redukcja wymiaru z 9 do 2 przy pomocy PCA na zbiorze danych glass

pca.fit(dataset2)
dataset2_pca = pca.transform(dataset2)
# glass
model8 = TrainModel_medoids(dataset2_pca, 4)
medoids8, res_cluster8, cluster_labels8, silhouette8 = model8.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 4 0.5

Redukcja wymiaru z 13 do 2 przy pomocy PCA na zbiorze danych wine

pca.fit(dataset3)
dataset3_pca = pca.transform(dataset3)
# wine
model9 = TrainModel_medoids(dataset3_pca, 3)
medoids9, res_cluster9, cluster_labels9, silhouette9 = model9.return_values()
Sylwetka (ang.silhouette) dla metody k-medoid i dla k = 3 0.45

Porównanie metody k-średnich, k-medoid, k-medoid + PCA

W celu porównania przedstawionych powyżej trzech metod został stworzony wykres. Na wykresie zostały porównane wartości sylwetek trzech metod na trzech zbiorach danych (iris, glass, wine):

result_data = {'Iris': [silhouette, silhouette4, silhouette7],
              'Glass': [silhouette2, silhouette5, silhouette8],
              'Wine': [silhouette3, silhouette6, silhouette9]}
df_shoulette = pd.DataFrame(result_data)
df_shoulette.index = ['k-średnich', 'k-medoid', 'k-medoid + PCA']
barWidth = 0.25
fig = plt.subplots(figsize =(12, 8))

iris = [silhouette, silhouette2, silhouette3]
glass = [silhouette4, silhouette5, silhouette6]
wine = [silhouette7, silhouette8, silhouette9]

br1 = np.arange(len(iris))
br2 = [x + barWidth for x in br1]
br3 = [x + barWidth for x in br2]

plt.bar(br1, iris, color ='y', width = barWidth, edgecolor ='grey', label ='k-średnich')
plt.bar(br2, glass, color ='m', width = barWidth, edgecolor ='grey', label ='k-medoid')
plt.bar(br3, wine, color ='c', width = barWidth, edgecolor ='grey', label ='k-medoid + PCA')

plt.xlabel('Zbiór danych', fontsize = 15)
plt.ylabel('Wartość sylwetki', fontsize = 15)
plt.xticks([r + barWidth for r in range(len(iris))], ['Iris', 'Glass', 'Wine'])

plt.legend()
plt.show()
df_shoulette
Iris Glass Wine
k-średnich 0.44 0.28 0.30
k-medoid 0.48 0.35 0.28
k-medoid + PCA 0.50 0.50 0.45

W wyniku tego porównania można dojść do wniosku, że najlepszą z metod jest metoda k-medoid wraz z redukcją wymiaru zbiorów danych przy pomocy PCA.