zoukankan      html  css  js  c++  java
  • 转:机器学习算法笔记:谱聚类方法

    https://blog.csdn.net/betarun/article/details/51154003

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

    从样本相似性到图

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

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

    现在我们假设已有的样本为X={x1,x2,,xn}X={x1,x2,…,xn}, 我们选择的样本相似性度量函数为(xi,xj)s(xi,xj)(xi,xj)→s(xi,xj),其中s0s≥0,ss越大表示相似性越高。一般我们选择的是距离的倒数。据此我们可以构造相似性图,节点为样本,节点之间的连边权重为样本间的相似性,如图所示。 
    相似性图

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

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

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

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

    现在我们得到一个较为稀疏的图。 
    稀疏化后的图

    图与图的Laplacian矩阵

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

     
    L(G,W)=⎛⎝⎜⎜⎜⎜⎜⎜nj1w1jw21wn1w1,2nj2w2jwn2w1nw2nnjnwnj⎞⎠⎟⎟⎟⎟⎟⎟=⎛⎝⎜⎜⎜⎜⎜⎜nj1w1jnj2w2jnjnwnj⎞⎠⎟⎟⎟⎟⎟⎟⎛⎝⎜⎜⎜⎜⎜w11w21wn1w1,2w22wn2w1nw2nwnn⎞⎠⎟⎟⎟⎟⎟=DWL(G,W)=(∑j≠1nw1j−w1,2⋯−w1n−w21∑j≠2nw2j⋯−w2n⋮⋮⋱⋮−wn1−wn2⋯∑j≠nnwnj)=(∑j≠1nw1j∑j≠2nw2j⋱∑j≠nnwnj)−(w11w1,2⋯w1nw21w22⋯w2n⋮⋮⋱⋮wn1wn2⋯wnn)=D−W

    容易看到,矩阵LL行和为零,且对于任意的向量ff有 

     
    fLf=fDffWf=i=1ndif2ii,j=1nfifjwij=12(i=1ndif2i2i,j=1nfifjwij+j=1ndjf2j)=12i,j=1nwij(fifj)2f′Lf=f′Df−f′Wf=∑i=1ndifi2−∑i,j=1nfifjwij=12(∑i=1ndifi2−2∑i,j=1nfifjwij+∑j=1ndjfj2)=12∑i,j=1nwij(fi−fj)2

    优化目标

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

     
    {ei,j|k,st.xiAk and xjAk}{ei,j|∃k,st.xi∈Ak and xj∉Ak}


    为了方便,引入记号 

     
    W(A,B)=iA,jBwijW(A,B)=∑i∈A,j∈Bwij


    那么 

     
    W(Ak,A¯k)=iAk,jAkwijW(Ak,A¯k)=∑i∈Ak,j∉Akwij


    因此去掉的边的权重和为 

     
    12k=1nW(Ak,A¯k)12∑k=1nW(Ak,A¯k)

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

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

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

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

      其中vol(A)=iAdivol(A)=∑i∈Adi

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

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

     
    hij=⎧⎩⎨1|Aj|√0xiAjxiAjhij={1|Aj|xi∈Aj0xi∉Aj


    那么, 

     
    hkLhk=12i,j=1nwij(hkjhkj)2=12xiAk,xjAk¯nwij(1|Ak|−−−−√0)2=12W(Ak,Ak¯)|Ak|hk′Lhk=12∑i,j=1nwij(hkj−hkj)2=12∑xi∈Ak,xj∈Ak¯nwij(1|Ak|−0)2=12W(Ak,Ak¯)|Ak|


    H=(h1,,hK)H=(h1,…,hK),则HH=IH′H=I,且 

     
    12k=1nW(Ak,A¯k)|Ak|=k=1nhkLhk=tr(HLH)12∑k=1nW(Ak,A¯k)|Ak|=∑k=1nhk′Lhk=tr(H′LH)


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

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

     
    argminHH=Itr(HLH)arg⁡minH′H=Itr(H′LH)

    L=QΛQ,Y=QHL=Q′ΛQ,Y=QH 则YY=IY′Y=I, 

     
    tr(HLH)=tr((QH)Λ(QH))=tr(YΛY)=tr(YYΛ)=i=1n(YY)iiλitr(H′LH)=tr((QH)′Λ(QH))=tr(Y′ΛY)=tr(YY′Λ)=∑i=1n(YY′)iiλi

    由于YY=IY′Y=I,有 

     
    0(YY)ii10≤(YY′)ii≤1


     
    i=1n(YY)ii=tr(YY)=tr(YY)=K∑i=1n(YY′)ii=tr(YY′)=tr(Y′Y)=K


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

     
    tr(HLH)i=1Kλitr(H′LH)≥∑i=1Kλi


    且当Yk=ekYk=ek时等号成立,对应的hk=(QY)k=Qek=Qkhk=(Q′Y)k=Q′ek=Qk′为LL的第kk小特征值对应的特征向量。

    最后一步

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

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

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

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

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

    总结

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

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

    代码例子

    左图是原始数据,右图是谱聚类结果 
    这里写图片描述

    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()            
  • 相关阅读:
    [CAMCOCO][C#]我的系统架构.服务器端.(一)
    开博啦,加油!!
    Django RestFul framework Serializer序列化器的使用(定义)
    Django项目快速搭建
    Django简介
    python搭建虚拟环境
    大专生自学web前端前前后后
    实现资源国际化
    利用ajax实现页面动态修改
    七牛使用
  • 原文地址:https://www.cnblogs.com/lm3306/p/9313875.html
Copyright © 2011-2022 走看看