机器学习算法笔记:谱聚类方法

这方法是昨天听同学提起的,大致翻看了几篇博客跟论文,这里写下自己的理解

从样本相似性到图

根据我们一般的理解,聚类是将相似的样本归为一类,或者说使得同类样本相似度尽量高,异类样本相似性尽量低。无论如何,我们需要一个方式度量样本间的相似性。常用的方式就是引入各种度量,如欧氏距离、余弦相似度、高斯度量等等。

度量的选择提现了你对样本或者业务的理解。比如说如果你要比较两个用户对音乐选择的品味,考虑到有些用户习惯打高分,有些用户习惯打低分,那么选择余弦相似度可能会比欧式距离更合理。

现在我们假设已有的样本为 X={x1,x2,,xn} , 我们选择的样本相似性度量函数为 (xi,xj)s(xi,xj) ,其中 s0 , s 越大表示相似性越高。一般我们选择的是距离的倒数。据此我们可以构造相似性图,节点为样本,节点之间的连边权重为样本间的相似性,如图所示。
机器学习算法笔记:谱聚类方法_第1张图片

这是一个完全图,我们的目的是去掉一些边,使得这个图变成 K 个连通子图。同一个子图内的节点归为一类。因此有两方面考虑:

  • 子图内的连边权重尽量大,即同类样本间尽量相似
  • 去掉的边权重尽量小,即异类样本间尽量不同

一个初步的优化方法是去掉部分权重小的边,常用的有两种方式:

  • ϵ 准则,即去掉权重小于 ϵ 的所有边
  • k 邻近准则,即每个节点之保留权最大的几条边

现在我们得到一个较为稀疏的图。
机器学习算法笔记:谱聚类方法_第2张图片

图与图的Laplacian矩阵

为了下一步的算法推导,首先介绍图的Laplacian矩阵,我们记节点 i,j 连边的权重为 wi,j ,如果两个节点之间没有连边, wi,j=0 ,另外 wii=0 ,那么图对应的Laplacian矩阵为:

L(G,W)=j1nw1jw21wn1w1,2j2nw2jwn2w1nw2njnnwnj=j1nw1jj2nw2jjnnwnjw11w21wn1w1,2w22wn2w1nw2nwnn=DW

容易看到,矩阵 L 行和为零,且对于任意的向量 f

fLf=fDffWf=i=1ndif2ii,j=1nfifjwij=12i=1ndif2i2i,j=1nfifjwij+j=1ndjf2j=12i,j=1nwij(fifj)2

优化目标

现在我们来推导我们要优化的目标函数。前面说过,我们的目的是去掉一些边,使得这个图变成 K 个连通子图,我们还希望去掉的边权重尽量小。为此,假设我们已经把图分割成立K个连通子图 A1,,AK ,那么我们去掉的边集合为

{ei,j|k,st.xiAk and xjAk}

为了方便,引入记号
W(A,B)=iA,jBwij

那么
W(Ak,A¯k)=iAk,jAkwij

因此去掉的边的权重和为
12k=1nW(Ak,A¯k)

现在的问题就转换为:找到 X 的划分 A1,,AK ,使得上式最小。不幸的是,存在两个问题:

  • 这是个NP难问题,没有有效算法
  • 实际实验得到的结果常常将单独的一个样本分为一类

先来解决第二个问题:
我们实际希望的是,每个类别中的样本数要充分大,有两种调整目标函数的方法:

  1. RatioCut,将目标函数改成
    12k=1nW(Ak,A¯k)|Ak|
  2. Ncut, 将目标函数改成
    12k=1nW(Ak,A¯k)volAk

    其中 vol(A)=iAdi

两种方法都使得某个类样本量少的时候,对应的目标函数项变大。这里我们以第一种方法为例,第二种是类似的。

现在来解决第二个问题:
我们碰到NP难问题的时候,通常是考虑近似解,谱聚类也不例外。首先,我们要引入列向量 hk=(h1k,,hn,k) ,其中

hij=1|Aj|0xiAjxiAj

那么,
hkLhk=12i,j=1nwij(hkjhkj)2=12xiAk,xjAk¯nwij(1|Ak|0)2=12W(Ak,Ak¯)|Ak|

H=(h1,,hK) ,则 HH=I ,且
12k=1nW(Ak,A¯k)|Ak|=k=1nhkLhk=tr(HLH)

现在的问题是找到 H 使得 tr(HLH) 尽量小。这当然还是NP问题。原因在于 H 的列向量元素只能选择 0 或者 |Ak|

这里用到的一个trick是放宽 H 的限制,在更大的变量空间内寻找目标函数的最小值。在这里,我们让 H 可以取任意实数,只要满足 HH=I .那么就是求解优化问题:

argminHH=Itr(HLH)

L=QΛQ,Y=QH YY=I ,

tr(HLH)=tr((QH)Λ(QH))=tr(YΛY)=tr(YYΛ)=i=1n(YY)iiλi

由于 YY=I ,有

0(YY)ii1

i=1n(YY)ii=tr(YY)=tr(YY)=K

可以分析得到 tr(HLH) 取最小值时,必有 (YY)ii=0 or 1 ,
因此
tr(HLH)i=1Kλi

且当 Yk=ek 时等号成立,对应的 hk=(QY)k=Qek=Qk L 的第 k 小特征值对应的特征向量。

最后一步

现在我们得到了放宽限制条件下的优化问题的最优解解 h1,hK ,如何得到原问题的一个解?

我们知道,如果 H 满足原来的限制条件,那么 hij0 表示第 i 个样本归为第 j 类,但是我们放宽限制条件后得到的 H 可能一个零都没有!

谱聚类有意思的地方是选择了对 H 的行向量做K-means聚类,我个人认为是基于如下考虑:

  1. 对满足原始限制条件的 H ,行向量一致等价于类别一致
  2. 在原始限制条件下得到的 H 跟放宽限制条件下得到的 H 应该比较相近

如此可以推断在放宽条件下得到的 H 如果行向量相似,则应该类别相似。因此直接对行向量做k-means聚类即可。

总结

至此,谱聚类的大致步骤就完成了,归纳下主要步骤

  1. 计算样本相似性得到样本为节点的完全图
  2. 基于 ϵ 准则或者 m 邻近准则将完全图稀疏化
  3. 计算稀疏化后的图的laplacian矩阵,计算其前 K 小特征值对应的特征向量作为矩阵 H 的列
  4. 对矩阵 H 的行向量作k-means聚类
  5. H 的第 i 行与第 j 行被聚为一类,则表示 xi xj 聚为一类。

代码例子

左图是原始数据,右图是谱聚类结果
机器学习算法笔记:谱聚类方法_第3张图片

import numpy as np
import networkx as nx
import scipy.linalg as llg
from Queue import PriorityQueue
import matplotlib.pylab as plt
import heapq as hp
from sklearn.cluster import k_means

# fake data from multivariate normal distribution
S = np.random.multivariate_normal([1,1], [[0.5,0],[0,0.7]],100)
T = np.random.multivariate_normal([-1,-1], [[0.3,0],[0,0.8]],100)
R = np.random.multivariate_normal([-1,0], [[0.4,0],[0,0.5]],100)
Data = np.vstack([S,T,R])
plt.subplot(1,2,1)
plt.scatter(S.T[0],S.T[1],c='r')
plt.scatter(T.T[0],T.T[1],c='b')
plt.scatter(R.T[0],R.T[1],c='y')

# calc k-nearest neighbors
def min_k(i,k):
    pq = []
    for j in range(len(Data)):
        if i == j:
            continue
        if len(pq) < k:
            hp.heappush( pq,(1/np.linalg.norm(Data[i]-Data[j]), j) )
        else:
            hp.heappushpop( pq, (1/np.linalg.norm(Data[i]-Data[j]), j) )
    return pq

# calc laplacian
L = np.zeros((len(Data),len(Data)))
for i in range(len(Data)):
    for (v,j) in min_k(i, 3):
        L[i,j] = -v
        L[j,i] = -v
L = L + np.diag(-np.sum(L,0)) 

# kmean
(lam, vec) = llg.eigh(L)
A = vec[:,0:3]
kmean = k_means(A,3)

plt.subplot(1,2,2)
plt.scatter(Data.T[0],Data.T[1],c=['r' if v==0 else 'b' if v==1 else 'y' for v in kmean[1]])
plt.show()            

你可能感兴趣的:(机器学习算法)