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

聚类算法通常会得到一种分类,将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;  

}  

    原文作者:聚类算法
    原文地址: https://blog.csdn.net/dreamzuora/article/details/52790347
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞