数据挖掘 实验五、k-均值聚类算法
本次数据挖掘实验围绕k-均值聚类算法展开,旨在通过编程实现该算法并验证其效果。以下是总结:
实验目的
- 掌握k-均值聚类的基本原理及实现方法。
- 熟悉VC++编程工具的应用。
- 通过编程验证k-均值算法对给定数据集的聚类效果。
实验原理- k-均值聚类是一种基于形心的划分技术,在迭代过程中不断更新簇中心(质心),直到满足终止条件(如质心不再变化或误差平方和最小)。
- 距离度量采用欧几里得距离,默认使用数据向量的重心作为簇中心。
- 终止条件包括:对象重新分配不再发生、质心不再变化或误差平方和局部最小化。
实验内容- 流程图:绘制了程序运行流程图,直观展示k-均值聚类的工作原理。
- 编程实现:
- 读取并处理数据集D={D1, D2, D3}。
- 初始化3个质心(随机选取)。
- 迭代更新簇中心直至满足终止条件。
- 屏蔽实时输出结果(如第1次至第3次迭代结果)。
- 输出最终各簇中心及其对应的样本点分布情况。
关键代码
包括初始化质心函数、计算距离函数、归类函数及更新质心函数等核心逻辑模块。
实验结果
程序成功完成对测试数据集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值。
基于各簇内所有样本点的位置信息重新确定新的质心位置。
当算法满足终止条件时停止迭代运算。
算法可能采用以下任一终止准则:
第一种准则为"没有(或最少)样本点被重新分配至不同的簇";
第二种准则是"没有(或最少)质中心发生位移";
第三种准则是"目标函数达到局部极小状态"。
- 实验内容
依据k均值聚类算法的具体运算流程,在k取值为3的情况下绘制相应的程序流程图。基于k均值程序流程图的设计与实现,在编程过程中构建完整的k均值聚类算法模型。在实验报告中详细展示k均值聚类过程中的关键阶段截图,并清晰标注各簇群的演变轨迹。在报告中明确阐述实验代码中初始质心选定的原则、终止条件设置的标准以及所采用的距离度量方法,并对其相关参数进行详细说明。
- 实验步骤
编程实现如下功能:
首先将属性向量作为实验数据输入至数据集D={D1, D2, D3}中进行处理;
请通过基于程序流程图的方式实现k-均值聚类算法,并使用上述实验数据进行验证;
在适当的时间点暂停迭代过程并实时显示结果信息;具体包括簇中心位置的变化以及基于距离最近的邻居分类结果等。
- 程序框图

- 关键代码
#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个类别后进行运算。
以上就是数据挖掘地五个实验内容了(地下划线好浅啊)
