基础算法(二):Kmeans聚类算法的基本原理与应用

Kmeans聚类算法的基本原理与应用


      内容说明:主要介绍Kmeans聚类算法的数学原理,并使用matlab编程实现Kmeans的简单应用,不对之处还望指正。

       参考资料:http://www.cnblogs.com/tiandsp/archive/2013/04/24/3040883.html

一、Kmeans数学原理

       以往的回归分类、朴素贝叶斯分类、SVM分类的样本的标签(类别)是已知的,通过大量的训练样本训练得到模型,然后判断新的样本所属已知类别中的哪一类。而Kmeans聚类属于无监督学习,样本所属的类别是未知的,只是根据特征将样本分类,且类别空间也是根据需要人为选定的。

       Kmeans核心思想:最小化所有样本到所属类别中心的欧式距离和,采用迭代的方式实现收敛。

      

      为了将J调整到最小,假设当前情况下J没有达到最小,那么可以通过固定每一个类别的中心u,调整每一个样本的所属类别c来减小J,也可以通过固定每一个样本的所属类别c,调整类别中心来减小J的值。理论上,可以有多组u,c值使得J最小,但实际应用中一般出现较少。

      J为非凸函数,所以最后收敛的点有可能是全局最优,也有可能是局部最优,说明Kmeans对初始条件比较敏感,可多次给定不同的初始条件计算J值,最后选择最小的那一组作为最终的结果。下图为不断迭代至收敛的过程图。

       

二、Kmeans聚类的matlab实现


      下面的代码主要来自参考资料,只是将三维数据改成二维数据,可以将二维训练数据类比为学生的语文和数学的成绩,通过聚类将300名学生按照成绩分别ABC三类,三维数据对应着可以类比为学生的语数外成绩。

      matlab代码实现:

kmeans_test.m

clear 
close all
clc
%% 采用随机函数的方法产生训练数据
%第一类数据
mu1=[0 0];                  %均值
S1=[0.3 0;0 0.35];          %协方差
data1=mvnrnd(mu1,S1,100);   %产生高斯分布数据
%%第二类数据
mu2=[1.25 1.25];
S2=[0.3 0;0 0.35];
data2=mvnrnd(mu2,S2,100);
%第三个类数据
mu3=[1.25 -1.25];
S3=[0.3 0;0 0.35];
data3=mvnrnd(mu3,S3,100);

%% 显示训练数据
plot(data1(:,1),data1(:,2),'+');
hold on;
plot(data2(:,1),data2(:,2),'r+');
plot(data3(:,1),data3(:,2),'g+');
grid on;
%三类数据合成一个不带标号的数据类
data=[data1;data2;data3];   %这里的data是不带标号的
%k-means聚类
[u re]=KMeans(data,3);  %最后产生带标号的数据,标号在所有数据的最后,意思就是数据再加一维度
[m n]=size(re);
%% 最后显示聚类后的数据
figure;
hold on;
for i=1:m 
    if re(i,3)==1   
         plot(re(i,1),re(i,2),'ro'); 
    elseif re(i,3)==2
         plot(re(i,1),re(i,2),'go'); 
    else 
         plot(re(i,1),re(i,2),'bo'); 
    end
end
plot(u(:,1),u(:,2),'k+'); 
grid on;
KMeans.m

%N是数据一共分多少类
%data是输入的不带分类标号的数据
%u是每一类的中心
%re是返回的带分类标号的数据
function [u re]=KMeans(data,N)   
    [m n]=size(data);   %m是数据个数,n是数据维数
    ma=zeros(n);        %每一维最大的数
    mi=zeros(n);        %每一维最小的数
    u=zeros(N,n);       %随机初始化,最终迭代到每一类的中心位置
    for i=1:n
       ma(i)=max(data(:,i));    %每一维最大的数
       mi(i)=min(data(:,i));    %每一维最小的数
       for j=1:N
            u(j,i)=ma(i)+(mi(i)-ma(i))*rand();  %随机初始化,不过还是在每一维[min max]中初始化好些
       end      
    end
   
    while 1
        pre_u=u;            %上一次求得的中心位置
        for i=1:N
            tmp{i}=[];      % 公式一中的x(i)-uj,为公式一实现做准备
            for j=1:m
                tmp{i}=[tmp{i};data(j,:)-u(i,:)];
            end
        end
        
        quan=zeros(m,N);
        for i=1:m           %计算每一个样本i所属的类别
            c=[];
            for j=1:N
                c=[c norm(tmp{j}(i,:))];
            end
            [junk index]=min(c);
            quan(i,index)=norm(tmp{index}(i,:));           
        end
        
        for i=1:N            %更新类别变化后的类别中心位置
           for j=1:n
                u(i,j)=sum(quan(:,i).*data(:,j))/sum(quan(:,i));
           end           
        end
        
        if norm(pre_u-u)<0.1  %不断迭代直到位置不再变化或变化极小
            break;
        end
    end
    
    re=[];
    for i=1:m
        tmp=[];
        for j=1:N
            tmp=[tmp norm(data(i,:)-u(j,:))];
        end
        [junk index]=min(tmp);
        re=[re;data(i,:) index];
    end
end
运行结果如下,这是按照高斯分布产生的3*100个二维的训练数据,可以根据需要替换训练数据。


这是Kmeans聚类之后的数据,每种颜色对应着一个类别,中心的黑色十字叉为类别中心。

三、Kmeans算法的实际应用

      Kmeans算法的应用很多,后期会根据自己碰到的具体应用不断更新。

      若有错误之处,还望不吝指出,谢谢。









猜你喜欢

转载自blog.csdn.net/stayfoolish_fan/article/details/51888717
今日推荐