參考資料:python機器學習庫sklearn——DBSCAN密度聚類, Python實現DBScan
import numpy as np from sklearn.cluster import DBSCAN from sklearn import metrics from sklearn.datasets.samples_generator import make_blobs from sklearn.preprocessing import StandardScaler # ############################################################################# # 產生樣本數據 centers = [[1, 1], [-1, -1], [1, -1]] # 生成聚類中心點 X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4,random_state=0) # 生成樣本數據集 X = StandardScaler().fit_transform(X) # StandardScaler作用:去均值和方差歸一化。且是針對每一個特征維度來做的,而不是針對樣本。 # 參數設置 aa = [] for i in range(X.shape[0]-1): for j in range(i+1,X.shape[0]): aa.append(np.power(X[i]-X[j], 2).sum()) plt.hist(aa, bins=10, density=1, edgecolor ='k', facecolor='g', alpha=0.75) # 調參############################################################################# t0 = time.time() optimum_parameter = [0,0,0] for r in np.linspace(0.1, 0.3, 5): for min_samples in range(5,12): db = DBSCAN(eps=r, min_samples=min_samples).fit(X) score = metrics.silhouette_score(X, db.labels_) print('(%0.2f, %d) 輪廓系數: %0.3f'%(r, min_samples, score)) if score > optimum_parameter[2]: optimum_parameter=[r, min_samples, score] print('最佳參數為:eps=%0.2f, min_samples=%d, 輪廓系數=%0.3f'%(optimum_parameter[0], optimum_parameter[1], optimum_parameter[2])) print('調參耗時:', time.time()-t0) # ############################################################################# # 調用密度聚類 DBSCAN db = DBSCAN(eps=0.3, min_samples=9).fit(X) # print(db.labels_) # db.labels_為所有樣本的聚類索引,沒有聚類索引為-1 # print(db.core_sample_indices_) # 所有核心樣本的索引 core_samples_mask = np.zeros_like(db.labels_, dtype=bool) # 設置一個樣本個數長度的全false向量 core_samples_mask[db.core_sample_indices_] = True #將核心樣本部分設置為true labels = db.labels_ # 獲取聚類個數。(聚類結果中-1表示沒有聚類為離散點) n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0) # 模型評估 print('估計的聚類個數為: %d' % n_clusters_) print("同質性: %0.3f" % metrics.homogeneity_score(labels_true, labels)) # 每個群集只包含單個類的成員。 print("完整性: %0.3f" % metrics.completeness_score(labels_true, labels)) # 給定類的所有成員都分配給同一個群集。 print("V-measure: %0.3f" % metrics.v_measure_score(labels_true, labels)) # 同質性和完整性的調和平均 print("調整蘭德指數: %0.3f" % metrics.adjusted_rand_score(labels_true, labels)) print("調整互信息: %0.3f" % metrics.adjusted_mutual_info_score(labels_true, labels)) print("輪廓系數: %0.3f" % metrics.silhouette_score(X, labels)) # ############################################################################# # Plot result import matplotlib.pyplot as plt # 使用黑色標注離散點 unique_labels = set(labels) colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))] for k, col in zip(unique_labels, colors): if k == -1: # 聚類結果為-1的樣本為離散點 # 使用黑色繪制離散點 col = [0, 0, 0, 1] class_member_mask = (labels == k) # 將所有屬於該聚類的樣本位置置為true xy = X[class_member_mask & core_samples_mask] # 將所有屬於該類的核心樣本取出,使用大圖標繪制 plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),markeredgecolor='k', markersize=14) xy = X[class_member_mask & ~core_samples_mask] # 將所有屬於該類的非核心樣本取出,使用小圖標繪制 plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),markeredgecolor='k', markersize=6) plt.title('Estimated number of clusters: %d' % n_clusters_) plt.show()