1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | #!/usr/bin/env python # coding: utf-8 # In[67]: import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn import metrics import warnings warnings.filterwarnings("ignore", category=RuntimeWarning) # In[2]: data = pd.read_csv('Mall_Customers.csv') data.head() # In[3]: data.info() # In[4]: data.describe() # * 감사히도 결측치는 없고 성별, 나이, 소득, 지출 점수를 가지고 클러스터링을 할 수 있을 것 같아요 # In[5]: data = data.drop(columns=['CustomerID']) sns.pairplot(data, hue="Gender") plt.show() # * ID는 필요없으므로 삭제했고 성별에 따라 분포를 보았는데 큰 차이는 없어보입니다. # In[6]: data['Gender'].replace(['Male','Female'],[0,1],inplace=True) sns.heatmap(data.corr(),annot=True,linewidths=0.2) fig=plt.gcf() plt.show() # * ID는 빼는게 맞아보입니다. # * 나이가 많을 수록 지출이 많을 줄 알았는데 그 것은 또 아니네요 # ## Hierarchical agglomerative clustering # In[7]: X = data[['Annual Income (k$)','Spending Score (1-100)']] X.head() # In[8]: import scipy.cluster.hierarchy as sch dendrogram = sch.dendrogram(sch.linkage(X, method = 'ward')) plt.title('ward method') plt.xlabel('고객') plt.ylabel('유클리디안 거리') plt.show() # In[9]: dendrogram = sch.dendrogram(sch.linkage(X, method = 'centroid')) plt.title('centroid method') plt.xlabel('고객') plt.ylabel('유클리디안 거리') plt.show() # * centroid 방식이 더 복잡해보입니다. # ## 평가 # # * Davies_bouldin_score: 높은 클러스터 내 유사도를 가지고 낮은 클러스터간 유사도를 가지는 클러스터들을 생성하는 클러스터링 알고리즘은 낮은 index 값을 가지게 된다. 따라서, 이 지표가 낮은 클러스터링 알고리즘이 좋은 클러스터링 알고리즘으로 평가된다. # * Silhouette Coefficient: 1에 가까울 수록 데이터 데이터 i 는 올바른 클러스터에 분류된 것이며, -1에 가까울 수록 잘못된 클러스터에 분류되었음을 나타낸다. # ## Agglomerative clustering # In[59]: from sklearn import metrics from sklearn.cluster import AgglomerativeClustering li = [2,5,8] for i in li: agg = AgglomerativeClustering(n_clusters=i, affinity='euclidean', linkage='ward').fit(X) labels = agg.labels_ plt.scatter(X['Annual Income (k$)'],X['Spending Score (1-100)'], c=labels, cmap='rainbow') plt.show() print('Silhouette Coefficient: ', metrics.silhouette_score(X, labels, metric='euclidean')) print('Davies_bouldin_score: ', metrics .davies_bouldin_score(X, labels)) # * 클러스터 개수를 하이퍼 파라미터로 지정해줄 수 있습니다. 5가 가장 평가지표가 좋네요 # ## K-Means # In[12]: from sklearn.cluster import KMeans inertias = [] for i in range(1, 20): kmeans = KMeans(n_clusters = i, init = 'k-means++') kmeans.fit(X) inertias.append(kmeans.inertia_) plt.plot(range(1, 20), inertias) plt.xlabel('cluster number') plt.ylabel('inertias') plt.show() # * 5가 elbow point로 가장 이상적인 개수로 보입니다. # In[61]: kmeans = KMeans(n_clusters = 5, init = 'k-means++', random_state = 42) kmeans.fit(X) label = kmeans.labels_ y_kmeans = kmeans.predict(X) centers = kmeans.cluster_centers_ plt.scatter(X['Annual Income (k$)'],X['Spending Score (1-100)'], c=y_kmeans, s=50, cmap='viridis') plt.scatter(centers[:, 0], centers[:, 1], c='black', s=200, alpha=0.5) print('Silhouette Coefficient: ', metrics.silhouette_score(X, label, metric='euclidean')) print('Davies_bouldin_score: ', metrics .davies_bouldin_score(X, label)) # ## Mean-Shift # In[62]: from sklearn.cluster import MeanShift, estimate_bandwidth li = [10,100,500] for i in li: bandwidth = estimate_bandwidth(X, quantile=0.2, n_samples=i) ms = MeanShift(bandwidth=bandwidth, bin_seeding=True) ms.fit(X) labels = ms.labels_ cluster_centers = ms.cluster_centers_ plt.scatter(X['Annual Income (k$)'],X['Spending Score (1-100)'], c=labels, s=50, cmap='viridis') plt.scatter(cluster_centers[:, 0], cluster_centers[:, 1], c='black', s=200, alpha=0.5); plt.show() print('Silhouette Coefficient: ', metrics.silhouette_score(X, labels, metric='euclidean')) print('Davies_bouldin_score: ', metrics .davies_bouldin_score(X, labels)) # * Mean Shift는 어떤 데이터 분포의 peak 또는 무게중심을 찾는 한 방법으로서, 현재 자신의 주변에서 가장 데이터가 밀집된 방향으로 이동한다. 그러다 보면 언젠가는 분포 중심을 찾을 수 있을 거라는 방법이다. # * bandwidth = distance/size scale of the kernel function # * estimate_bandwith로 파라미터에 따라 클러스터 수를 결정해주고 있습니다. # ## DBSCAN # In[68]: from sklearn.cluster import DBSCAN li = [2,5,10,15] for i in li: db = DBSCAN(eps=i, min_samples=5).fit(X) cluster = db.fit_predict(X) label = db.labels_ plt.scatter(x = X['Annual Income (k$)'],y = X['Spending Score (1-100)'], c=cluster) plt.xlabel("Annual Income") plt.ylabel("Spending Score") plt.show() print('Silhouette Coefficient: ', metrics.silhouette_score(X, label, metric='euclidean')) print('Davies_bouldin_score: ', metrics .davies_bouldin_score(X, label)) # * eps를 어떻게 정하느냐에 따라 상당히 다른 모습을 보이고 있습니다. # | cs |
Designed by sketchbooks.co.kr / sketchbook5 board skin
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5