k-中心点算法(k-medoids)及Matlab代码实现

k-中心点算法(k-medoids)及Matlab代码

1. 提出:

上篇文章给出了 k-means算法的具体思想和代码实现:https://blog.csdn.net/qiu1440528444/article/details/80611942

k-means算法是每次选择簇的均值作为新的中心点,迭代直到簇中心不再变化(趋于稳定)。其缺点是对离群点特别敏感,因为一个很大的极端值对象会扭曲数据分布,使簇均值严重偏离;于是我们考虑新的簇中心不用均值表示而是选择簇内的某个对象,只要使总的代价降低就行。。

2. 优化后的算法:

PAM(围绕中心点的划分),具有代表性的k-medoids算法。

算法思想: 迭代选出簇中位置最中心的对象,试图将N个对象给出k个划分。
具体:

  • 最初随机选择k个对象作为中心点,并代表初始簇,然后根据欧氏距离划分其余所有对象到各个中心点所代表的簇,得到初始簇划分。

  • 该算法反复利用数据D中所有非代表对象替换当前代表对象,试图找出更好的中心点,以改进聚类质量。 中心点也叫代表对象,其他对象叫非代表对象。

  • 在每次迭代中,所有可能的对象都被分析,每一对替换中的一个对象是中心点,而另一个是非代表对象。如果一个当前的中心点被一个非代表对象所替换,代价函数将计算平方误差值所产生的差别;替换的总代价是所有非中心对象去替换所产生的代价之和。

  • 如果总代价为负值,则实际的平方误差将会减少,则代表对象Oi可被非代表对象Oh替换。

中心点的定义:簇中某点的平均差异性在这一簇中所有点中最小。

3. 算法描述:

输入:

  • k:簇的数目;
  • N:包含N个对象的数据;

输出:k个簇,使得所有对象与其距离最近的中心点的相异度总和最小。

  1. 初始化:随机选择N个点中的k个点作为初始中心点;
  2. 将其余各点根据欧式距离划分到这k个类别中;
  3. 当损失值减少时:
    对于每个中心点o,对于每个非中心点m;
    a.)交换o和m,重新计算损失(损失值为,所有点到中心点的距离和);
    b.)如果总的损失增加则不进行交换;

另外一种解释:
1. 任选k个对象作为初始簇中心;
2. 划分其余对象给离它最近的中心点所表示的簇;
3. 选择一个未被选择的中心点Oi;
4. 选择一个未被选择的非中心点Oh;
5. 计算Oh替换Oi所产生的总代价并记录在S中;
6. Utill 所有非中心点都被选择过;
7. Utill 所有中心点都被选择过;
8. if 在S中的所有替换所产生的总代价有负值存在,then 找出并用该非中心点替换对应的中心点,形成一个新的k个中心点的集合;
9. Utill 没有再发生簇的重新分配,即所有的S都大于0.

总的来说:与k均值算法一样,初始代表对象任意选取,反复用一个非代表对象替换一个代表对象,试图找出更好的中心点,以改进聚类质量。一个中心点对象被可以产生误差平方和减少的对象替换,再一次迭代中产生的最佳对象集合成为下次迭代中心点。

为判定一个非代表对象Oh是否是当前一个代表对象Oi的好的替换,对每个非中心点对象Oj,有以下四种情况:

  • 第一种情况:Oj当前隶属于中心点对象Oi。如果Oi被Oh所代替作为中心点,且Oj离某个中心点Om最近,i≠m,那么Oj被重新分配给Om。

  • 第二种情况:Oj当前隶属于中心点对象Oi。如果Oi被Oh所代替作为中心点,且Oj离Oh最近,那么Oj被重新分配给Oh。

  • 第三种情况:Oj当前隶属于中心点Om,m≠i。如果Oi被Oh代替作为中心点,而Oj依然离Om最近,那么对象的隶属不发生变化。

  • 第四种情况:Oj当前隶属于中心点Om,m≠i。如果Oi被Oh代替作为一个中心点,且Oj离Oh最近,那么Oi被重新分配给Oh。

每当重新分配发生时,绝对误差E的差会对代价函数有影响。因此,如果一个当前的代表对象被非代表对象所替换时,则代价函数就计算绝对误差值的差。交换的总代价是所有非代表对象所产生的代价之和。如果总代价为负,则实际的绝对误差和会减少,Oi可以被Oh所替换作为新中心点。如果代价为正,则本次迭代无变化。

总代价定义如下:
这里写图片描述

其中,TCih表示中心点Oi被非中心点Oh替换后产生的总代价。Cjih表示,Oj在Oi被Oh替换后产生的代价。下面将介绍上述四种情况中代价函数的计算公式,其中引用到的符号有:Oi和Om是两个原中心点,Oh将替换Oi作为新的中心点。

代价函数计算图示:
这里写图片描述

Matlab代码:

k_medoids.m文件

clc;  
clear;  
%读取数据文件,生成点矩阵  
fileID = fopen('E:\MySoftware\matlabWorks\textKMediods\sample.txt');  
 C=textscan(fileID,'%f %f'); %textscan函数读取数据
 fclose(fileID); %关闭一个打开的fileID的文件
 %显示数组结果  
 %celldisp(C);  
 %将cell类型转换为矩阵类型,这里只假设原数据为二维属性,且是二维的坐标点  
 CC_init=cat(2,C{1},C{2});%用来保存初始加载的值  
 CC=CC_init;  %cat函数用于连接两个矩阵或数组
  %获得对象的数量  
 num=length(C{1});  
 %显示初始分布图  
 grid on;%显示表格
 scatter(C{1},C{2},'filled');  %filled为实心圆,该函数可以把C中所有坐标的点都画出来。
 %%设置任意k个簇  
k=3;  
%临时存放k个中心点的数组  
C_temp=zeros(k,2);  
%判断所设置的k值是否小于对象的数量  
if k<num  
    %产生随机的k个整数  
   randC=randperm(num);  
   randC=randC(1:k);  
   %从原数组中提出这三个点     
   for i=1:k  
       C_temp(i,:)=CC(randC(1,i),:);  
   end  
   %将原数组中的这三个点清空  
    for j=1:k  
       CC(randC(1,j),:)=zeros(1,2);  
    end    
    idZero=find(CC(:,1)==0);  
    %删除为零的行  
    [i1,j1]=find(CC==0);  
    row=unique(i1);  
    CC(row,:)=[];  
   %分配k个二维数组,用来存放聚类点  
   %分配行为k的存储单元  
   cluster=cell(k,1,1);   
    %将剔除的三个点加入到对应的三个存储单元,每个单元的第一行置为0,为了存储相对应的簇中心  
   for m=1:k  
       cluster{m}=C_temp(m,:);  
   end    
   %计算其他点到这k个点的距离,然后分配这些点,第一次遍历  
   for i=1:num-k  
       %分别计算到三个点的距离         
       minValue=1000000;%最小值,要根据实际情况设定该值  
       minNum=-1;%最小值序号  
       for j=1:k  
           if minValue>sqrt((CC(i,1)-C_temp(j,1))*(CC(i,1)-C_temp(j,1))+(CC(i,2)-C_temp(j,2))*(CC(i,2)-C_temp(j,2)))  
               minValue=sqrt((CC(i,1)-C_temp(j,1))*(CC(i,1)-C_temp(j,1))+(CC(i,2)-C_temp(j,2))*(CC(i,2)-C_temp(j,2)));  
               minNum=j;  
           end  
       end  
       cluster{minNum}=cat(1,cluster{minNum},CC(i,:));         
   end  
   %随机选择p点  
   flag=1;  
   count=0;  
   while flag==1  
       randC=randperm(num-k);  
       randC=randC(1:1);    
       o_random=CC(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  
       %将选择的随机点从点集中删除  
       CC(randC,:)=[];  
       %计算替换代价  
       o=cluster{recordN}(1,:);  
       o_rand_sum=0;  
       o_sum=0;  
       for i=1:length(CC)  
           o_rand_sum=o_rand_sum+sqrt((CC(i,1)-o_random(1,1))*(CC(i,1)-o_random(1,1))+(CC(i,2)-o_random(1,2))*(CC(i,2)-o_random(1,2)));  
           o_sum=o_sum+sqrt((CC(i,1)-o(1,1))*(CC(i,1)-o(1,1))+(CC(i,2)-o(1,2))*(CC(i,2)-o(1,2)));  
       end  
       %如果随机选择的点的代价小于原始代表点的代价,则替换该代表点,然后重新聚类  
       if o_rand_sum<o_sum  
           cluster{recordN}(1,:)=o_random;  
           %将代表点放入对象集  
           CC=cat(1,CC,o);  
           %对所有对象重新进行聚类  
           %将cluster除第一行之外的数据全部清空  
           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((CC(i,1)-C_temp(j,1))*(CC(i,1)-C_temp(j,1))+(CC(i,2)-C_temp(j,2))*(CC(i,2)-C_temp(j,2)))  
                       minValue=sqrt((CC(i,1)-C_temp(j,1))*(CC(i,1)-C_temp(j,1))+(CC(i,2)-C_temp(j,2))*(CC(i,2)-C_temp(j,2)));  
                       minNum=j;  
                   end  
               end  
               cluster{minNum}=cat(1,cluster{minNum},CC(i,:));         
           end             
       else  
           %将随机点重新放入对象集  
           CC=cat(1,CC,o_random);  
           %终止循环  
           flag=0;  
       end  
       count=count+1;  
   end     
   %绘制聚类结果  
   for i=1:k  
       scatter(cluster{i}(:,1),cluster{i}(:,2),'filled');  
       hold on  
       grid on;%显示表格
   end     
end  

运行结果如下:

当K=3时:
这里写图片描述

当K=4时:

这里写图片描述

参考文献及例子:

http://dy.163.com/v2/article/detail/CUSKS65T0511HOMM.html

欢迎扫描提问码交流
CSDN代码下载地址:

https://download.csdn.net/download/qiu1440528444/10486659

评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值