谱聚类算法介绍

基本介绍

谱聚类(Spectral Clustering)是一种基于图论的无监督聚类算法。它通过将数据集表示为图的形式,并利用图的谱特征进行聚类分析。谱聚类算法在图论和线性代数的基础上建立起来,具有较好的聚类性能和理论保证。

图论基础

既然该算法是基于图论的算法,那么要了解谱聚类算法,首先就要学习图的基本概念

图是一种几何结构。图G由顶点(Node)和边(Edge)构成,通常将顶点的集合记为V,边的集合记为E。边由它连接的起点和终点表示。下图是一个典型的图。

上图中的图G=(V,E)有7个顶点、7条边。顶点的集合为

                                                        V=\left \{ 1,2,3,4,5,6,7 \right \}

边的集合为

                                E=\left \{(1,2), (1,6),(2,3),(2,4),(3,4),(4,5),(4,7) \right \}

图的边可能带有权重,表示两个顶点之间的某种信息,例如两点之间的路线长度。通常情况下,边的权重值表示顶点之间的距离或相似度。对于前者,权重越大说明两个顶点之间距离越远;对于后者,权重越大则说明两个顶点之间的联系越紧密。如不作特殊说明,均认为边的权重是正数。

如果图的边是无向的,则称图为无向图;如果边是有向的,则称图为有向图

对于顶点的度(Degree)定义为与其有相关边的数量。如上图顶点2的度d_{i=2} = 3,因为它与边(1,2),(2,3),(2,4)相关。

对于顶点的加权度定义为与其有相关边的权重和。如上图顶点2的加权度为w=2+4+3=9


邻接矩阵(Adjacent Matrix)是图的矩阵表示,借助它可以方便地存储图的结构,并用线性代数的方法解决图的问题。
如果图有n个顶点,则其邻接矩阵Wn \times n的矩阵,矩阵元素w_{ij},;表示边(i,j)的权重。如果两个顶点之间没有边连接,则在邻接矩阵中对应的元素为0

上图的邻接矩阵

 加权度矩阵D是一个对角矩阵,其主对角线元素为每个顶点的加权度,其他位置的元素为0。即

                                                             d_{i}=\sum_{j=1}^{n}w_{ij}

上图的加权度矩阵

 有了上述理论后我们可以引出拉普拉斯(Laplace)矩阵

拉普拉斯(Laplace)矩阵即为加权度矩阵(D)与邻接矩阵(W)之差

                                                           L = D-W

了解完图的基本概念后,我们边可以学习谱聚类算法

下面是谱聚类算法的详细介绍:

  1. 构建相似度矩阵(Affinity Matrix): 首先,根据给定的数据集,计算每个样本之间的相似度或距离。常用的相似度度量包括高斯核函数、欧氏距离、余弦相似度等。将相似度或距离构建成一个相似度矩阵,其中每个元素表示对应样本之间的相似度。

  2. 构建拉普拉斯矩阵(Laplacian Matrix): 将相似度矩阵进行归一化处理,得到归一化的相似度矩阵。然后,通过计算度矩阵(Degree Matrix)和邻接矩阵(Adjacency Matrix)之间的差值,得到拉普拉斯矩阵。拉普拉斯矩阵有多种形式,包括无向图的拉普拉斯矩阵和对称归一化的拉普拉斯矩阵等。

  3. 特征值分解(Eigenvalue Decomposition): 对拉普拉斯矩阵进行特征值分解,得到其特征值和对应的特征向量。通常情况下,选择前k个最小的非零特征值对应的特征向量作为聚类的输入。

  4. 聚类操作: 将特征向量构建成一个新的矩阵,然后使用传统的聚类算法(如k-means)对新矩阵进行聚类操作。常用的方法是将特征向量作为数据样本,然后使用k-means算法将其分为k个簇。

  5. 输出聚类结果: 将聚类操作得到的簇标签作为最终的聚类结果。

在计算边的权值时我们可采用 ϵ邻近法、k近邻法、全连接法。

具体介绍可参考此篇谱聚类算法原理

谱聚类算法代码展示: 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans


def distance(x, y):
    return np.linalg.norm(x-y)

def getDistanceMatrix(data):
    # 计算距离矩阵
    N, D = data.shape
    dists = np.zeros([N, N])
    for i in range(N):
        for j in range(N):
            dists[i, j] = distance(data[i,:], data[j,:])
    return dists

def get_WeightMatrix(dists, eps=2, sigma=1):
    """
    计算邻接矩阵
    计算边的权重: 此处采用的是"全连接法"
    使用的是Gaussion核函数: w(ij) = exp[-(xi-xj)^2/2*eps^2]
    :param dists: 欧式距离矩阵
    :param eps: 高斯核函数的参数
    :param sigma: 高斯核函数的参数
    :return: 返回一个邻接矩阵
    """
    N, D = dists.shape
    W = np.zeros([N, N])
    for i in range(N):
        for j in range(N):
            if i != j and dists[i,j] < eps:
                W[i, j] = np.exp(-dists[i,j]**2/(sigma**2))
    return W

def get_DgreeMatrix(W):
    # 计算点的加权度
    # 点的  度:与其相关边的数量
    # 点的  加权度:与其相关边的权重的和
    N, D = W.shape
    D = np.zeros([N, N])
    for i in range(N):
        D[i, i] = np.sum(W[i,:])
    return D

def spectral(data, k):
    N, D = data.shape
    dists = getDistanceMatrix(data)
    W = get_WeightMatrix(dists)
    D = get_DgreeMatrix(W)
    L = D - W       # Laplace Matrix 拉普拉斯矩阵
    eigvals, eigvecs = np.linalg.eig(L)     # 计算特征值和对应的特征向量
    # 取特征值最小的k个特征向量
    selected_eigvecs = eigvecs[:, np.argsort(eigvals)[:k]]
    # 将所取的特征向量组成的矩阵看做一个若干个数据点
    # 应用kmeans算法对这些数据点进行聚类,对应的标签就是原数据聚类的标签
    kmeans = KMeans(n_clusters=k)
    kmeans.fit(selected_eigvecs)
    labels = kmeans.labels_
    return labels

导入数据

data = np.loadtxt(r"data.txt")
labels = spectral(data, 7)

聚类结果展示

(部分数据,没有调参)

部分参考  雷明——《机器学习的数学》 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值