关于谱聚类的ng算法的实现

广义上讲,任何在学习过程中应用到矩阵特征值分解的方法均叫做谱学习方法,比如主成分分析(PCA),线性判别成分分析(LDA),流形学习中的谱嵌入方法,谱聚类等等。

由于科苑向世明老师课件上面关于ng的谱聚类算法里面与ng大神的论文中写到的算法中有所出入,导致昨天晚上调了一晚上的算法并没有调出满意的结果,今天在网上找到了ng大神的原始paper阅读一遍,虽然还是有很多不理解的地方,还是有了自己的见解。下面是ng算法的流程。

算法第一步先通过高斯函数计算出每个点与其他点的亲和度,与自己的亲和度为0,对于每一个点保留前k_nearest个最近邻的点的亲和度(即k_nearest个亲和度最大的点),其他的亲和度置为0,这里的k作为算法的参数传入

算法第二步先计算度矩阵D,D矩阵为一个对角矩阵,将亲和度矩阵的每一行元素求和放在度矩阵的相应对角元素上面即可,算出对角矩阵后再构造归一化的拉普拉斯矩阵,由于D是对角矩阵,所以D^(-0.5)可以直接理解为对角元素的倒数开根号,然后得到拉普拉斯矩阵

算法第三步求解拉普拉斯矩阵的特征值和特征向量,并按照特征值大小选取对应最大的K个特征值对应的特征向量(这里的K为将数据点聚成的类的个数),每个特征向量按列排列组成K维空间的n个向量即X属于Rn*k

算法第四步将得到的X矩阵按行归一化长度得到矩阵Yn*k

算法第五步将得到的归一化长度的矩阵数据送入k_means算法进行聚类,得到的类别标签即为原始数据点的类别标签

个人对算法的理解是将原始数据点映射到K维数据空间便于更好的将数据分类出来。

下面是算法实现的matlab代码,python代码等有时间写完再贴上来。

function [after_class_data,class_label,acc] = spectral_clustering(dataSet,class_num,sigma,k_near)
Affinity_mat = creat_D(dataSet,k_near,sigma);     %创建亲和度矩阵
laplas = get_norm_laplas(Affinity_mat);           %得到归一化的拉普拉斯矩阵
[eig_val,eig_vec] = get_special_vector(laplas,class_num);    %得到拉普拉斯矩阵的前K大的特征值对应的特征向量
[label,after_center] = k_means(eig_vec,class_num);           %将特征向量送入k_means进行聚类
after_class_data = after_center;
class_label = label;
%{
n11 = size(find(label(1:100)==1),2);
n12 = size(find(label(1:100)==2),2);
n21 = size(find(label(1:100)==1),2);
n22 = size(find(label(1:100)==2),2);
n_1 = max(n11,n12);
n_2 = max(n21,n22);
acc = (n_1 + n_2)/size(label,2);       %计算分类正确率
%}

%计算亲和度矩阵,用K近邻求取,其余的赋值为0,每个点与本身的亲和度为0
function Affinity_mat = creat_D(dataSet,k,sigma)
[row,col] = size(dataSet);
dis_mat = zeros(row,row);
index_all = zeros(row,row);
%index_all = [];
for i = 1:row
    for j=1:row
        if i ~= j
            dis_mat(i,j) = exp((-sum((dataSet(i,:)-dataSet(j,:)).^2))/(2*sigma.^2));
        end
    end
end

Affinity = dis_mat;

for t =1:row
    [sort_dis,index] = sort(Affinity(t,:),‘descend‘);
    index_all(t,:) = index;
end

for ii = 1:row
    temp_index = index_all(ii,:);
    temp_clear = temp_index(k+1:row);
    %temp_one = temp_index(1:k);
    Affinity(ii,temp_clear) = 0;
    %Affinity(ii,temp_one) = 1;
    Affinity(ii,ii) = 0;
end
Affinity_mat = Affinity;

function laplas = get_norm_laplas(Affinity_mat)
row = size(Affinity_mat,1);
du = zeros(row,row);
%col_sum = sum(Affinity_mat);
for i=1:row
    du(i,i) = sum(Affinity_mat(i,:));   %求度矩阵
end
dn = du^(-0.5);
laplas = dn*Affinity_mat*dn;        %归一化的laplas

%求k个最小的特征值和对应的特征向量
function [eig_val,special_vector] = get_special_vector(laplas,k)
eig_con = eig(laplas);
[vector,x] = eig(laplas);
[sort_vec,index] = sort(eig_con,‘descend‘);
eig_val = eig_con(index(1:k));
temp_vector = vector(:,index(1:k));
[row,col] = size(temp_vector);
y = zeros(row,col);
for i=1:row
    s = (sum(temp_vector(i,:).^2)).^(0.5);    %特征向量的归一化
    for j=1:col
        y(i,j) = temp_vector(i,j)/s;
    end
end
special_vector = y;

k_means聚类算法代码如下:

function [class_type,after_center] = k_means(dataSet,class_number)
[data_row,data_col] = size(dataSet);
%last_label = zeros(1,data_row);
label = ones(1,data_row);
ini_center = randn(class_number,data_col)
%ini_center = [1.1437 0.9726;-0.5316 -0.5223];
new_center = zeros(class_number,data_col);

while (sum(sum(abs(ini_center - new_center) > 1e-5)) > 0)
    new_center = ini_center;
    for i=1:data_row
        min_dis = Inf;
        belong_class = 1;             %用该变量来存储属于的类别,如为1,则归属为第一类。。。
        for j=1:class_number
            cur_dis = sum((ini_center(j,:)-dataSet(i,:)).^2);
            if cur_dis < min_dis
                min_dis = cur_dis;
                belong_class = j;
            end
        end
        label(i) = belong_class;
    end        %找到每一个类的归属标签
    %重新计算归属类的中心点
    for k=1:class_number
        class_index = find(label==k);
        n = size(class_index,2);
        %{
        sum_x = sum(dataSet(class_index,1));   %算出类别k中的x的和
        sum_y = sum(dataSet(class_index,2));
        ini_center(k,1) = sum_x/n;
        ini_center(k,2) = sum_y/n;   %更新归属类的中心
        %}
        ini_center(k,:) = sum(dataSet(class_index,:))./n;
    end
end

class_type = label;
after_center = new_center;

用月牙型数据进行测试分类情况,设定sigma参数为35,当取k_nearest=10,20,30时,对应的分类图如下

k_nearest = 10

k_nearest = 20

k_nearest = 30

随着最近邻参数k_nearest的增大,分类的正确逐渐下降。由于此k_means算法的初始点使用randn生成,而初始点的选取对结果是有影响的,故在跑程序途中会出现结果不理想出现Nan的情况,这些比较正常,多试几次就能得到比较稳定的分类结果了。以后会逐渐的用python来实现算法,后续会上传python代码。

感慨:特征值分解,特征向量映射原始点到K维空间,大神们是怎么想到了呢,太神奇了,个人的数学思维和素养需要进一步提升,虽然算法里面的一些数学原理上的东西还不是很理解,但是我会加油的。

时间: 2024-08-25 17:10:57

关于谱聚类的ng算法的实现的相关文章

用scikit-learn学习谱聚类

在谱聚类(spectral clustering)原理总结中,我们对谱聚类的原理做了总结.这里我们就对scikit-learn中谱聚类的使用做一个总结. 1. scikit-learn谱聚类概述 在scikit-learn的类库中,sklearn.cluster.SpectralClustering实现了基于Ncut的谱聚类,没有实现基于RatioCut的切图聚类.同时,对于相似矩阵的建立,也只是实现了基于K邻近法和全连接法的方式,没有基于$\epsilon$-邻近法的相似矩阵.最后一步的聚类方

谱聚类算法及其代码(Spectral Clustering)

简介 文章将介绍谱聚类(spectral clustering)的基本算法,以及在matlab下的代码实现.介绍内容将包括: 从图分割角度直观理解谱聚类 谱聚类算法步骤 数据以及实现代码 本文将不会涉及细节化的证明和推导,如有兴趣可参考july大神的文章从拉普拉斯矩阵说到谱聚类. 对谱聚类的理解 这一节将从图分割聚类的角度直观理解谱聚类.不过,因为本人是从事社交媒体分析的,将从一种社会关系网络的角度来介绍网络图分割成多个子图的概念. 图的分割 首先将社会关系网络看成是一个整体,每一个个体(use

谱聚类(spectral clustering)及其实现详解

Preface 开了很多题,手稿都是写好一直思考如何放到CSDN上来,一方面由于公司技术隐私,一方面由于面向对象不同,要大改,所以一直没贴出完整,希望日后可以把开的题都补充全. 先把大纲列出来: 一.从狄多公主圈地传说说起 二.谱聚类的演算 (一).演算 1.谱聚类的概览 2.谱聚类构图 3.谱聚类切图 (1).RatioCut (2).Ncut (3).一点题外话 (二).pseudo-code 三.谱聚类的实现(scala) (一).Similarity Matrix (二).kNN/mut

阅读《基于谱聚类的终端区飞行轨迹分析》笔记

一. 前言 由于参与的相关可视化项目进展到飞行轨迹的聚类算法部分,于是阅读了部分相关论文,并做了一些摘要. 论文均来源与中国知网,均将申明出处. 二. 论文出处 <基于谱聚类的终端区飞行轨迹分析> 马 勇,胡明华,顾 欣,袁立罡 ( 南京航空航天大学民航学院,江苏 南京 210016) 航空计算技术,第45卷,第5期,2015年9月 三. 论文笔记 1.摘要:为了实现智能化处理海量航班数据,精细描述终端区运行特性,研究了基于谱聚类的终端区飞行轨迹分析方法.在分析终端区航班飞行特点的基础上,提出

理解矩阵及谱聚类小记

最近看了一些矩阵和谱聚类的知识,特在此简单记录一下.详细可以先看下参考文献. 首先看到的是孟岩写的三篇<理解矩阵>. 一:理解矩阵(一) 1:传统书籍空间的定义:存在一个集合,在这个集合上定义某某概念,然后满足某些性质",就可以被称为空间.孟的空间包含四点:(1). 由很多(实际上是无穷多个)位置点组成:(2). 这些点之间存在相对的关系:(3). 可以在空间中定义长度.角度:4.这个空间可以容纳运动,这里我们所说的运动是从一个点到另一个点的移动(变换),而不是微积分意义上的&quo

【谱聚类算法总结】

前言:以前只是调用过谱聚类算法,我也不懂为什么各家公司都问我一做文字检测的这个算法具体咋整的,没整明白还给我挂了哇擦嘞?讯飞和百度都以这个理由刷本宝,今天一怒把它给整吧清楚了,下次谁再问来!说不晕你算我输! 一.解释: 二.推导: 三.步骤: 四.优缺点: 五.链接: https://www.cnblogs.com/pinard/p/6221564.html 原文地址:https://www.cnblogs.com/EstherLjy/p/9432651.html

机器学习(6)之聚类算法(k-means\Canopy\层次聚类\谱聚类)

目录 1 聚类的定义 1.1 距离公式(相似度) 1.2 聚类的思想 2 K-means算法 2.1 K-means算法的思考 2.2 总结 3 二分K-Means算法 4 K-Means++算法 4.1 K-Means||算法 5 Canopy算法 5.1 应用场景 6 Mini Batch K-Means算法 7 层次聚类方法 7.1 AGNES算法中簇间距离 7.2 层次聚类优化算法 8 密度聚类 8.1 DBSCAN算法 8.1.1 基本概念 8.1.2 算法流程 8.1.3 DBSCA

万年历算法的实现(C语言--gcc编译)

/** cal.c * * 现行的格里历是从儒略历演化而来的.儒略历每4年一个润年,润年366天,平年365天.* 如果从公元1年算的话,那么凡是能够被4整除的都是润年.从天文角度看,儒略历这种 * 历法是有误差的,到16世纪误差已经达到了10天.1582年,罗马教皇对儒略历进行了 * 一次校定,该年的10-5到10-14这10天被抹掉,并规定凡不能被400整除的世纪年不再 * 算为润年,校定之后的儒略历即为现行的格里历. * * 但是英国直到1752年才开始使用格里历,此时时间误差已经达到了1

搜索引擎--范例:中英文混杂分词算法的实现--正向最大匹配算法的原理和实现

纯中文和中英文混杂的唯一区别是,分词的时候你如何辨别一个字符是英文字符还是孩子字符, 人眼很容易区分,但是对于计算机来说就没那么容易了,只要能辨别出中文字符和英文的字符,分词本身就不是一个难题 1:文本的编码问题: utf8:windows下,以utf8格式保存的文本是一个3个字节(以16进制)的BOM的,并且你不知道一个汉字是否是用3位表示,但是英文适合ascii编码一样的 ascii:英文一位,中文两位,并且中文的第一个字节的值是大于128和,不会和英文混淆,推荐 unicode:中文基本是