k-means和k-medoids聚类算法matlab编程实现

k-means算法步骤:

步骤1:随机选择k个初始簇中心(聚类中心);

步骤2:对剩余的每个样本,分别计算其到k个簇中心的距离,并将其划分入距离它最近的簇中心所在的簇中,从而形成k个簇;

步骤3:重新计算每个簇的均值向量作为新的簇中心;

步骤4:如果簇中心没有任何改变,算法停止,否则回到步骤2

k-means算法优点:

  1. 单,

  2. Ο(tkn)

  3. ,n是k是目,t数。k和t以k-线Ο(n)


k-medoids算法步骤:

步骤1:随机选择k个样本作为初始的簇中心;

步骤2:对剩余的每个样本,将其划分入距离它最近的簇中心所在的簇中,从而形成k个簇;

步骤3:重新计算簇中心,即对于每个簇,找到该簇的一个样本点,称为medoid,使得该簇中所有其他点到该样本点的距离之和最小;

步骤4:如果簇中心没有任何改变,算法停止,否则回到步骤2


实例:

完整代码如下:mo_2.m聚类分析算法实例(k-means和k-medois)matlab实现

假设3个样本集合:set1,set2,set3,每个集合中包含1000个样本:

第一个集合所使用的正态分布参数:均值向量为[0 0],协方差矩阵为[0.5 0; 0 0.5];

第二个集合所使用的正态分布参数:均值向量为[2 3],协方差矩阵为[0.6 0.1; 0.1 0.6];

第三个集合所使用的正态分布参数:均值向量为[-2 3],协方差矩阵为[0.5 -0.1; -0.1 0.5];

使用scatter函数将这3个集合中的点显示在一幅图中:

mul = [0 0];
SIGMA = [0.5 0; 0 0.5];
set1 = mvnrnd(mul,SIGMA,1000);
scatter(set1(:,1),set1(:,2),'r+');
hold on;
mul = [2 3];
SIGMA = [ 0.6 0.1; 0.1 0.6];
set2 = mvnrnd(mul,SIGMA,1000);
scatter(set2(:,1),set2(:,2),'b*');
hold on;
mul = [-2 3];
SIGMA = [ 0.5 -0.1; -0.1 0.5];
set3 = mvnrnd(mul,SIGMA,1000);
scatter(set3(:,1),set3(:,2),'g.');

三个样本簇

将上述3个样本集合并,放到样本集set中;然后编程实现k-means,此处并没有使用matlab自带的kmeans得到结果。

%%
figure;
set=[set1;set2;set3];
[u,re]=KMeans(set,3);
[m,n]=size(re);
for i=1:m 
    if re(i,3)==1   
         scatter(re(i,1),re(i,2),'ro'); 
    elseif re(i,3)==2
         scatter(re(i,1),re(i,2),'go'); 
    else 
         scatter(re(i,1),re(i,2),'bo'); 
    end
end
%% k-means
function [u,re]=KMeans(data,N)   
    [m,n]=size(data);   
    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();  
       end      
    end
   
    while 1
        pre_u=u;          
        for i=1:N
            tmp{i}=[];     
            for j=1:m
                tmp{i}=[tmp{i};data(j,:)-u(i,:)];
            end
        end
        
        quan=zeros(m,N);
        for i=1:m      
            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

k-means分类结果

编程实现k-kmedoids,此处并没有使用matlab自带的kmedoids得到结果。

%% k-kmedoids
k=3;  
[num,z]=size(set);
C_temp=zeros(k,2);  
if k<num  
   randC=randperm(num);  
   randC=randC(1:k);  
   for i=1:k  
       C_temp(i,:)=set(randC(1,i),:);  
   end  
    for j=1:k  
       set(randC(1,j),:)=zeros(1,2);  
    end    
    idZero=find(set(:,1)==0);  
    [i1,j1]=find(set==0);  
    row=unique(i1);  
    set(row,:)=[];  
   cluster=cell(k,1,1);   
   for m=1:k  
       cluster{m}=C_temp(m,:);  
   end    
   for i=1:num-k  
       minValue=1000000;
       minNum=-1; 
       for j=1:k  
           if minValue>sqrt((set(i,1)-C_temp(j,1))*(set(i,1)-C_temp(j,1))+(set(i,2)-C_temp(j,2))*(set(i,2)-C_temp(j,2)))  
               minValue=sqrt((set(i,1)-C_temp(j,1))*(set(i,1)-C_temp(j,1))+(set(i,2)-C_temp(j,2))*(set(i,2)-C_temp(j,2)));  
               minNum=j;  
           end  
       end  
       cluster{minNum}=cat(1,cluster{minNum},set(i,:));         
   end  
   flag=1;  
   count=0;  
   while flag==1  
       randC=randperm(num-k);  
       randC=randC(1:1);    
       o_random=set(randC,:);  
       recordN=0;  
       for i=1:k        
           for j=1:size(cluster{i},1)        
               cc=cluster{i}(j,:);  
               cc=cc-o_random;  
               if cc==0  
                   recordN=i;  
                   break;  
               end  
           end  
       end  
       set(randC,:)=[];  
       o=cluster{recordN}(1,:);  
       o_rand_sum=0;  
       o_sum=0;  
       for i=1:length(set)  
           o_rand_sum=o_rand_sum+sqrt((set(i,1)-o_random(1,1))*(set(i,1)-o_random(1,1))+(set(i,2)-o_random(1,2))*(set(i,2)-o_random(1,2)));  
           o_sum=o_sum+sqrt((set(i,1)-o(1,1))*(set(i,1)-o(1,1))+(set(i,2)-o(1,2))*(set(i,2)-o(1,2)));  
       end  
       if o_rand_sum<o_sum  
           cluster{recordN}(1,:)=o_random;  
           set=cat(1,set,o);  
           for i=1:k  
               c=cluster{i}(1,:);  
               cluster{i}=[];  
               cluster{i}=c;  
           end   
           for i=1:num-k  
               minValue=1000000; 
               minNum=-1; 
               for j=1:k  
                   if minValue>sqrt((set(i,1)-C_temp(j,1))*(set(i,1)-C_temp(j,1))+(set(i,2)-C_temp(j,2))*(set(i,2)-C_temp(j,2)))  
                       minValue=sqrt((set(i,1)-C_temp(j,1))*(set(i,1)-C_temp(j,1))+(set(i,2)-C_temp(j,2))*(set(i,2)-C_temp(j,2)));  
                       minNum=j;  
                   end  
               end  
               cluster{minNum}=cat(1,cluster{minNum},set(i,:));         
           end             
       else  
           set=cat(1,set,o_random);  
           flag=0;  
       end  
       count=count+1;  
   end     
   for i=1:k  
       scatter(cluster{i}(:,1),cluster{i}(:,2),'filled');  
       hold on  
   end     
end  

k-medoids

 实例2:

set1 = mvnrnd([0 0],[0.1 0; 0 0.1],2000);

set2 = mvnrnd([1.5 1],[0.07 0; 0 1],2000);

set = [set1; set2];

用之前的k-means算法对样本集set 进行聚类

set1=mvnrnd([0 0],[0.1 0; 0 0.1],2000);
scatter(set1(:,1),set1(:,2),'r+');
axis equal;
hold on;
set2 = mvnrnd([1.5 1],[0.07 0; 0 1],2000);
scatter(set2(:,1),set2(:,2),'b*');
axis equal;
set = [set1; set2];
%%
figure;
hold on;
axis equal;
[u,re]=KMeans(set,2);
[m,n]=size(re);
for i=1:m 
    if re(i,3)==1   
         scatter(re(i,1),re(i,2),'ro'); 
    elseif re(i,3)==2
         scatter(re(i,1),re(i,2),'go'); 
    end
end
 
%% k-means
function [u re]=KMeans(data,N)   
    [m n]=size(data);  
    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(); 
       end      
    end
    while 1
        pre_u=u;         
        for i=1:N
            tmp{i}=[];     
            for j=1:m
                tmp{i}=[tmp{i};data(j,:)-u(i,:)];
            end
        end
        quan=zeros(m,N);
        for i=1:m      
            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

初始簇图像

聚类分析后的图像

结果产生明显偏差,原因如下:

k- 均 值 聚 类 的 缺 点

 

### 回答1: k-medoids聚类算法是一种基于中心点(称为"medoid")的聚类算法。它和k-means算法类似,但是k-medoids使用样本点作为聚类中心,而k-means使用质心(即均值)。 在matlab中,可以使用pam()函数实现k-medoids聚类算法。该函数是由Kaufman和Rousseeuw在1987年提出的Partitioning Around Medoids(PAM)算法实现。 使用示例如下: [IDX,C,SUMD,K] = pam(X,k) 其中X是待聚类的数据矩阵, k是聚类的类别数。 IDX表示每个样本所属的类别, C表示每个类别的中心点。 ### 回答2: k-medoids聚类算法是一种常见的聚类算法,可以在不知道数据分布情况和真实标签的情况下,对数据进行聚类分析,找出其中的潜在分组。与k-means算法相比,k-medoids算法采用与数据点实际值相对应的代表点(称为medoids)作为簇心,而不是通过计算平均值(质心)得出代表点,从而使聚类结果更加稳健。 在Matlab中,可使用Statistics and Machine Learning Toolbox中的kmedoids函数来实现k-medoids聚类。该函数的调用格式为: [idx,medoids,iter] = kmedoids(X,k) 其中,X是大小为n x p的数据矩阵,其中n表示数据点数,p表示特征数;k是指定的簇数。函数返回三个值,idx是大小为n x 1的向量,表示每个数据点所属的簇;medoids是大小为k x p的矩阵,表示每个簇的medoid;iter是迭代次数。 在实际应用中,使用k-medoids算法时需要根据具体数据集选择合适的k值,并进行初始化。通常的做法是多次(如10次)运行k-medoids算法,并从这些运行结果中选择最优的聚类结果,可利用常见的内部聚合度和外部聚合度二者评价聚类效果的方法来指导选择最优聚类结果。无论采取何种评价标准,均需要人工介入,即k值的选择和初始情况的确定等,所以实际应用中需要进行相应的调试和优化。 总之,k-medoids聚类算法是一种常用且有效的聚类算法,能够满足聚类任务中的不同需求。在实际场景中,可根据具体数据集进行参数选择和调优,并结合其他技术手段进行聚类结果评估和应用。 ### 回答3: K-medoids是一种基于距离的聚类算法,与K-means类似,但是它将聚类中心限定为样本点,而不是实际的数据点。这使得K-medoids算法更加鲁棒,因为它不太容易受到离群值的影响。 在Matlab中, 要实现K-medoids算法,首先需要选择K值和距离度量。在选择K值时,可以使用手肘法或轮廓系数来寻找最佳的K值。而在选择距离度量时,常用的有欧式距离和曼哈顿距离。在确定K值和距离度量后,就可以开始K-medoids实现。 K-medoids算法实现过程: 1. 随机选择K个样本点作为聚类中心; 2. 将每个样本点分配给与其距离最近的聚类中心; 3. 计算每个聚类中心与其它非聚类中心的总距离,并将其中距离最小的样本点作为新的聚类中心; 4. 重复上述步骤,直到聚类中心不再发生变化或达到最大迭代次数。 K-medoids算法的优点: 1. 不需要事先设定簇数量; 2. 更加鲁棒,对离群点不太敏感; 3. 结果可解释性高。 K-medoids算法的缺点: 1. 对于大数据集,时间复杂度较高; 2. 对初始聚类中心的选择较为敏感; 3. 在处理高维数据时,由于维度灾难问题,K-medoids算法效果不如K-means算法。 总的来说,K-medoids聚类算法可以应用于不同领域的数据挖掘和机器学习问题中,如文本聚类、图像分割、生物信息学等。在特定的问题场景下,选择合适的聚类算法很关键,K-medoids算法是一个不错的选择。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙子树下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值