Advertisement

数据挖掘 实验五、k-均值聚类算法

阅读量:

本次数据挖掘实验围绕k-均值聚类算法展开,旨在通过编程实现该算法并验证其效果。以下是总结:
实验目的

  • 掌握k-均值聚类的基本原理及实现方法。
  • 熟悉VC++编程工具的应用。
  • 通过编程验证k-均值算法对给定数据集的聚类效果。
    实验原理
  • k-均值聚类是一种基于形心的划分技术,在迭代过程中不断更新簇中心(质心),直到满足终止条件(如质心不再变化或误差平方和最小)。
  • 距离度量采用欧几里得距离,默认使用数据向量的重心作为簇中心。
  • 终止条件包括:对象重新分配不再发生、质心不再变化或误差平方和局部最小化。
    实验内容
  • 流程图:绘制了程序运行流程图,直观展示k-均值聚类的工作原理。
  • 编程实现:
  1. 读取并处理数据集D={D1, D2, D3}。
  2. 初始化3个质心(随机选取)。
  3. 迭代更新簇中心直至满足终止条件。
  4. 屏蔽实时输出结果(如第1次至第3次迭代结果)。
  5. 输出最终各簇中心及其对应的样本点分布情况。
    关键代码
    包括初始化质心函数、计算距离函数、归类函数及更新质心函数等核心逻辑模块。
    实验结果
    程序成功完成对测试数据集D的聚类任务:
  • 第1次迭代后初始质心中各簇分配明确。
  • 第2次及第3次迭代进一步优化质心位置直至收敛。
  • 终止条件满足时输出最终各簇的结果图像及详细信息。
    结论
    k-均值聚类是一种高效的迭代式聚类方法,在合理设置参数下能够准确划分给定数据集为指定簇数(本例为3)。该方法适用于处理多维空间中的复杂数据分布问题,并可扩展至更高维空间应用中。

Data Mining: 第五次实验——K-means Clustering Algorithm]()

一、 实验目的:
(1) 熟悉 VC++编程工具和 k-均值聚类算法。
(2) 在训练样本集上用 VC++编程工具编写用于 k-均值聚类的程序,对任务 相关数据运行 k-均值聚类算法,调试实验。
(3) 掌握距离计算方法和聚类的评价准则。
(4) 写出实验报告。
二、 实验原理:
1、k-均值聚类
k-均值聚类是一种基于形心的划分技术,具体迭代的计算步骤如下:

在属性向量空间中随机选取k个初始质心位置。
依次计算数据集D中每个样本点Ti(i=1,…,n)与各质心中对应的距离度量Dist(i,j)(j=1,…,k),并将其归入最小距离所对应的簇Cj中(即Ti∈Cj)。其中j=argmin(Dist(i,j))表示使得Dist(i,j)取得最小值的j值。
基于各簇内所有样本点的位置信息重新确定新的质心位置。
当算法满足终止条件时停止迭代运算。
算法可能采用以下任一终止准则:
第一种准则为"没有(或最少)样本点被重新分配至不同的簇";
第二种准则是"没有(或最少)质中心发生位移";
第三种准则是"目标函数达到局部极小状态"。

  1. 实验内容

依据k均值聚类算法的具体运算流程,在k取值为3的情况下绘制相应的程序流程图。基于k均值程序流程图的设计与实现,在编程过程中构建完整的k均值聚类算法模型。在实验报告中详细展示k均值聚类过程中的关键阶段截图,并清晰标注各簇群的演变轨迹。在报告中明确阐述实验代码中初始质心选定的原则、终止条件设置的标准以及所采用的距离度量方法,并对其相关参数进行详细说明。

  1. 实验步骤
    编程实现如下功能:

首先将属性向量作为实验数据输入至数据集D={D1, D2, D3}中进行处理;
请通过基于程序流程图的方式实现k-均值聚类算法,并使用上述实验数据进行验证;
在适当的时间点暂停迭代过程并实时显示结果信息;具体包括簇中心位置的变化以及基于距离最近的邻居分类结果等。

  1. 程序框图
在这里插入图片描述
  1. 关键代码
复制代码
    #include<iostream> 
    #include<string> 
    #include<fstream> 
    #include<algorithm> 
    #include <math.h> 
    using namespace std; 
    #define k 3 //聚类数 
    #define n 2 //数据维数 
    #define size 30 //数据大小  
    typedef struct { //定义存储结构
    double d[n];  
    double distance[k]; 
    }Data;  
    typedef struct {  
    Data center[k]; // 即簇类中心 
    int cluster[k][size]; //簇数组  
    int cluster_num[k];// 簇类中一组数据的编号 
    Data old_center[k];  
    int isend[k][n]; //各簇类中心是否相等标示值 
    int is; 
    }Tdata;  
    Data data[size]; 
    Tdata td;  
    void Init() //创建与读取数据
    {  
    char name1[50]="data.txt";  
    ifstream infile;  
    cout<<"要打开的文件为:data.txt"<<endl; 
    infile.open(name1,ios::in); 
    if(infile.fail()) 
    {  
        cout << "error open!" << endl; 
        exit(1);
    }  
    for(int i = 0;i < size;i++) 
        for(int j = 0;j<n;j++) 
            infile>>data[i].d[j]; 
    cout<<"the data are:"<<endl;  
    for(int i=0;i<size;i++)//输出要处理的数据 
    {  
        for(int j = 0;j<n;j++) 
            cout<<data[i].d[j]<<" ";   
        cout<<endl; 
    }  
    infile.close();//关闭文件 
    }  
    void Init_center() //初始化质心
    {  
    for(int i = 0;i<k;i++)
    {  
        cout<<"初始质心"<<i+1<<":"<<endl; 
        for(int j = 0;j<n;j++) 
        {  
            td.center[i].d[j] = data[i].d[j]; 
            cout<<td.center[i].d[j]<<" "; 
        }  
        cout<<endl; 
    } 
    }  
    double Euclid(int x, int y) //计算一组数组到质心的欧几里得距离
    {  
    double distance = 0; 
    for(int i = 0; i < n; i++)  
        distance += pow((data[x].d[i] - td.center[y].d[i]), 2); 
    return sqrt(distance); 
    }  
    void calculate_distance()// 计算数据到K个质心的欧几里德距离
    {  
    int i, j;  
    for(i = 0; i < size; i++) 
        for(j = 0; j < k; j++)
            data[i].distance[j] = Euclid(i, j); //i 表示第几个数组j 表示距离第几个质心   
       
    }  
    void new_cluster() //将数据进行簇归类
    {  
    int i, j;  
    double min;  
    for(i = 0; i < k; i++) //初始化编号 
        td.cluster_num[i] = 0; 
    for(i = 0; i < size; i++)
    {  
        int index = 0; //找出最小的欧几里德距离编号 
        min = data[i].distance[0];  
        for(j = 1; j < k; j++)
        { // 筛选到簇心欧几里德最小的值 
            if(data[i].distance[j] < min)
            { 
                min = data[i].distance[j]; 
                index = j; 
            } 
        }  
    td.cluster[index][td.cluster_num[index]++] = i; //划分簇集  
    } 
    }  
    void new_center() //更新质心
    {  
    int i, j, m; 
    double sum;  
    for(i = 0; i < k; i++) 
        for(j = 0; j < n; j++)
        { 
            sum = 0;  
            td.old_center[i].d[j] = td.center[i].d[j]; 
            for(m = 0; m < td.cluster_num[i]; m++) 
              sum += data[td.cluster[i][m]].d[j]; // 第i 个簇的第j 维数的所有数据和 
            td.center[i].d[j] = sum / td.cluster_num[i]; // 取平均数得到新的簇中心 
        } 
    }  
    void comp( ) //比较质心
    {  
    int i , j,m = 0; 
    new_center(); //更新质心
    for(i = 0;i<k;i++)
        for(j=0;j<n;j++)
            td.isend[i][n]=td.old_center[i].d[j] != td.center[i].d[j]?0:1;
    
    for(i = 0;i<k;i++) 
        for(j=0;j<n;j++)  
            td.is=td.isend [i][n]*td.is; 
    
    td.is=td.is==0?1:0; //确定终止条件
    }  
    void output_info( ) //输出结果函数
    {  
    int i, j, m;  
    for(i = 0; i < k; i++)
    {  
        cout<<"质心"<<i+1<<":"<<endl; 
        for(m = 0; m < n; m++)  
            cout<<td.center[i].d[m]<<" "; 
        cout<<endl;  
        cout<<"簇类"<<i+1<<":"<<endl; 
        for(j = 0; j < td.cluster_num[i]; j++)
        { 
            for(m = 0; m < n; m++)
                cout<<data[td.cluster[i][j]].d[m]<<" "; 
            cout<<endl; 
        } 
    } 
    }  
    int main () 
    {  
    int count = 0;  
    Init();  //读取文件
    Init_center(); //选择初始质心
    td.is =1; 
    while (td.is) //确定终止条件
    {  
        calculate_distance(); //选择距离函数,进行欧几里得计算
        new_cluster(); //将数据进行簇归类
        count++;  
        cout<<"______________________________________________________"<<endl; 
        cout<<"第"<<count<<"次聚类:"<<endl; 
        output_info();  //输出结果
        comp(); //比较质心 
    }  
    system( "PAUSE "); 
    return 0; 
    }

四、实验结果:

实验数据文件为data.txt

处理结果

在这里插入图片描述

(首先读入文件,并初始化质心)

在这里插入图片描述

(进行第一次聚类计算)

在这里插入图片描述

(进行第二次聚类计算)

在这里插入图片描述

该程序通过自动加载文件内容并确定初始质心位置。随后使用欧几里得距离进行计算以实现3-均值聚类算法,并采用迭代优化策略直至达到预设终止条件后输出最终聚类结果。

3. 实验结论
该算法属于迭代优化方法。其特点是可以无需终止条件地运行,并且能够将样本划分为K个类别后进行运算。



以上就是数据挖掘地五个实验内容了(地下划线好浅啊)

全部评论 (0)

还没有任何评论哟~