机器学习中的亲和传播 |查找集群的数量
Affinity Propagation 通过在数据点之间发送消息直到收敛来创建集群。与 k-means 或 k-medoids 等聚类算法不同,亲和力传播不需要在运行算法之前确定或估计聚类的数量,为此,两个重要的参数是偏好,它控制有多少样本(或原型),以及抑制消息的责任和可用性的阻尼因子,以避免在更新这些消息时出现数值振荡。
使用少量示例描述数据集,“示例”是代表集群的输入集的成员。对之间发送的消息表示一个样本是否适合作为另一个样本的样本,该样本会根据其他对的值进行更新。这种更新迭代地发生直到收敛,此时选择了最终的样本,因此我们获得了最终的聚类。亲和传播算法:
输入:给定一个数据集 D = {d1, d2, d3, .....dn}
s是一个 NxN 矩阵,使得s(i, j)
表示 d i和 d j之间的相似性。两个数据点的负平方距离用作点xi和xj的 s ie , s(i, j)= -||x i -x j || 2
.
s 即s(i, i)的对角线特别重要,因为它代表了输入偏好,这意味着特定输入成为样本的可能性有多大。当它为所有输入设置为相同的值时,它控制算法产生多少类。接近最小可能相似度的值产生较少的类,而接近或大于最大可能相似度的值产生许多类。它通常被初始化为所有输入对的中值相似度。
该算法通过交替两个消息传递步骤来更新两个矩阵:
- “责任”矩阵 R 的值 r(i, k) 量化了 x k作为 x i的示例相对于 x i的其他候选示例的适合程度。
- “可用性”矩阵 A 包含值 a(i, k),表示 x i选择 x k作为其样本有多“合适”,同时考虑到其他点对 x k作为样本的偏好。
两个矩阵都初始化为全零。然后该算法迭代地执行以下更新:
- 一、责任更新四处发送
- 然后,可用性更新每
执行迭代直到集群边界在多次迭代中保持不变,或者在某个预定数量的迭代之后。样本是从最终矩阵中提取的,它们的“责任+可用性”对自己是积极的(即(r(i, i) + a(i, i)) > 0
)。
下面是使用 scikit-learn 库的 Affinity Propagation 聚类的Python实现:
from sklearn.cluster import AffinityPropagation
from sklearn import metrics
from sklearn.datasets.samples_generator import make_blobs
# Generate sample data
centers = [[1, 1], [-1, -1], [1, -1], [-1, -1]]
X, labels_true = make_blobs(n_samples = 400, centers = centers,
cluster_std = 0.5, random_state = 0)
# Compute Affinity Propagation
af = AffinityPropagation(preference =-50).fit(X)
cluster_centers_indices = af.cluster_centers_indices_
labels = af.labels_
n_clusters_ = len(cluster_centers_indices)
# Plot result
import matplotlib.pyplot as plt
from itertools import cycle
plt.close('all')
plt.figure(1)
plt.clf()
colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
class_members = labels == k
cluster_center = X[cluster_centers_indices[k]]
plt.plot(X[class_members, 0], X[class_members, 1], col + '.')
plt.plot(cluster_center[0], cluster_center[1], 'o',
markerfacecolor = col, markeredgecolor ='k',
markersize = 14)
for x in X[class_members]:
plt.plot([cluster_center[0], x[0]],
[cluster_center[1], x[1]], col)
plt.title('Estimated number of clusters: % d' % n_clusters_)
plt.show()
输出: