1. 程式人生 > >python 實現 AP近鄰傳播聚類演算法(Affinity Propagation)

python 實現 AP近鄰傳播聚類演算法(Affinity Propagation)

Affinity Propagation (AP) 聚類是2007年在Science雜誌上提出的一種新的聚類演算法。它根據N個數據點之間的相似度進行聚類,這些相似度可以是對稱的,即兩個資料點互相之間的相似度一樣(如歐氏距離);也可以是不對稱的,即兩個資料點互相之間的相似度不等。這些相似度組成N×N的相似度矩陣S(其中N為有N個數據點)。

AP演算法不需要事先指定聚類數目,相反它將所有的資料點都作為潛在的聚類中心,稱之為 exemplar。以S矩陣的對角線上的數值s (k, k)作為k點能否成為聚類中心的評判標準,這意味著該值越大,這個點成為聚類中心的可能性也就越大,這個值又稱作參考度p ( preference) 。聚類的數量受到參考度p的影響,如果認為每個資料點都有可能作為聚類中心,那麼p就應取相同的值。如果取輸入的相似度的均值作為p的值,得到聚類數量是中等的。如果取最小值,得到類數較少的聚類。

AP演算法中傳遞兩種型別的訊息,(responsiility)和(availability) 。r(i,k)表示從點i傳送到候選聚類中心k的數值訊息,反映k點是否適合作為i點的聚類中心。a(i,k)則從候選聚類中心k傳送到i的數值訊息,反映i點是否選擇k作為其聚類中心。r (i, k)與a (i, k)越強,則k點作為聚類中心的可能性就越大,並且i點隸屬於以k點為聚類中心的聚類的可能性也越大。AP演算法通過迭代過程不斷更新每一個點的吸引度和歸屬度值,直到產生m個高質量的exemplar,同時將其餘的資料點分配到相應的聚類中。

在這裡介紹幾個文中常出現的名詞:

exemplar:指的是聚類中心。

similarity:資料點i和點j的相似度記為S(i,j)。是指點j作為點i的聚類中心的相似度。

preference:資料點i的參考度稱為P(i)或S(i,i)。是指點i作為聚類中心的參考度。一般取S相似度值的中值。

Responsibility:R(i,k)用來描述點k適合作為資料點i的聚類中心的程度。

Availability:A(i,k)用來描述點i選擇點k作為其聚類中心的適合程度。

Damping factor:阻尼係數,主要是起收斂作用的。

AP聚類演算法是將每個資料看成圖中的一個節點,迭代的過程即是在圖中通過傳播信 息來找到聚類集合。本文計算兩個資料點的相似度採用距離的負數,也就是說距離越近,相似度越大。相似矩陣S中i到j的相似度就是剛剛所說的距離的負數。但是主對角線上的那些數表示的是某個點和自身的相似度,但是這裡我們不能直接用0來表示。根據演算法要求,主對角線上的值s(k,k)一般稱為偏向引數,一般 情況下對所有k,s(k,k)都相等,取非主對角線上的所有數的中位數。這個值很重要,他的大小與最後得到的類的數目有關,一般而言這個數越大,得到的類的數目就越多。

這裡為什麼要設定一個偏向引數而不直接用0來算呢,估計是因為AP聚類演算法是要 用圖論的一些東西來理解的,它把所有的點都看成一個圖中的節點,通過節點之間的資訊傳遞來達到聚類的效果。具體比較複雜,形象一點說就是我告訴你我和這些人是死黨,如果你認為你也是我死黨的話,那你就加入我們這一堆人裡面來吧!

有一些詳細的原理上的東西就不說了,直接說計算過程吧。。聚類就是個不斷迭代的過程,迭代的過程主要更新兩個矩陣,代表(Responsibility)矩陣R = [r(i,k)]N×N和適選(Availabilities)矩陣A=[a(i,k)]N×N。這兩個矩陣才初始化為0,N是所有樣本的數目。r(i,k)表示第k個樣本適合作為第i個樣本的類代表點的代表程度,a(i,k)表示第i個樣本選擇第k個樣本作為類代表樣本的適合程度。迭代更新公式如下:

每次更新後就可以確定當前樣本i的代表樣本(exemplar)點k,k就是使{a(i,k)+r(i,k)}取得最大值的那個k,如果i=k的話,那麼說明樣本i就是自己這個cluster的類代表點,如果不是,那麼說明i屬於k所屬的那個cluster。

當然,迭代停止的條件就是所有的樣本的所屬都不在變化為止,或者迭代了n次都還沒有變化(n的值可以自己取)。

說起來還有一種判斷點屬於屬於哪一類的方法,就是找出所有決策矩陣主對角線元素{a(k,k)+r(k,k)}大於0的所有點,這些點全部都是類代表點,之後在決定其餘的點屬於這裡面的一類。這兩種方法的結果我沒比較過誒,不知是不是一樣的。

另外還有一點就是AP聚類演算法迭代過程很容易產生震盪,所以一般每次迭代都加上一個阻尼係數λ

rnew(i,k) = λ*rold(i,k) + (1-λ)*r(i,k)

anew(i,k) = λ*aold(i,k) + (1-λ)*a(i,k)

# coding:utf-8

from sklearn.datasets.samples_generator import make_blobs
import matplotlib.pyplot as plt
import random
import numpy as np

##############################################################################
# Generate sample data
centers = [[1, 1], [-1, -1], [1, -1]]
X, labels_true = make_blobs(n_samples=1000, centers=centers, cluster_std=0.4,
                            random_state=0)

##############################################################################


def euclideanDistance(X, Y):
	"""計算每個點與其他所有點之間的歐幾里德距離"""
	X = np.array(X)
	Y = np.array(Y)
	# print X
	return np.sqrt(np.sum((X - Y) ** 2))



def computeSimilarity(datalist):

	num = len(datalist)

	Similarity = []
	for pointX in datalist:
		dists = []
		for pointY in datalist:
			dist = euclideanDistance(pointX, pointY)
			if dist == 0:
				dist = 1.5
			dists.append(dist * -1)
		Similarity.append(dists)

	return Similarity


def affinityPropagation(Similarity, lamda):

	#初始化 吸引矩陣 和 歸屬 矩陣
	Responsibility = np.zeros_like(Similarity, dtype=np.int)
	Availability = np.zeros_like(Similarity, dtype=np.int)

	num = len(Responsibility)

	count = 0
	while count < 10:
		count += 1
		# update 吸引矩陣

		for Index in range(num):
			# print len(Similarity[Index])
			kSum = [s + a  for s, a in zip(Similarity[Index], Availability[Index])]
			# print kSum
			for Kendex in range(num):
				kfit = delete(kSum, Kendex)
				# print fit
				ResponsibilityNew = Similarity[Index][Kendex] - max(kfit)
				Responsibility[Index][Kendex] = lamda * Responsibility[Index][Kendex] + (1 - lamda) * ResponsibilityNew

		# print "Responsibility", Responsibility


		# update 歸屬矩陣

		ResponsibilityT = Responsibility.T

		# print ResponsibilityT, Responsibility

		for Index in range(num):

			iSum = [r for r in ResponsibilityT[Index]]

			for Kendex in range(num):

				# print Kendex
				# print "ddddddddddddddddddddddddddd", ResponsibilityT[Kendex]
				#
				ifit = delete(iSum, Kendex)
				ifit = filter(isNonNegative, ifit)   #上面 iSum  已經全部大於0  會導致  delete 下標錯誤

				#   k == K 對角線的情況
				if Kendex == Index:
					AvailabilityNew  = sum(ifit)
				else:
					result = Responsibility[Kendex][Kendex] + sum(ifit)
					AvailabilityNew = result if result > 0 else 0
				Availability[Kendex][Index] = lamda * Availability[Kendex][Index] + (1 - lamda) * AvailabilityNew
		print "###############################################"
		print Responsibility
		print Availability
		print "###############################################"
	return Responsibility + Availability

def computeCluster(fitable, data):
	clusters = {}
	num = len(fitable)
	for node in range(num):
		fit = list(fitable[node])
		key = fit.index(max(fit))
		if not clusters.has_key(key):
			clusters[key] = []
		point = tuple(data[node])
		clusters[key].append(point)

	return clusters
##############################################################################

"""切片刪除 返回新陣列"""
def delete(lt, index):
    lt = lt[:index] + lt[index+1:]
    return lt

def isNonNegative(x):
	return x >= 0


##############################################################################

Similarity = computeSimilarity(X)

Similarity = np.array(Similarity)

print "Similarity", Similarity

fitable = affinityPropagation(Similarity, 0.34)

print fitable

clusters = computeCluster(fitable, X)

# print clusters

##############################################################################
clusters = clusters.values()

print len(clusters)

##############################################################################
def plotClusters(clusters, title):
	""" 畫圖 """
	plt.figure(figsize=(8, 5), dpi=80)
	axes = plt.subplot(111)
	col=[]
	r = lambda: random.randint(0,255)
	for index in range(len(clusters)):
		col.append(('#%02X%02X%02X' % (r(),r(),r())))
	color = 0
	for cluster in clusters:
		cluster = np.array(cluster).T
		axes.scatter(cluster[0],cluster[1], s=20, c = col[color])
		color += 1
	plt.title(title)
	# plt.show()
##############################################################################
plotClusters(clusters, "clusters by affinity propagation")
plt.show()

##############################################################################


相關推薦

python 實現 AP近鄰傳播演算法(Affinity Propagation)

Affinity Propagation (AP) 聚類是2007年在Science雜誌上提出的一種新的聚類演算法。它根據N個數據點之間的相似度進行聚類,這些相似度可以是對稱的,即兩個資料點互相之間的相似度一樣(如歐氏距離);也可以是不對稱的,即兩個資料點互相之間的相似度不等

python實現簡單的kmeans演算法

問題描述:一堆二維資料,用kmeans演算法對其進行聚類,下面例子以分k=3為例。 原資料: 1.5,3.1 2.2,2.9 3,4 2,1 15,25 43,13 32,42 0,0 8,9 12,5 9,12 11,8 22,33 24,25 實現程式碼: #codin

機器學習實戰——python實現SOM神經網路演算法

演算法基礎 SOM網路結構 輸入層:假設一個輸入樣本為X=[x1,x2,x3,…,xn],是一個n維向量,則輸入層神經元個數為n個。 輸出層(競爭層):通常輸出層的神經元以矩陣方式排列在二維空間中,每個神經元都有一個權值向量。 假設輸出層有m個神經元,則有m

利用python內建K-Means演算法實現鳶尾花資料的

在進去聚類情況分析前,我們需要為我們的IDLE安裝sklearn庫,scikit-learn是Python的一個開源機器學習模組,它建立在NumPy,SciPy和matplotlib模組之上能夠為使用者提供各種機器學習演算法介面,可以讓使用者簡單、高效地進行資料探勘和資料分析

【無監督學習】3:Density Peaks演算法實現(區域性密度演算法

前言:密度峰聚類演算法和DBSCAN聚類演算法有相似的地方,兩者都是基於密度的聚類方式。自己是在學習無監督學習過程中,無意間見到介紹這種聚類演算法的文章,感覺密度峰聚類演算法方法很新奇,操作也很簡答,於是自己也動手寫一下了。 –—-—-—-—-—-—-—-—-

Matlab實現簡單K-means演算法

K-means演算法簡要思想: 演算法接受引數 k ;然後將事先輸入的n個數據物件劃分為 k個聚類以便使得所獲得的聚類滿足:同一聚類中的物件相似度較高;而不同聚類中的物件相似度較小。 (1)適當選擇k個類的初始中心; (2)在第k次迭代中,對任意一個樣本,求其

python實現mean-shift演算法

新建MeanShift.py檔案 import numpy as np # 定義 預先設定 的閾值 STOP_THRESHOLD = 1e-4 CLUSTER_THRESHOLD = 1e-1 # 定義度量函式 def distance(a, b):

看完這篇文章,包你懂得如何用Python實現演算法的層次演算法

什麼是聚類 將物理或抽象物件的集合分成由類似的物件組成的多個類的過程被稱為聚類。由聚類所生成的簇是一組資料物件的集合,這些物件與同一個簇中的物件彼此相似,與其他簇中的物件相異。聚類分析又稱群分析,它是研究(樣品或指標)分類問題的一種統計分析方法。   聚類分析起源於分類學,但是聚

k-medoid(k中心點)演算法Python實現

k-means演算法有個很大的缺點,就是對孤立點敏感性太高,孤立點即是脫離群眾的點,與眾不同的點,即在顯示中與其他點不是抱在一團的點。 為了體現兩者的不同,我特意溫習了一下知識,在構造初始點的時候,自己定義加入了幾個孤立點,使用k-means演算法跑的效果如下: 一開始的所有點:(可以看出其

Python實現K-Means演算法

       宣告:程式碼的執行環境為Python3。Python3與Python2在一些細節上會有所不同,希望廣大讀者注意。本部落格以程式碼為主,程式碼中會有詳細的註釋。相關文章將會發布在我的個人部落格專欄《Python從入門到深度學習》,歡迎大家關注~

層次演算法的原理及python實現

層次聚類(Hierarchical Clustering)是一種聚類演算法,通過計算不同類別資料點間的相似度來建立一棵有層次的巢狀聚類樹。在聚類樹中,不同類別的原始資料點是樹的最低層,樹的頂層是一個聚類的根節點。 聚類樹的建立方法:自下而上的合併,自上而下的分裂。(這裡介紹第一種) 1.2 層次聚類的合

演算法——python實現SOM演算法

演算法簡介 SOM網路是一種競爭學習型的無監督神經網路,將高維空間中相似的樣本點對映到網路輸出層中的鄰近神經元。 訓練過程簡述:在接收到訓練樣本後,每個輸出層神經元會計算該樣本與自身攜帶的權向量之間的距離,距離最近的神經元成為競爭獲勝者,稱為最佳匹配單元。然

K-means和PAM演算法Python實現及對比

K-means(K均值劃分)聚類:簡單的說,一般流程如下:先隨機選取k個點,將每個點分配給它們,得到最初的k個分類;在每個分類中計算均值,將點重新分配,劃歸到最近的中心點;重複上述步驟直到點的劃歸不再改變。下圖是K-means方法的示意。 PAM

——譜演算法以及Python實現

譜聚類(spectral cluster)可以視為一種改進的Kmeans的聚類演算法。常用來進行影象分割。缺點是需要指定簇的個數,難以構建合適的相似度矩陣。優點是簡單易實現。相比Kmeans而言,處理高維資料更合適。 核心思想 構建樣本點的相似度矩陣(圖

python K-Means演算法實現

K-Means 簡介 聚類演算法有很多種(幾十種),K-Means是聚類演算法中的最常用的一種,演算法最大的特點是簡單,好理解,運算速度快,但是一定要在聚類前需要手工指定要分成幾類。 具體實現步驟如下: 給定n個訓練樣本{x1,x2,x3,…,xn}  

鳶尾花三種演算法(K-means,AGNES,DBScan)的python實現

一.分散性聚類(kmeans) 演算法流程: 1.選擇聚類的個數k. 2.任意產生k個聚類,然後確定聚類中心,或者直接生成k箇中心。 3.對每個點確定其聚類中心點。 4.再計算其聚類新中心。 5.重複以上步驟直到滿足收斂要求。(通常就是確定的中心點不再改變。

Kmeans演算法python下的實現--附測試資料

Kmeans演算法 1:隨機初始化一個聚類中心 2:根據距離將資料點劃分到不同的類中 3:計算代價函式 4:重新計算各類資料的中心作為聚類中心 5:重複2-4步直到代價函式不發生變化 測試資料: XY -1.260.46 -1.150.49 -1.190.36 -1.330

文字演算法之一趟(One-pass Cluster)演算法python實現

一、演算法簡介 一趟聚類演算法是由蔣盛益教授提出的無監督聚類演算法,該演算法具有高效、簡單的特點。資料集只需要遍歷一遍即可完成聚類。演算法對超球狀分佈的資料有良好的識別,對凸型資料分佈識別較差。一趟聚類可以在大規模資料,或者二次聚類中,或者聚類與其他演算法結合的情況下,發

機器學習經典演算法 —— k-均值演算法(附python實現程式碼及資料集)

目錄 工作原理 python實現 演算法實戰 對mnist資料集進行聚類 小結 附錄 工作原理 聚類是一種無監督的學習,它將相似

【機器學習】:Kmeans均值演算法原理(附帶Python程式碼實現)

這個演算法中文名為k均值聚類演算法,首先我們在二維的特殊條件下討論其實現的過程,方便大家理解。 第一步.隨機生成質心 由於這是一個無監督學習的演算法,因此我們首先在一個二維的座標軸下隨機給定一堆點,並隨即給定兩個質心,我們這個演算法的目的就是將這一堆點根據它們自身的座標特徵分為兩類,因此選取了兩個質心,什麼時