最大最小距离算法(K-MEANS K-medoids )聚类算法的结合运用

26 篇文章 0 订阅
15 篇文章 1 订阅


聚类算法通常会得到一种分类,将n个点聚合成k类,同一聚类(即插槽簇)中的对象相似度较高;而不同类中的对象相似度较小。
聚类算法的基本流程如下:
(1)从n个节点中选择 k 个节点作为初始聚类中心。(2)将剩余节点根据它们与这k个聚类中心的代价大小,分别将它们分配给与其代价最小的(聚类中心所代表的)聚类。(3)更新聚类的聚类中心。不断重复(2)(3)这一过程将剩下其它节点分配完毕。(4)排序,将各聚类按照聚类间节点代价和高低降序排列。
         下面详细解释上述步骤。
(1)从n个节点中选择 k 个节点作为初始聚类中心
由于K-MEANS算法(一种典型的聚类算法,随机确定k个聚类中心)有缺点:产生类的大小相差不会很大,对于脏数据很敏感。所以采用最大最小距离算法确定这k个聚类中心。最大最小距离算法是识别领域中的一种试探性算法。思想是取尽可能离得远的对象作为聚类中心,以避免聚类中心过于邻近。
步骤如下:
1.计算各节点到其他节点的最大代价总和,取满足最大的点i(可理解为距其他节点最远)为聚类1的中心点。
2.计算其他节点到点的最大代价,取满足最大的i点为聚类2的中心点。
3. 计算其他节点到、点的最大代价,取满足最大的i点为聚类3的中心点。
4. 计算其他节点到、、点的最大代价,取满足最大的i点为聚类4的中心点。
以此类推直到找到k个聚类中心点。
 
(2)将剩余节点根据它们与这些聚类中心的代价大小,分别将它们分配给与其代价最小的(聚类中心所代表的)聚类
依次将不是聚类中心点的节点分配到k个聚类中去。若某类中已经有两个节点,则在分配进入该节点之后还要进行更新聚类中心点的操作(见后(3)详解)。
 
(3)更新聚类的聚类中心
当某个聚类中存在3个或3个以上节点时需要更新此聚类中心点。采用K-medoids算法中的更新聚类中心方式。在 K-medoids算法中,我们将从当前聚类中选取这样一个点——它到其他所有(当前聚类中)点的代价之和最小——作为中心点。
 
(4)排序,将各聚类按照聚类间代价高低降序排列。
[cpp] view plain copy
#include <stdio.h>  
#include <stdlib.h>  
#include <iostream>  
#include <math.h>  
#include "CLSlotClustering.h"  
#include "CLZone.h"  
#include "CLVMMinKCut.h"  
  
using namespace std;  
  
CLSlotClustering::CLSlotClustering()  
{  
}  
  
CLSlotClustering::~CLSlotClustering()  
{  
}  
  
int CLSlotClustering::Find(int i)  
{  
    int j;  
    if (m_Parent[i]==i)  
    {  
        return  i;  
    }  
    j=m_Parent[i];  
    Find(j);  
    return 0;  
}  
  
CLZone CLSlotClustering::SlotClustering(int C[][MAXNUMBER],int n,int k,int flag)  
{  
    m_VexOfMaxCost=0;                               //初始化  
    m_Flag=0;  
    m_Number=(-1);  
    for (int i = 0; i < MAXNUMBER; i++)  
    {  
        m_Parent[i]=i;  
        m_VexOfCostSum[i]=0;  
        for (int j = 0; j < MAXNUMBER; j++)            
        {  
            m_C[i][j]=0;  
        }  
    }  
    m_k=k;  
    m_n=n;  
    //cout<<"m_C:"<<endl;  
    for (int i = 0; i < n; i++)  
    {  
        for (int j = 0; j < n; j++)  
        {  
            m_C[i][j]=C[i][j];                      //读入代价矩阵  
            //cout<<m_C[i][j]<<"\t";  
        }  
        //cout<<"\n";  
    }  
    //Sleep(3000);  
  
    FindCenter();  
    if (!flag)  
    {  
        Clusting();  
    }  
    Sort();  
    return **m_MyZone;  
}  
int CLSlotClustering::FindCenter()              //找k个聚合类的中心点  
{  
    for (int i = 0; i < m_n; i++)  
    {  
        for (int j = 0; j < m_n; j++)  
        {  
            m_VexOfCostSum[i]+=m_C[i][j];  
        }  
        if (m_VexOfCostSum[i]>m_Flag)  
        {  
            m_VexOfMaxCost=i;  
            m_Flag=m_VexOfCostSum[i];  
        }  
    }  
    m_MyZone[0]= new CLZone;  
    m_MyZone[0]->m_Center=m_VexOfMaxCost;        //第一个中心点  
    m_MyZone[0]->m_Size=1;  
    m_MyZone[0]->m_Member[0]=m_MyZone[0]->m_Center;  
    m_Flag=0;                                 
    m_VexOfMaxCost=0;         
    for (int l = 1; l < m_k; l++)                //找其余中心点  
    {  
        for (int k = 0; k < m_n; k++)  
        {  
            if (l>1)  
            {  
                if (l==2)  
                {  
                    m_Cost[k]=m_C[m_MyZone[0]->m_Center][k];  
                }  
                m_Cost[k]=min(m_C[m_MyZone[l-1]->m_Center][k],m_Cost[k]);    //min(Dl(l-1),Dl(l-2))  
                if (m_Flag<m_Cost[k])                                        //max(min(Dl(l-1),Dl(l-2)))  
                {  
                    m_Flag=m_Cost[k];  
                    m_VexOfMaxCost=k;  
                }  
            }  
            else                                                //第二个节点,只需要maxDl1,不需要min(Dl1,Dl2)  
            {  
                if (m_Flag<m_C[m_MyZone[0]->m_Center][k])  
                {  
                    m_Flag=m_C[m_MyZone[0]->m_Center][k];  
                    m_VexOfMaxCost=k;  
                }  
            }  
        }     
        m_MyZone[l]=new CLZone;  
        m_MyZone[l]->m_Center=m_VexOfMaxCost;                    //各类中心点  
        m_MyZone[l]->m_Size=1;  
        m_MyZone[l]->m_Member[0]=m_MyZone[l]->m_Center;  
        m_Flag=0;  
    }  
    return 0;  
}  
  
int CLSlotClustering::Clusting()  
{  
      
    m_VexOfCostSum[m_n-1]=10000;                    //临时变量  
    for (int i = 0; i < m_n; i++)  
    {  
        m_Flag=10000;  
        m_Flag_IsCenter=0;  
        for (int j = 0; j < m_k; j++)      
        {  
            if (i==m_MyZone[j]->m_Member[0])     //验证是否是首个中心点,如果是则不进行聚合操作  
            {  
                m_Parent[i]=i;  
                m_Flag_IsCenter=1;  
                break;  
            }  
            if (m_Flag>m_C[i][m_MyZone[j]->m_Center]&&m_C[i][m_MyZone[j]->m_Center]!=0)        //记录i点离某个中心最近  
            {  
                m_Flag=m_C[i][m_MyZone[j]->m_Center];  
                m_Parent[i]=Find(m_MyZone[j]->m_Center);  
                m_Number=j;  
            }  
        }  
        if (m_Flag_IsCenter==0&&m_Number!=(-1))                             //将i点聚合  
        {  
            m_MyZone[m_Number]->m_Member[m_MyZone[m_Number]->m_Size]=i;  
            (m_MyZone[m_Number]->m_Size)++;  
            if (m_MyZone[m_Number]->m_Size>2)                             //当某聚合类中数量大于2时需要检验是否要改变聚合类中心  
            {  
                for (int k = 0; k < m_MyZone[m_Number]->m_Size; k++)  
                {  
                    m_VexOfCostSum[k]=0;  
                    for (int l = 0; l < m_MyZone[m_Number]->m_Size; l++)  
                    {  
                        m_VexOfCostSum[k]+=m_C[m_MyZone[m_Number]->m_Member[k]][m_MyZone[m_Number]->m_Member[l]];  
                    }  
                    if (m_VexOfCostSum[k]<m_VexOfCostSum[m_n-1])  
                    {  
                        m_VexOfCostSum[m_n-1]=m_VexOfCostSum[k];  
                        m_MyZone[m_Number]->m_Center=m_MyZone[m_Number]->m_Member[k];  
                    }  
                }  
                //cout<<"changed--m_MyZone["<<m_Number<<"]->m_Center:"<<m_MyZone[m_Number]->m_Center<<endl;  
            }  
        }  
        m_Number=(-1);  
    }  
    return 0;  
}  
  
int CLSlotClustering::Sort()  
{  
    m_Flag=0;  
    for (int i = 0; i < m_n; i++)                        //得到各点到其他聚合类的代价和  
    {  
        m_VexOfCostSum[i]=0;  
        for (int j = 0; j < m_n; j++)                      
        {  
            if (m_Parent[i]==m_Parent[j])               //若i,j为同一个集合,则查看下一个点  
            {  
                continue;  
            }  
            else  
            {  
                m_VexOfCostSum[i]+=m_C[i][j];  
            }                             
        }  
    }  
    m_MyZone[m_k]=new CLZone;  
    for (int k = 0; k < m_k; k++)                                    //得到各类到其他类的代价和  
    {  
        m_MyZone[k]->m_SumOfCost=0;  
        for (int l = 0; l < m_MyZone[k]->m_Size; l++)  
        {  
            m_MyZone[k]->m_SumOfCost+=m_VexOfCostSum[m_MyZone[k]->m_Member[l]];             
        }  
    }  
    for (int i = 0; i < m_k; i++)                                        //各聚合类降序排序  
    {  
        for (int j = i+1; j < m_k; j++)  
        {  
            if (m_MyZone[i]->m_SumOfCost<m_MyZone[j]->m_SumOfCost)  
            {  
                m_MyZone[m_k]=m_MyZone[i];  
                m_MyZone[i]=m_MyZone[j];  
                m_MyZone[j]=m_MyZone[m_k];  
            }  
        }  
    }  
    /*for (int i = 0; i < m_k; i++) 
    { 
        cout<<"m_MyZone["<<i<<"]->m_Center:"<<m_MyZone[i]->m_Center<<"\t"<<"m_MyZone["<<i<<"]->Size:"<<m_MyZone[i]->m_Size<<"\t"<<"m_MyZone["<<i<<"]->Member:\n"; 
        for (int j = 0; j < m_MyZone[i]->m_Size; j++) 
        { 
            cout<<m_MyZone[i]->m_Member[j]<<"\t"; 
        } 
        cout<<endl; 
    }*/  
    return 0;  
}  
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值