LogoLogo
  • README
  • 前端编程
    • 01 Node JS
    • 02-ES6详解
    • 03-NPM详解
    • 04-Babel详解
    • 05-前端模块化开发
    • 06-WebPack详解
    • 07-Vue详解
    • 08-Git详解
    • 09-微信小程序
  • 人工智能
    • 机器学习
      • 二次分配问题
      • 非负矩阵
      • 概率潜在语义分析
      • 概率图模型
      • 集成学习
      • 降维
      • 距离度量
      • 决策树
      • 逻辑回归
      • 马尔可夫决策过程
      • 马尔可夫链蒙特卡洛法
      • 朴素贝叶斯法
      • 谱聚类
      • 奇异值分解
      • 潜在狄利克雷分配
      • 潜在语义分析
      • 强化学习
      • 社区算法
      • 时间序列模型
      • 特征工程
      • 条件随机场
      • 图论基础
      • 线性分类
      • 线性回归
      • 信息论中的熵
      • 隐马尔科夫模型
      • 支持向量机
      • 主成分分析
      • EM算法
      • Hermite 矩阵的特征值不等式
      • k-means聚类
      • k近邻法
      • PageRank算法
    • 深度学习
      • Pytorch篇
        • 01-线性模型
        • 02-梯度下降法
        • 03-反向传播
        • 04-pytorch入门
        • 05-用pytorch实现线性回归
        • 06-logistic回归
        • 07-处理多维特征的输入
        • 08-加载数据集
        • 09-多分类问题
        • 10-卷积神经网络
        • 11-循环神经网络
    • 图神经网络
      • 图神经网络笔记01
        • 01-图(Graphs)的结构
        • 02-网络的性质和随机图模型
        • 03-网络工具
        • 04-网络中的主题和结构角色
        • 05-网络中的社区结构
      • 图神经网络笔记02
        • 01-深度学习引言
        • 02-神经网络基础
        • 03-卷积神经网络
        • 04-图信号处理与图卷积神经网络
        • 05-GNN的变体与框架-
        • [06-Google PPRGo 两分钟分类千万节点的最快GNN](人工智能/图神经网络/图神经网络笔记02/06-Google%20PPRGo 两分钟分类千万节点的最快GNN.md)
        • 07-序列模型
        • 08-变分自编码器
        • 09-对抗生成网络
  • 日常记录
    • 健身日记
    • 面经记录
    • 自动生成Summary文件
  • 实战项目
    • 谷粒商城
      • 00-项目概述
      • 01-分布式基础-全栈开发篇
      • 02-分布式高级-微服务架构篇
      • 03-高可用集群-架构师提升篇
  • 数据库
    • MySQL笔记
      • 01-MySQL基础篇
      • 02-MySQL架构篇
      • 03-MySQL索引及调优篇
      • 04-MySQL事务篇
      • 05-MySQL日志与备份篇
    • Redis笔记
      • 01-Redis基础篇
      • 02-Redis高级篇
    • 02-Redis篇
  • 算法笔记
    • 01-算法基础篇
    • 02-算法刷题篇
  • 职能扩展
    • 产品运营篇
  • Go编程
    • 01-Go基础
      • 01-Go基础篇
  • Java编程
    • 01-Java基础
      • 01-Java基础篇
      • 02-多线程篇
      • 03-注射与反解篇
      • 04-JUC并发编程篇
      • 05-JUC并发编程与源码分析
      • 06-JVM原理篇
      • 07-Netty原理篇
      • 08-设计模式篇
    • 02 Java Web
      • 01-Mybatis篇
      • 01-Mybatis篇(新版)
      • 02-Spring篇
      • 02-Spring篇(新版)
      • 03-SpringMVC篇
      • 04-MybatisPlus篇
    • 03-Java微服务
      • 01-SpringBoot篇
      • 01-SpringBoot篇(新版)
      • 02-SpringSecurity篇
      • 03-Shiro篇
      • 04-Swagger篇
      • 05-Zookeeper篇
      • 06-Dubbo篇
      • 07-SpringCloud篇
      • 08-SpringAlibaba篇
      • 09-SpringCloud篇(新版)
    • 04-Java中间件
      • 数据库篇
        • 01-分库分表概述
        • 02-MyCat篇
        • 03-MyCat2篇
        • 04-Sharding-jdbc篇
        • 05-ElasticSearch篇
      • 消息中间件篇
        • 01-MQ概述
        • 02-RabbitMQ篇
        • 03-Kafka篇
        • 04-RocketMQ篇
        • 05-Pulsar篇
    • 05-扩展篇
      • Dubbo篇
      • SpringBoot篇
      • SpringCloud篇
    • 06-第三方技术
      • 01-CDN技术篇
      • 02-POI技术篇
      • 03-第三方支付技术篇
      • 04-第三方登录技术篇
      • 05-第三方短信接入篇
      • 06-视频点播技术篇
      • 07-视频直播技术篇
    • 07-云原生
      • 01-Docker篇
      • 02-Kubernetes篇
      • 03-Kubesphere篇
  • Linux运维
    • 01-Linux篇
    • 02-Nginx篇
  • Python编程
    • 01-Python基础
      • 01.配置环境
      • 02.流程控制
      • 03.数值
      • 04.操作符
      • 05.列表
      • 06.元祖
      • 07.集合
      • 08.字典
      • 09.复制
      • 10.字符串
      • 11.函数
      • 12.常见内置函数
      • 13.变量
      • 14.异常和语法错误
      • 15.时间和日期
      • 16.正则表达式
    • 02 Python Web
      • flask篇
        • 01.前言
        • 02.路由
        • 03.模板
        • 04.视图进阶
        • 05.flask-sqlalchemy
        • 06.表单WTForms
        • 07.session与cookie
        • 08.上下文
        • 09.钩子函数
        • 10.flask 信号
        • 11.RESTFUL
        • 13.flask-mail
        • 14.flask+celery
        • 15.部署
        • 16.flask-login
        • 17.flask-cache
        • 18.flask-babel
        • 19.flask-dashed
        • 20.flask-pjax
        • 21.flask上传文件到第三方
        • 22.flask-restless
        • 23.flask-redis
        • 24.flask-flash
        • 25.消息通知
        • 26.分页
    • 03-Python数据分析
      • Matplotlib
      • Numpy
      • Pandas
      • Seaborn
    • 04-Python爬虫
      • 1.准备工作
      • 2.请求模块的使用
      • 3.解析模块的使用
      • 4.数据存储
      • 5.识别验证码
      • 6.爬取APP
      • 7.爬虫框架
      • 8.分布式爬虫
由 GitBook 提供支持
在本页
  • 基本概念
  • 相似矩阵
  • 拉普拉斯矩阵
  • 由图分割问题到谱聚类问题
  • 谱聚类实现

这有帮助吗?

在GitHub上编辑
  1. 人工智能
  2. 机器学习

谱聚类

上一页朴素贝叶斯法下一页奇异值分解

最后更新于3年前

这有帮助吗?

基本概念

定义无向图$G={V,E,W}$,其中,$V$为图的顶点,$E$为图的边,$W$为图中边的权值矩阵。

定义顶点的度为该顶点与其他顶点连接权值之和:

di=∑j=1Nwijd_i = \sum_{j=1}^N w_{ij}di​=j=1∑N​wij​

度矩阵$D$为:

D=[d1d2⋱dN]D = \left [ \begin{matrix} d_1&&& \\ &d_2&& \\ &&\ddots& \\ &&&&d_N \end{matrix} \right ]D=​d1​​d2​​⋱​​dN​​​

图的邻接矩阵(相似矩阵)$W$:

W=[wij],1≤i,j≤NW=[w_{ij}],1\leq i,j\leq NW=[wij​],1≤i,j≤N

对于$V$的一个子集$A\subset V$:

V=∪k=1KAkAi∩Aj=⊘,∀i,j∈{1,2,⋯ ,N}vol(A)=∑i∈Adi\begin{align} &V = \cup_{k=1}^K A_k\\ &A_i \cap A_j = \oslash,\forall i,j \in \{1,2,\cdots,N\} \\ &vol(A) = \sum_{i\in A} d_i \end{align}​V=∪k=1K​Ak​Ai​∩Aj​=⊘,∀i,j∈{1,2,⋯,N}vol(A)=i∈A∑​di​​​

相似矩阵

邻接矩阵$W$:由任意两点之间的权重值$w_{ij}$组成的矩阵。通常手动输入权重,但是在谱聚类中,只有数据点的定义,并没有直接给出这个邻接矩阵,那么如何构造邻接矩阵?

基本思想:距离较远的两个点之间的边权重值较低,而距离较近的两个点之间的边权重值较高,不过这仅仅是定性,需要定量的权重值。一般来说,我们可以通过样本点距离度量的相似矩阵$S$来获得邻接矩阵$W$。

构造方法:这里采用全连接法进行构造邻接矩阵。可以采用不同的核函数来定义边权重,这里采用高斯核函数RBF:

W_{ij} = S_{ij} = \left \{ \begin{array}{**lr**} exp(-\frac{||x_i-x_j||^2_2}{2\sigma^2}),& (i,j) \in E \\ 0,otherwise.& \end{array} \right.

拉普拉斯矩阵

拉普拉斯矩阵定义:

L=D−WL = D - WL=D−W

其中,$D$为度矩阵,$W$为邻接矩阵。

拉普拉斯矩阵的性质:

  1. 拉普拉斯矩阵是对称矩阵,其所有特征值都是实数

  2. 对于任意向量$f$,有:

fTLf=12∑i,j=1nwij(fi−fj)2f^TLf = \frac{1}{2} \sum_{i,j=1}^n w_{ij}(f_i-f_j)^2fTLf=21​i,j=1∑n​wij​(fi​−fj​)2

​ 于是,可以得知:

fTLf=fTDf−fTWf=∑i=1Ndifi2−∑i,j=1Nwijfifj=12(∑i=1Ndifi2−2∑i,j=1Nwijfifj+∑j=1Ndjfj2)=12∑i,j=1Nwij(fi−fj)2\begin{align} f^TLf &= f^TDf - f^TWf \\ &= \sum_{i=1}^N d_i f_i^2 - \sum_{i,j=1}^N w_{ij}f_if_j \\ &= \frac{1}{2}(\sum_{i=1}^N d_i f_i^2 - 2\sum_{i,j=1}^N w_{ij}f_if_j+\sum_{j=1}^N d_j f_j^2) \\ &= \frac{1}{2}\sum_{i,j=1}^N w_{ij}(f_i-f_j)^2 \end{align}fTLf​=fTDf−fTWf=i=1∑N​di​fi2​−i,j=1∑N​wij​fi​fj​=21​(i=1∑N​di​fi2​−2i,j=1∑N​wij​fi​fj​+j=1∑N​dj​fj2​)=21​i,j=1∑N​wij​(fi​−fj​)2​​
  1. 拉普拉斯矩阵是半正定的,且对应的n个实数特征值都大于等于0$(0=\lambda_1\leq \lambda_2 \leq \cdots \leq \lambda_N)$,且最小的特征值为0,对应的特征向量是单位向量。

由图分割问题到谱聚类问题

对于无向图$G$的切割图,目标是将图$G$切分成相互没有连接的$k$个子图,每个子图点的集合为:

V=∪k=1KAkAi∩Aj=⊘,∀i,j∈{1,2,⋯ ,N}\begin{align} &V = \cup_{k=1}^K A_k\\ &A_i \cap A_j = \oslash,\forall i,j \in \{1,2,\cdots,N\} \\ \end{align}​V=∪k=1K​Ak​Ai​∩Aj​=⊘,∀i,j∈{1,2,⋯,N}​​

对于任意两个子图点的集合$A,B \subset V,A\cap B = \oslash$,定义$A$和$B$之间的切图之间的权重为:

W(A,B)=∑i∈A,j∈BwijW(A,B) = \sum_{i\in A,j\in B} w_{ij}W(A,B)=i∈A,j∈B∑​wij​

对于k个子图点的集合,定义切图$cut$为:

cut(V)=cut(A1,A2,⋯ ,Ak)=∑k=1KW(Ak,Akˉ)=∑k=1KW(Ak,V)−W(Ak,Ak)\begin{align} cut(V) &= cut(A_1,A_2,\cdots,A_k) \\ &= \sum_{k=1}^K W(A_k,\bar{A_k}) \\ &= \sum_{k=1}^K W(A_k,V) - W(A_k,A_k) \end{align}cut(V)​=cut(A1​,A2​,⋯,Ak​)=k=1∑K​W(Ak​,Ak​ˉ​)=k=1∑K​W(Ak​,V)−W(Ak​,Ak​)​​

其中,$\bar{A_i}$为$A_i$的补集(除去$A_i$子集以外其他的属于$V$的结点的集合)。

为了让切图可以让子图内的点权重和高(内部连接强),子图间的点权重和低(外部连接弱),需要使$cut$达到最小化。

优化目标:

max{Ak}k=1Kcut(V)=∑i=1KW(Ai,Aiˉ)\begin{align} \mathop{max}\limits_{\{A_k\}^K_{k=1}} cut(V) = \sum\limits_{i=1}^K W(A_i,\bar{A_i}) \end{align}{Ak​}k=1K​max​cut(V)=i=1∑K​W(Ai​,Ai​ˉ​)​​

为了避免最小切图导致的切图效果不佳,需要对每个子图的规模做出限定。这里得到了一个新的优化目标:

Ncut(A1,A2,⋯ ,Ak)=12∑i=1KW(Ai,Aiˉ)vol(Ai)=12∑i=1KW(Ai,Aiˉ)∑i∈Akdi,di=∑j=1NwijNcut(A_1,A_2,\cdots,A_k) = \frac{1}{2} \sum\limits_{i=1}^K \frac{W(A_i,\bar{A_i})}{vol(A_i)} = \frac{1}{2} \sum\limits_{i=1}^K \frac{W(A_i,\bar{A_i})}{\sum\limits_{i\in A_k}d_i},d_i=\sum_{j=1}^Nw_{ij}Ncut(A1​,A2​,⋯,Ak​)=21​i=1∑K​vol(Ai​)W(Ai​,Ai​ˉ​)​=21​i=1∑K​i∈Ak​∑​di​W(Ai​,Ai​ˉ​)​,di​=j=1∑N​wij​

由上可知,算法的目标函数为:

{Ak^}k=1K=argmin{Ak}k=1K∑k=1KW(Ak,v)−W(Ak,AK)∑i∈Ak∑j=1Nwij\{\hat{A_k} \}_{k=1}^K = \mathop{argmin}_{\{A_k\}^K_{k=1}} \sum\limits_{k=1}^K\frac{W(A_k,v)-W(A_k,A_K)}{\sum\limits_{i\in A_k}\sum\limits_{j=1}^Nw_{ij}}{Ak​^​}k=1K​=argmin{Ak​}k=1K​​k=1∑K​i∈Ak​∑​j=1∑N​wij​W(Ak​,v)−W(Ak​,AK​)​

由于求解的时候,不方便计算,于是设法将目标函数转换为矩阵的形式表达。

引入指示向量

令

\left \{ \begin{array}{**lr**} y_i \in \{0,1\}^k,&\\ \sum\limits_{j=1}^K y_{ij} = 1,1 \leq i,j \leq N \end{array} \right.

其中,$y_i$是一个$k$维的向量,每一个维度的值为0或者1;$y_{ij}$表示第$i$个样本属于第$j$个类别,并且每个样本只能属于一个类别。

由上,可知目标函数为:

Y=(y1,y2,⋯ ,yN)N×KTY^=argminYNcut(V)=argminY∑k=1KW(Ak,Akˉ)∑i∈Akdi\begin{align} &Y = (y_1,y_2,\cdots,y_N)_{N\times K}^T \\ &\hat Y = \mathop{argmin}\limits_{Y} Ncut(V) = \mathop{argmin}\limits_Y \sum\limits_{k=1}^K \frac{W(A_k,\bar{A_k})}{\sum\limits_{i \in A_k}d_i} \end{align}​Y=(y1​,y2​,⋯,yN​)N×KT​Y^=Yargmin​Ncut(V)=Yargmin​k=1∑K​i∈Ak​∑​di​W(Ak​,Ak​ˉ​)​​​

又,

∑k=1KW(Ak,Akˉ)∑i∈Akdi=tr[W(A1,A1ˉ)∑i∈A1diW(A2,A2ˉ)∑i∈A2di⋱W(AK,AKˉ)∑i∈AKdi]=tr[W(A1,A1ˉ)W(A2,A2ˉ)⋱W(AK,AKˉ)]K×K⏟O⋅[[∑i∈A1di∑i∈A2di⋱∑i∈AKdi]K×K⏟P]−1=tr(OP−1)\begin{align} \sum\limits_{k=1}^K \frac{W(A_k,\bar{A_k})}{\sum\limits_{i \in A_k}d_i} &= tr \left [ \begin{matrix} \frac{W(A_1,\bar{A_1})}{\sum\limits_{i \in A_1}d_i}&&& \\ &\frac{W(A_2,\bar{A_2})}{\sum\limits_{i \in A_2}d_i}&& \\ &&\ddots& \\ &&&&\frac{W(A_K,\bar{A_K})}{\sum\limits_{i \in A_K}d_i} \end{matrix} \right ] \\ &= tr \underbrace{\left [ \begin{matrix} W(A_1,\bar{A_1})&&& \\ &W(A_2,\bar{A_2})&& \\ &&\ddots& \\ &&&&W(A_K,\bar{A_K}) \end{matrix} \right ]_{K\times K}}_{O} \cdot \left[\underbrace{\left [ \begin{matrix} \sum\limits_{i \in A_1}d_i&&& \\ &\sum\limits_{i \in A_2}d_i&& \\ &&\ddots& \\ &&&&\sum\limits_{i \in A_K}d_i \end{matrix} \right ]_{K\times K}}_{P}\right]^{-1} \\ = tr(OP^{-1}) \end{align}k=1∑K​i∈Ak​∑​di​W(Ak​,Ak​ˉ​)​=tr(OP−1)​=tr​i∈A1​∑​di​W(A1​,A1​ˉ​)​​i∈A2​∑​di​W(A2​,A2​ˉ​)​​⋱​​i∈AK​∑​di​W(AK​,AK​ˉ​)​​​=trO​W(A1​,A1​ˉ​)​W(A2​,A2​ˉ​)​⋱​​W(AK​,AK​ˉ​)​​K×K​​​⋅​P​i∈A1​∑​di​​i∈A2​∑​di​​⋱​​i∈AK​∑​di​​​K×K​​​​−1​​

现在已知$W$,$Y$,求$O$,$P$,注意$Y$矩阵是$N\times K$维的,行代表结点标号,列代表属于的类别,其中$y_{ij}$表示第$i$个样本属于第$j$个类别。

有,

yiyiT=[0,0,⋯ ,yij=1,⋯ ,0]⋅[00⋯yij=1⋯0]=[0⋯0⋯0⋮⋱⋮⋱⋮0⋯yjj=1⋯0⋮⋱⋮⋱⋮0⋯0⋯0]\begin{align} y_iy_i^T&= \left[\begin{matrix}0,0,\cdots,y_{ij}=1,\cdots,0\end{matrix}\right]\cdot \left[\begin{matrix}0\\0\\\cdots\\y_{ij}=1\\\cdots\\0\end{matrix}\right] \\ &= \left[ \begin{matrix} 0&\cdots&0&\cdots&0 \\ \vdots&\ddots&\vdots&\ddots&\vdots\\ 0&\cdots&y_{jj}=1&\cdots&0 \\ \vdots&\ddots&\vdots&\ddots&\vdots\\ 0&\cdots&0&\cdots&0 \\ \end{matrix} \right] \end{align}yi​yiT​​=[0,0,⋯,yij​=1,⋯,0​]⋅​00⋯yij​=1⋯0​​=​0⋮0⋮0​⋯⋱⋯⋱⋯​0⋮yjj​=1⋮0​⋯⋱⋯⋱⋯​0⋮0⋮0​​​​

于是,

YTY=(y1,y2,⋯ ,yN)⋅(y1T,y2T,⋯ ,yNT)=∑i=1NyiyiT=[N1N2⋱NK]K×K\begin{align} Y^TY &= (y_1,y_2,\cdots,y_N)\cdot (y_1^T,y_2^T,\cdots,y_N^T) \\ &=\sum\limits_{i=1}^N y_iy_i^T \\ &= \left[ \begin{matrix} N_1&&&&\\ &N_2&&&\\ &&\ddots&\\ &&&&N_K\\ \end{matrix} \right]_{K\times K} \end{align}YTY​=(y1​,y2​,⋯,yN​)⋅(y1T​,y2T​,⋯,yNT​)=i=1∑N​yi​yiT​=​N1​​N2​​⋱​​NK​​​K×K​​​

其中,$N_K$表示在$N$个样本中,属于类别$k$的样本个数,且$\sum\limits_{k=1}^KN_k = N$,$N_k = |A_k|=\sum\limits_{i\in A_k} 1_N$,$1_N$表示元素全为$1$的$N\times 1$维向量。

有,

P=∑i=1NyiTdiyi=YTDY=YT(W⋅1N)YP = \sum\limits_{i=1}^Ny_i^Td_iy_i = Y^TDY = Y^T(W\cdot1_N)YP=i=1∑N​yiT​di​yi​=YTDY=YT(W⋅1N​)Y

使用拉普拉斯矩阵的性质,简化$O$矩阵,如下:

O=[W(A1,A1ˉ)W(A2,A2ˉ)⋱W(AK,AKˉ)]=[W(A1,V)W(A2,V)⋱W(AK,V)]−[W(A1,A1)W(A2,A2)⋱W(AK,AK)]=[∑i∈A1di∑i∈A2di⋱∑i∈AKdi]−[W(A1,A1)W(A2,A2)⋱W(AK,AK)]\begin{align} O &= \left [ \begin{matrix} W(A_1,\bar{A_1})&&& \\ &W(A_2,\bar{A_2})&& \\ &&\ddots& \\ &&&&W(A_K,\bar{A_K}) \end{matrix} \right ] \\ &= \left [ \begin{matrix} W(A_1,V)&&& \\ &W(A_2,V)&& \\ &&\ddots& \\ &&&&W(A_K,V) \end{matrix} \right ] - \left [ \begin{matrix} W(A_1,A_1)&&& \\ &W(A_2,A_2)&& \\ &&\ddots& \\ &&&&W(A_K,A_K) \end{matrix} \right ] \\ &= \left [ \begin{matrix} \sum\limits_{i \in A_1} d_i&&& \\ &\sum\limits_{i \in A_2} d_i&& \\ &&\ddots& \\ &&&&\sum\limits_{i \in A_K} d_i \end{matrix} \right ] - \left [ \begin{matrix} W(A_1,A_1)&&& \\ &W(A_2,A_2)&& \\ &&\ddots& \\ &&&&W(A_K,A_K) \end{matrix} \right ] \\ \end{align}O​=​W(A1​,A1​ˉ​)​W(A2​,A2​ˉ​)​⋱​​W(AK​,AK​ˉ​)​​=​W(A1​,V)​W(A2​,V)​⋱​​W(AK​,V)​​−​W(A1​,A1​)​W(A2​,A2​)​⋱​​W(AK​,AK​)​​=​i∈A1​∑​di​​i∈A2​∑​di​​⋱​​i∈AK​∑​di​​​−​W(A1​,A1​)​W(A2​,A2​)​⋱​​W(AK​,AK​)​​​​

由于,

YTWT=[y1y2⋯yN][w11⋯w1N⋮⋱⋮wN1⋯wNN][y1Ty2T⋯yNT]=[∑i=1Ny1wi1∑i=1Ny2wi2⋯∑i=1NyNwiN][y1Ty2T⋯yNT]=∑i=1N∑j=1NyiwijyjT=∑i=1N∑j=1NyiyjTwij=[∑i∈A1,j∈A1wij∑i∈A1,j∈A2wij⋯∑i∈A1,j∈ANwij⋮⋮⋱⋮∑i∈AN,j∈A1wij∑i∈AN,j∈A2wij⋯∑i∈AN,j∈ANwij]\begin{align} Y^TWT &= \left[ \begin{matrix} y_1 &y_2&\cdots&y_N \end{matrix} \right] \left[ \begin{matrix} w_{11}&\cdots&w_{1N} \\ \vdots&\ddots&\vdots \\ w_{N1}&\cdots&w_{NN} \\ \end{matrix} \right] \left[ \begin{matrix} y_1^T\\y_2^T\\\cdots\\y_N^T \end{matrix} \right] \\ &= \left[ \begin{matrix} \sum\limits_{i=1}^N y_1w_{i1} &\sum\limits_{i=1}^N y_2w_{i2}&\cdots&\sum\limits_{i=1}^N y_Nw_{iN} \end{matrix} \right] \left[ \begin{matrix} y_1^T\\y_2^T\\\cdots\\y_N^T \end{matrix} \right] \\ &=\sum\limits_{i=1}^N \sum\limits_{j=1}^N y_iw_{ij}y_j^T = \sum\limits_{i=1}^N \sum\limits_{j=1}^N y_iy_j^Tw_{ij} \\ &= \left[ \begin{matrix} \sum\limits_{i\in A_1,j\in A_1}w_{ij}&\sum\limits_{i\in A_1,j\in A_2}w_{ij}&\cdots& \sum\limits_{i\in A_1,j\in A_N}w_{ij} \\ \vdots&\vdots&\ddots&\vdots \\ \sum\limits_{i\in A_N,j\in A_1}w_{ij}&\sum\limits_{i\in A_N,j\in A_2}w_{ij}&\cdots& \sum\limits_{i\in A_N,j\in A_N}w_{ij} \end{matrix} \right] \end{align}YTWT​=[y1​​y2​​⋯​yN​​]​w11​⋮wN1​​⋯⋱⋯​w1N​⋮wNN​​​​y1T​y2T​⋯yNT​​​=[i=1∑N​y1​wi1​​i=1∑N​y2​wi2​​⋯​i=1∑N​yN​wiN​​]​y1T​y2T​⋯yNT​​​=i=1∑N​j=1∑N​yi​wij​yjT​=i=1∑N​j=1∑N​yi​yjT​wij​=​i∈A1​,j∈A1​∑​wij​⋮i∈AN​,j∈A1​∑​wij​​i∈A1​,j∈A2​∑​wij​⋮i∈AN​,j∈A2​∑​wij​​⋯⋱⋯​i∈A1​,j∈AN​∑​wij​⋮i∈AN​,j∈AN​∑​wij​​​​​

令,

O′=YTDY−YWYO^{'} = Y^TDY - Y^WYO′=YTDY−YWY

由$trace$性质可知,

tr(O′P−1)=tr(OP−1)tr(O^{'}P^{-1}) = tr(OP^{-1})tr(O′P−1)=tr(OP−1)

其中,$O^{'}$与$O$的对角元素一样。

于是,有

Y^=argminY tr(OP−1)=argminY tr[YTLY⋅(YTDY)−1]\hat Y = \mathop{argmin}_{Y} \ tr(OP^{-1}) = \mathop{argmin}_{Y} \ tr[Y^TLY\cdot (Y^TDY)^{-1}]Y^=argminY​ tr(OP−1)=argminY​ tr[YTLY⋅(YTDY)−1]

定义$H$为新的指示向量:

h_{ij}=\left \{ \begin{array}{**lr**} 0&v_i \not\in A_j&\\ \frac{1}{\sum\limits_{i\in A_j} d_i}&v_i \in A_j \end{array} \right.

有,

HTDH=IH^TDH = IHTDH=I

于是,

H^=argminH tr(HTLH),s.t.HTDH=I\hat H = \mathop{argmin}_{H}\ tr(H^TLH),s.t.H^TDH=IH^=argminH​ tr(HTLH),s.t.HTDH=I

记,$H=D^{-\frac{1}{2}}F$,有$F^TF=I$,

F^=argminF tr(FTD−12LD−12F)\hat F = \mathop{argmin}_F \ tr(F^T{D^{-\frac{1}{2}}}L{D^{-\frac{1}{2}}}F)F^=argminF​ tr(FTD−21​LD−21​F)

注意$Y^TY$与$H^TH$表示的含义,两者的主对角线的值是相反的。

谱聚类实现

  • 实现步骤

  • 导入包

import warnings
import numpy as np
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.cluster import KMeans
from sklearn.metrics import accuracy_score,recall_score
from sklearn.datasets.samples_generator import make_blobs
warnings.filterwarnings('ignore')
  • 谱聚类

class SpectralClustering:
    def __init__(self,n_clusters=None,sigma=None,normalize=0):
        """
        
        """
        self.n_clusters = n_clusters
        self.W = None
        self.N = None # 样本数量/结点数量
        self.D = None # 度矩阵
        self.L = None # 拉普拉斯矩阵
        self.sigma = sigma # 高斯函数的sigma
        
        self.score = None
        
        self.normalize = normalize
        
        if self.n_clusters == None:
            self.n_clusters = 2
        
        if self.sigma == None:
            self.sigma = 3
    
    def init_params(self,X,y):
        self.X,self.y = X,y
        self.N = X.shape[0]
        self.W = self.similaryMatrix(X)
        self.D = self.diagMatrix()
        self.L = self.laplacianMatrix()
    
    def diagMatrix(self,):
        """
        对角矩阵
        """
        diag = np.sum(self.W,axis=1)
        diag = np.squeeze(diag)
        return np.diag(diag)
    
    def kernel(self,num,x,y):
        if num == 1: # 选择高斯核函数
            distance  = ((x - y)@(x - y))
            return np.exp(-distance/(2*self.sigma*self.sigma)) # 高斯函数
    
    def similaryMatrix(self,data):
        """
        相似矩阵/邻接矩阵/权值矩阵,权重值为距离的平方的倒数,表示越近的结点权重越大,越远的结点权重越小
        """
        S = np.zeros((self.N,self.N))
        for i in range(self.N):
            for j in range(self.N):
                S[i,j] = S[j,i] = self.kernel(1,data[i],data[j])
        S = S - np.diag(np.diag(S))
        return S
    
    def laplacianMatrix(self):
        L = self.D - self.W
        if self.normalize == 1:
            return np.sqrt(np.linalg.pinv(self.D)).dot(L).dot(np.sqrt(np.linalg.pinv(self.D)))
        return L
    
    def getEigenvectors(self,):
        eigenvalue,eigenvector = np.linalg.eig(self.L)
        index = np.argsort(eigenvalue)[:self.n_clusters]
        eigenvector = eigenvector[:,index]
        if self.normalize == 1:
#             eigenvector = preprocessing.StandardScaler().fit(
							eigenvector).transform(eigenvector) # 正则化
            eigenvector = preprocessing.normalize(eigenvector, norm='l2')
        return eigenvector
        
    def fit(self,X,y):
        self.init_params(X,y)
        vector = self.getEigenvectors()
        self.kmeans = KMeans(n_clusters=self.n_clusters)
        self.kmeans.fit(vector)
        self.y_pred = self.prediction()
        self.score = self.calc_score()
        self.plot()
        
    def prediction(self,):
        return self.kmeans.labels_
    
    def plot(self,):
        plt.scatter(X[:,0],X[:,1],c=self.y_pred)
        
    def calc_score(self,):
        a = accuracy_score(1-self.y_pred,self.y)
        b = accuracy_score(self.y_pred,self.y)
        return a if a>b else b
  • 生成数据

def create_data():
    X,y = make_blobs(n_samples=500,centers=2,random_state=4)
    return X,y
X,y = create_data()
plt.scatter(X[:,0],X[:,1],c=y)
  • 运行

sc = SpectralClustering(n_clusters=2,normalize=1)
sc.fit(X,y)
sc.score
image-20210107164311389
image-20210107164257045
image-20210107164133043
image-20210107164216858
image-20210105223513014