Affinity Propagation算法的python实现和分析

Affinity Propagation 算法更新方式很简单就是 更新 r矩阵在更新a矩阵

公式如下:

其中 s是相似度矩阵 一般直接可以采用距离来表示相似度

r 表示吸引度  a归属度

这里就用选举来进行形象讲解下

对于公式1

就好比是一个投票阶段  s(i, k)表示i 选k作为总统(聚类中心)的合适度    用r(i, k) 表示选k作为总统的意向有多大

直观来说  直接用r(i, k) =  s(i, k) -  max(s(i, k'))      k' != k     貌似更加形象,但是人是感性动物,会受别人影响,这里就是a起到的作用,比如 i 的亲人朋友都投了k'当总统,就会来问我你要不要和我们一样投k',  大家都在投k', 你也快点投k'。然后我经过深思熟虑 最终投给k的意向会受到影响(影响的大小取决于a(i, k')的大小)。所以  r(i, k) =  s(i, k) -  max{s(i, k') + a(i, k')}  最终我投给k的意向 

对于公式2

就像是一个拉票,a(i, k)表示形象理解为k对i的影响力而他的大小受k对其他i'的影响力,如果亲人朋友 i' 都投了k, 对于i来说就有很大概率也投k,这就是所谓的随波逐流。越多i'投k, a(i, k)就会也大,也就是说k对i的影响力越大,对于公式1起到的影响就越大。这里加上r(k, k)也很好理解,我自己对自己也有个投票意向,虽然大家都投了我,但是我自己这一票肯定还是要算计来的,万一比别人就差这一票不是亏大了。

迭代停止的条件就是所有的样本的聚类中心都不在变化为止,或者迭代了n次都还没有变化(n的值可以自己取)。

代码如下:

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

centers = [[1, 1], [-1, -1], [1, -1]]
X, labels_true = make_blobs(n_samples=300, centers=centers, cluster_std=0.4,
                            random_state=0)


def calc_similarity(X):
    m, n = np.shape(X)
    X_copy = np.copy(X)
    X = X.reshape((m, 1, n))
    X_copy = X_copy.reshape(1, m, n)
    sum = np.sum(np.square(X[..., :] - X_copy[..., :]), axis=-1)
    similarity = -1 * np.sqrt(sum)
    median_value = calc_median(similarity)
    for i in range(m):
        # preference设置 非对角线元素中值
        similarity[i, i] = median_value
    return similarity


def calc_median(X):
    data = []
    for i in range(len(X)):
        x = X[i]
        x = np.delete(x, i)
        data += list(x)
    n = len(data)
    return data[n // 2]


def affinityPropagation(similarity, lamda=0.):
    # 定义吸引度矩阵和归属感矩阵
    r = np.zeros_like(similarity, dtype=np.int32)
    a = np.zeros_like(similarity, dtype=np.int32)

    m, n = np.shape(similarity)

    last_change = np.zeros((m, ), dtype=np.int32)
    while True:
        # update r matrix
        for idx in range(m):
            a_s_idx = a[idx] + similarity[idx]
            for idy in range(n):
                a_s_idx_del = np.delete(a_s_idx, idy)
                max_value = np.max(a_s_idx_del)
                r_new = similarity[idx, idy] - max_value
                r[idx][idy] = lamda * r[idx][idy] + (1 - lamda) * r_new
        # update a matrix
        for idx in range(m):
            for idy in range(n):
                r_idy = r[:, idy]
                r_idy = np.delete(r_idy, idx)
                a_new = np.sum(np.maximum(0, r_idy))
                if idx != idy:
                    a_new = min(0, r[idy, idy] + a_new)
                a[idx][idy] = lamda * a[idx][idy] + (1 - lamda) * a_new
        r_a = r + a
        # 当聚类中心不再发生变化时停止
        argmax = np.argmax(r_a, axis=1)
        current_change = argmax
        if (last_change == current_change).all():
            break
        last_change = current_change
    print('r', r)
    print('a', a)
    return r + a


def computeCluster(fitable, data):
    clusters = {}
    num = len(fitable)
    for idx in range(num):
        fit = fitable[idx]
        argmax = np.argmax(fit, axis=-1)
        if argmax not in clusters:
            clusters[argmax] = []
        clusters[argmax].append(tuple(data[idx]))
    return clusters


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


similarity = calc_similarity(X)
fitable = affinityPropagation(similarity, lamda=0.25)
clusters = computeCluster(fitable, X)
print(len(clusters))
plotClusters(clusters, "clusters by affinity propagation")

结果如下图:

与君共勉~

### Affinity Propagation 算法及其在 Iris 数据集中的实现 Affinity Propagation 是一种聚类算法,其核心思想是通过消息传递机制来识别数据集中具有代表性的样本作为簇中心。该方法不需要预先指定簇的数量,而是基于输入的数据相似度矩阵自动推断最佳的簇数[^1]。 #### 1. **Affinity Propagation 的基本原理** Affinity Propagation 使用两个主要的消息类型来进行迭代计算:责任(responsibility)可用性(availability)。 - 责任 $ r(i, k) $ 表示节点 $ i $ 将节点 $ k $ 视为其 exemplar 的合适程度。 - 可用性 $ a(i, k) $ 表示节点 $ k $ 成为其他节点 exemplar 的适合程度。 这些消息通过更新规则不断调整,直到收敛到稳定的簇分配状态[^3]。 #### 2. **Iris 数据集简介** Iris 数据集是一个经典的机器学习数据集,包含 150 条记录,每条记录有四个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度),以及三个类别标签(Setosa、Versicolor Virginica)。由于其简单性广泛的应用场景,它常被用于测试各种分类聚类算法的效果[^2]。 #### 3. **Python 实现** 以下是使用 Python 中 `sklearn` 库实现 Affinity Propagation 并应用于 Iris 数据集的一个例子: ```python from sklearn.datasets import load_iris from sklearn.cluster import AffinityPropagation import numpy as np import matplotlib.pyplot as plt # 加载 Iris 数据集 data = load_iris() X = data.data # 创建并训练 Affinity Propagation 模型 ap_model = AffinityPropagation(damping=0.9, max_iter=200, convergence_iter=15, preference=-50).fit(X) # 获取聚类结果 cluster_centers_indices = ap_model.cluster_centers_indices_ labels = ap_model.labels_ n_clusters_ = len(cluster_centers_indices) print(f'Estimated number of clusters: {n_clusters_}') # 绘制聚类结果 plt.figure(figsize=(8, 6)) colors = ['navy', 'turquoise', 'darkorange'] 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, 2], X[class_members, 3], '.', color=col) plt.plot(cluster_center[2], cluster_center[3], '+', markerfacecolor=col, markeredgecolor='k', markersize=14) for x in X[class_members]: plt.plot([cluster_center[2], x[2]], [cluster_center[3], x[3]], col) plt.title('Affinity Propagation Clustering on Iris Dataset') plt.xlabel(data.feature_names[2]) plt.ylabel(data.feature_names[3]) plt.show() ``` 上述代码展示了如何加载 Iris 数据集,并利用 `AffinityPropagation` 类完成聚类分析。最终的结果可以通过可视化展示不同簇之间的分布情况。 #### 4. **参数调优** Affinity Propagation 的性能高度依赖于几个关键超参数的选择: - `preference`: 控制每个点成为 exemplar 的倾向,默认值通常设置为数据点间平均相似度。 - `damping`: 防止数值振荡的阻尼系数,取值范围为 `[0.5, 1)`,推荐值为 0.9 左右。 通过对这些参数进行合理调节,可以显著提升模型的表现效果。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值