#大神教你做项目#之K-means聚类算法的MATLAB实现

Posted 紫冬科协

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#大神教你做项目#之K-means聚类算法的MATLAB实现相关的知识,希望对你有一定的参考价值。

嘿嘿!你模式识别作业写了没?
#大神教你做项目#之K-means聚类算法的MATLAB实现
李雷
#大神教你做项目#之K-means聚类算法的MATLAB实现
韩梅梅
#大神教你做项目#之K-means聚类算法的MATLAB实现
嗯。。。
那个分类的题目该怎么做啊?
#大神教你做项目#之K-means聚类算法的MATLAB实现
#大神教你做项目#之K-means聚类算法的MATLAB实现
李雷
#大神教你做项目#之K-means聚类算法的MATLAB实现
韩梅梅
#大神教你做项目#之K-means聚类算法的MATLAB实现
用K-Means聚类算法啊~分类又快有准,用过的都说棒!
那是啥。。。能吃么
#大神教你做项目#之K-means聚类算法的MATLAB实现
#大神教你做项目#之K-means聚类算法的MATLAB实现
李雷
1
概述
首先需要明确聚类的概念。简而言之就是把相似的事物按照某一种标准分为若干类。比如说下图中的一系列二维平面中的点。我们可以很直观地发现,按照不同点之间的距离,这些点可以分成三组。不过,我们应当如何让计算机自动完成分类呢?这就需要用到聚类算法了。
#大神教你做项目#之K-means聚类算法的MATLAB实现

本文中介绍的K-means,是一种非常经典,也是十分常用的一种聚类算法。考虑到大家对数学公式比较反感,这里只给出大致的描述,较为详细的说明大家可以参考下面这篇博客,里面涉及到算法的数学描述以及结果收敛的证明。


http://www.cnblogs.com/moondark/archive/2012/03/08/2385770.html


在分类之前,我们需要明确分类的标准。设我们一共有 N 个数据点需要分为K个类。这些数据的类别可以是二维平面中的点,也可以是更高维的向量。令μk 表示第k类的平均值(也就是中心)。K-means的目标是使每个点到其所属类的中心“距离”之和最小。“距离”的定义实际上多种多样,这里采用两点间距离(也就是欧氏距离)的平方,因为比较直观并且便于计算。


实际上,直接找出k个中心比较困难,所以我们退而求其次,采用迭代的方法:具体实现的步骤如下:

1. 随机选择K个点作为初始的中心点
2. 按照到达各个中心点的距离最小的原则,将所有点分类
3. 取每一类中的中心(即计算均值)作为k个新的中心

4. 重复步骤2,3,直到结果收敛


数学上可以证明,k-means一定是收敛的(证明可以参考前面给的博客),不过并不一定收敛到全局最优解(也就是我们希望看到的结果)。收敛的结果依赖于初始中心点的选定。这也是k-means算法最大的缺点之一。不过一般来说k-means的聚类结果都很理想,所以遇到这种特殊情况再跑一遍就好了。

另一个缺点是k的值必须要预先给定,并不能进行自动判断。不过总体而言k-means依然是一种非常经典的聚类算法。


2
算法实现
道理我都懂。。。可是该肿么实现呢。。。
#大神教你做项目#之K-means聚类算法的MATLAB实现
#大神教你做项目#之K-means聚类算法的MATLAB实现
李雷
#大神教你做项目#之K-means聚类算法的MATLAB实现
韩梅梅
#大神教你做项目#之K-means聚类算法的MATLAB实现
。。。拿去抄吧。。。


CreateData.m

% 按正态分布生成三组二维平面中的点,每一组100个,方差均为0.5

function X=CreateData()

X =[0.5.*randn(100,2)+ones(100,2);... %第一组:中心(1,1)

0.5.*randn(100,2)-ones(100,2);... %第二组:中心(-1,-1)

0.5.*randn(100,2)+repmat([1,-1],100,1)]; %第三组:中心(1,-1)

%返回矩阵300*2的矩阵X,每一行表示一个点的坐标

Kmeans.m

%通过Kmeans将数据X分成k

%X是数据集,为n*p矩阵。n为数据个数,p为每一个数据的维数(此运行实例为2维)

%Ctrsk*p矩阵,存储k个类的中心坐标,Classn*1矩阵,存储每一个数据的分类(1,…,k表示)

function [Ctrs,Class]=Kmeans(X,k)

[n,p]=size(X);

Ctrs=zeros(k,p);%0初始化

Class=ones(n,1);%1初始化

Init=randi(n,k,1);

for i=1:k %随机选取X中的k个点作为初始中心

Ctrs(i,:)=X(Init(i),:);

end

while 1 %反复迭代,直到中心收敛

TempCtrs=Ctrs;

for i=1:n %根据当前的中心,将每一个数据归类

Class(i)=Sort(X,Ctrs,k,i);

end

for i=1:k %根据新的分类结果,计算每一个类的中心

Ctrs(i,:)=ClassCtr(X,Class,i,n,p);

end

if sum((TempCtrs-Ctrs).^2)<0.001 %判断中心是否收敛

break;

end

end

function D=dist(X,Y) %计算向量X,Y之间欧氏距离的平方

D=sum((X-Y).^2);

%按照欧氏距离平方最小的原则,将X中第i个数据归到第NClass类中

function NClass=Sort(X,Ctr,k,i)

MinDist=dist(X(i,:),Ctr(1,:));

NClass=1;

for j=2:k

Dj=dist(X(i,:),Ctr(j,:));

if Dj<MinDist

MinDist=Dj;

NClass=j;

end

end

%计算第K类的中心,即第K类所有数据的均值

function Ctr=ClassCtr(X,Class,K,n,p)

Sum=zeros(1,p);

num=0;

for i=1:n

if Class(i)==K;

Sum=Sum+X(i,:);

num=num+1;

end

end

Ctr=Sum/num;


Plot.m

%将结果绘制成二维图片,参考帮助文件中kmeans词条

function Plot(X,idx,ctrs)

plot(X(idx==1,1),X(idx==1,2),'r.','MarkerSize',12)

hold on

plot(X(idx==2,1),X(idx==2,2),'b.','MarkerSize',12)

plot(X(idx==3,1),X(idx==3,2),'g.','MarkerSize',12)

plot(ctrs(:,1),ctrs(:,2),'kx',...

'MarkerSize',12,'LineWidth',2)

plot(ctrs(:,1),ctrs(:,2),'ko',...

'MarkerSize',12,'LineWidth',2)

legend('Cluster 1','Cluster 2','Cluster 3','Centroids',...

'Location','NW')


(代码会稍后在科协学术博客更新提供下载)


3
实例运行
好,那么现在我已经有了聚类算法的代码了!
#大神教你做项目#之K-means聚类算法的MATLAB实现
#大神教你做项目#之K-means聚类算法的MATLAB实现
李雷
#大神教你做项目#之K-means聚类算法的MATLAB实现
韩梅梅
#大神教你做项目#之K-means聚类算法的MATLAB实现
不是我刚给你的么...
那我该怎么运行代码呢?拷到VS里编译不通过啊!
#大神教你做项目#之K-means聚类算法的MATLAB实现
#大神教你做项目#之K-means聚类算法的MATLAB实现
李雷
#大神教你做项目#之K-means聚类算法的MATLAB实现
韩梅梅
#大神教你做项目#之K-means聚类算法的MATLAB实现
主页君把你黑成这样子你还卖萌真的不介意么...


由于MATLAB实在是博大精深,不可能面面俱到,所以这一部分用来教会大家如何在MATLAB上跑出我写的代码。


安装好MATLAB后(网上有好多安装教程),启动程序,应该是这样一个界面:

#大神教你做项目#之K-means聚类算法的MATLAB实现

点击左上角的NewScript,在同一目录下新建三个源文件,文件名如第二部分所述。(注意文件名一定要与函数名一样,否则无法运行)。然后将源代码依次复制进去。


#大神教你做项目#之K-means聚类算法的MATLAB实现


写好三个源文件之后,左边的“当前目录”栏会显示刚才创建的文件,需要编辑时可以从这里打开。


#大神教你做项目#之K-means聚类算法的MATLAB实现


CommandWindow中依次输入下列命令:


#大神教你做项目#之K-means聚类算法的MATLAB实现
#大神教你做项目#之K-means聚类算法的MATLAB实现#大神教你做项目#之K-means聚类算法的MATLAB实现


之后就会弹出分类的结果:


#大神教你做项目#之K-means聚类算法的MATLAB实现


右侧的Workspace栏会显示刚才的计算结果,可以双击某一变量进行查看


#大神教你做项目#之K-means聚类算法的MATLAB实现

需要说明的是MATLAB的帮助文件是学习MATLAB的利器,里面会有详细的语法说明,并提供相应的实例。比如说我们可以查看MATLAB中自带的kmeans算法:



如果不了解源代码中某一函数,可以直接在源代码中右键,点击Help on Selection,即可显示相应的帮助词条:


大家可以尝试生成不同的数据集X、修改一些参数,多次运行,观察最终结果有何不同。


最后我想说的是,这个项目难度不是很大,比较适合MATLAB初学者学习。可以看到算法的每一步都涉及的矩阵以及线性空间的知识,这充分说明大一学习的线性代数和微积分是非常有用的(微积分在证明迭代结果收敛时用到)。所以五字班的同学们一定要认真学习,打好基础。




以上是关于#大神教你做项目#之K-means聚类算法的MATLAB实现的主要内容,如果未能解决你的问题,请参考以下文章

数据挖掘之聚类算法K-Means总结

数据挖掘之聚类算法K-Means总结

03-01 K-Means聚类算法

机器学习笔记之谱聚类k-Means聚类算法介绍

机器学习笔记之谱聚类k-Means聚类算法介绍

机器学习(25)之K-Means聚类算法详解