证据积累聚类集成算法(Evidence Accumulation Clustering)代码复现与实验
生活随笔
收集整理的這篇文章主要介紹了
证据积累聚类集成算法(Evidence Accumulation Clustering)代码复现与实验
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1. 基本環(huán)境
運(yùn)行環(huán)境: - Python 3.7 + - Jupyter NoteBook - 處理器:2.6 GHz 六核Intel Core i72. 聚類集成代碼
# 導(dǎo)入包 import pandas as pd import numpy as np import math import random import matplotlib.pyplot as plt from sklearn.cluster import KMeans, AgglomerativeClustering from sklearn import datasets from scipy.cluster.hierarchy import dendrogram, linkage, fcluster from sklearn import metrics import scipy.spatial.distance as dist # Kmeans-聚類算法 def kmeans_cluster(data, **kwargs): # K-meansif kwargs is None:kwargs = {'k': 8}kmean = KMeans(n_clusters=kwargs['k'])return kmean.fit_predict(data) # 更新鄰近度矩陣 # similar_mat: 原鄰近度矩陣 # cluster_ind: 類群的樣本序號列表 def update_similar_mat(similar_mat, cluster_ind):if len(cluster_ind) <= 1:return similar_matfor ind, no_i in enumerate(cluster_ind): # ind 是下標(biāo), no_i 是值if no_i == cluster_ind[-1]:return similar_matfor no_j in cluster_ind[ind+1:]:similar_mat[no_i, no_j] += 1similar_mat[no_j, no_i] += 1 # 單聚類算法 def single_fit(para_list, data):k = random.randint(0, len(para_list)-1)cluster_result = kmeans_cluster(data, k=para_list[k])return cluster_result # number 聚類次數(shù) # X 原始數(shù)據(jù) # result_dict 聚類結(jié)果 def ensemble_SL(number, X, result_dict):threshold = 0 # 閾值similar_mat = np.zeros((X.shape[0], X.shape[0]))for single_result in result_dict:k_num = list(set(single_result)) # set(single_result) 取出單個聚類結(jié)果中不重復(fù)的元素形成一個set集合, 然后再轉(zhuǎn)化為list列表threshold += len(k_num)for k_i in k_num:index_same_ki = np.where(single_result == k_i)[0] # 存儲相同類簇的樣本序號update_similar_mat(similar_mat, index_same_ki) # 根據(jù)樣本序號更新鄰近度矩陣# [number] * X.shape[0] 構(gòu)成長度為總樣本數(shù),且每個值為聚類分區(qū)數(shù)目的一維數(shù)組# np.diag([number] * X.shape[0]) 輸出一個以 [number] * X.shape[0] 一維數(shù)組為對角線元素的矩陣# 更新相似度矩陣的主對角線元素值為聚類分區(qū)數(shù)similar_mat += np.diag([number] * X.shape[0])# 鄰近度矩陣變換為距離矩陣# similar_mat / number 構(gòu)成投票后的鄰近度矩陣, 值越大,兩者出現(xiàn)在不同聚類分區(qū)中同一類簇的次數(shù)越多# 1 - similar_mat / number 值越小,兩者出現(xiàn)在不同聚類分區(qū)中同一類簇的次數(shù)越多,如此才能層次聚類distance_mat = 1 - similar_mat / numberdistance = dist.squareform(distance_mat)# linkage SL 層次聚類Z = linkage(distance, 'single')# Z矩陣,第一個和第二個元素是每一步合并的兩個簇,# 第三個元素是這些簇之間的距離,# 第四個元素是新簇的大小——包含的原始數(shù)據(jù)點的數(shù)量.# dendrogram(Z)# plt.show()# 挑選生存時間最長簇個數(shù)# group_distance = Z[:-min_cluster, 2] # 類間距離向量, 取出Z從-min_cluster行開始的每一維度的第三列元素,各元素之間的簇。group_distance = Z[:, 2] # 類間距離向量, 取出Z第三列所有的類簇lifetime = group_distance[1:] - group_distance[:-1] # 計算生命周期max_lifetime_index = np.argmax(lifetime)threshold = Z[max_lifetime_index, 2] # 對應(yīng)的類間距離cluster_result = fcluster(Z, threshold, 'distance')return cluster_result EAC-SL 或 EAC-AL 的區(qū)別在于采用“Single”或是“Average”的層次聚類算法。 def ensemble_AL(number, X, result_dict):threshold = 0 # 閾值similar_mat = np.zeros((X.shape[0], X.shape[0]))for single_result in result_dict:k_num = list(set(single_result)) # set(single_result) 取出單個聚類結(jié)果中不重復(fù)的元素形成一個set集合, 然后再轉(zhuǎn)化為list列表threshold += len(k_num)for k_i in k_num:index_same_ki = np.where(single_result == k_i)[0] # 存儲相同類簇的樣本序號update_similar_mat(similar_mat, index_same_ki) # 根據(jù)樣本序號更新鄰近度矩陣# [number] * X.shape[0] 構(gòu)成長度為總樣本數(shù),且每個值為聚類分區(qū)數(shù)目的一維數(shù)組# np.diag([number] * X.shape[0]) 輸出一個以 [number] * X.shape[0] 一維數(shù)組為對角線元素的矩陣# 更新相似度矩陣的主對角線元素值為聚類分區(qū)數(shù)similar_mat += np.diag([number] * X.shape[0])# 鄰近度矩陣變換為距離矩陣# similar_mat / number 構(gòu)成投票后的鄰近度矩陣, 值越大,兩者出現(xiàn)在不同聚類分區(qū)中同一類簇的次數(shù)越多# 1 - similar_mat / number 值越小,兩者出現(xiàn)在不同聚類分區(qū)中同一類簇的次數(shù)越多,如此才能層次聚類distance_mat = 1 - similar_mat / numberdistance = dist.squareform(distance_mat)# linkage SL 層次聚類Z = linkage(distance, 'average')# Z矩陣,第一個和第二個元素是每一步合并的兩個簇,# 第三個元素是這些簇之間的距離,# 第四個元素是新簇的大小——包含的原始數(shù)據(jù)點的數(shù)量.# dendrogram(Z)# plt.show()# 挑選生存時間最長簇個數(shù)# group_distance = Z[:-min_cluster, 2] # 類間距離向量, 取出Z從-min_cluster行開始的每一維度的第三列元素,各元素之間的簇。group_distance = Z[:, 2] # 類間距離向量, 取出Z第三列所有的類簇lifetime = group_distance[1:] - group_distance[:-1] # 計算生命周期max_lifetime_index = np.argmax(lifetime)threshold = Z[max_lifetime_index, 2] # 對應(yīng)的類間距離cluster_result = fcluster(Z, t=2, criterion='maxclust')return cluster_result3. 聚類集成的測試
3.1 兩個同心圓測試
3.1.1 生成同心圓數(shù)據(jù)
data,y = datasets.make_circles(600, noise=0) labels_true = y plt.scatter(data[:, 0], data[:, 1],s=40, c = y, cmap=plt.cm.Spectral) plt.show()3.1.2 進(jìn)行50次K-Means聚類,并計算平均 ARI 得分
# 進(jìn)行 50 次 K-Means 聚類,并計算平均 ARI 得分 fig = plt.figure(figsize=(50,50)) ARI = 0 for i in range(50):result = kmeans_cluster(data,k=2)plt.subplot(10,5,i+1)plt.title(i+1)plt.scatter(data[:, 0], data[:, 1],s=40, c = result, cmap=plt.cm.Spectral)labels_pred = resultARI += metrics.adjusted_rand_score(labels_true, labels_pred) plt.show() print("Average - ARI: \n", ARI / 50)運(yùn)行結(jié)果
運(yùn)行時間 6.9s
3.1.3 進(jìn)行50次 EAC-SL 聚類集成,并計算平均 ARI 得分
# EAC-SL ARI = 0 fig = plt.figure(figsize=(30,30)) number = 200 # 參與集成的數(shù)據(jù)分區(qū)數(shù) para_list = np.arange(2, 2 * int(math.sqrt(len(data))), 1) # K-Means的超參列表 for i in range(50):result_dict = []for k in range(number):result_dict.append(single_fit(para_list,data)) result = ensemble_SL(number, data, result_dict) # 使用EAC-SL聚類集成labels_pred = resultplt.subplot(10,5,i+1)plt.scatter(data[:, 0], data[:, 1],s=40, c = result, cmap=plt.cm.Spectral)ARI += metrics.adjusted_rand_score(labels_true, labels_pred) # 累加 50 輪 ARI 得分 plt.show() print("Average - ARI: \n", ARI / 50)運(yùn)行結(jié)果
運(yùn)行時間 15m 25.4s
3.1.3 進(jìn)行50次 EAC-AL 聚類集成,并計算平均 ARI 得分
# EAC-AL ARI = 0 fig = plt.figure(figsize=(50,50)) number = 200 para_list = np.arange(2, 2 * int(math.sqrt(len(data))), 1) for i in range(50):result_dict = []for k in range(number):result_dict.append(single_fit(para_list,data)) result = ensemble_AL(number, data, result_dict)labels_pred = resultplt.subplot(10,5,i+1)plt.scatter(data[:, 0], data[:, 1],s=40, c = result, cmap=plt.cm.Spectral)ARI += metrics.adjusted_rand_score(labels_true, labels_pred)plt.show() print("Average - ARI: \n", ARI / 50)運(yùn)行結(jié)果
運(yùn)行時間 16m51.7s
3.1.4 進(jìn)行50次單鏈接層次聚類,并計算平均 ARI 得分
fig = plt.figure(figsize=(50,50)) ARI = 0 for i in range(50):result = AgglomerativeClustering(linkage='single').fit(data)plt.subplot(10,5,i+1)plt.title(i+1)plt.scatter(data[:, 0], data[:, 1],s=40, c = result.labels_, cmap=plt.cm.Spectral)labels_pred = result.labels_ARI += metrics.adjusted_rand_score(labels_true, labels_pred) plt.show() print("Average - ARI:",ARI / 50)運(yùn)行結(jié)果
運(yùn)行時間 6.7s
3.1 小結(jié)
對于分離干凈的類簇, EAC-SL 和 單鏈接層次聚類效果很好,但是 EAC-SL 的時間復(fù)雜度很高,運(yùn)行時間遠(yuǎn)遠(yuǎn)大于單鏈接層次聚類。但讓我覺得詫異的是,原論文(Combining Multiple Clusterings Using Evidence Accumulation)中 EAC-AL 解決此數(shù)據(jù)集的錯誤率是0,也就是應(yīng)當(dāng)完美聚成兩類,但是復(fù)現(xiàn)的結(jié)果很垃圾,希望看到此篇文章的朋友們能指點迷津。
3.2 接下來要做的事情
明日更新,給數(shù)據(jù)集加噪聲,繼續(xù)做對比測試。
總結(jié)
以上是生活随笔為你收集整理的证据积累聚类集成算法(Evidence Accumulation Clustering)代码复现与实验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Microsoft Teams:团队Ow
- 下一篇: 三星手机变砖后急救