问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

KMEANS算法。哪位高手指点一下啊。知道kmeans算法但看不懂下面代码。请尽量多注释一下啊。谢谢啦!在线等

发布网友 发布时间:2022-04-01 10:22

我来回答

1个回答

热心网友 时间:2022-04-01 11:51

程序需要一个数据文件
格式如下:
5 2 3
2 3 4 5 10 12 5 1 12 10
其中,5表示数据的数量,2表示数据的维度,3表示聚类的数量。
后面每两个实数对应一个数据点。
不过这个程序始数据维数固定为2,后来想改成4以下的任意维度,但没有改完,所以其实只能为2维。
我已经对程序做了注释。

#include < stdio.h>
#include < stdlib.h>
#include < string.h>
#include < conio.h>
#include < math.h>

#define SUCCESS 1
#define FAILURE 0
#define TRUE 1
#define FALSE 0
#define MAXVECTDIM 4 // 数据最大维数 (看来这个程序写了一半,维数实际上只能为2)
#define MAXPATTERN 1588 // 数据数量最大值
#define MAXCLUSTER 10 // 聚类最大值

// 聚类结构
struct aCluster {
double Center[MAXVECTDIM]; // 中心/引力数据对象
int Member[MAXPATTERN]; // 该聚类中数据在Pattern中的索引
int NumMembers; // 数据的数量
};

struct aVector {
double Center[MAXVECTDIM];
int Size;
};

static double Pattern[MAXPATTERN][MAXVECTDIM + 1]; // 所有数据存放在这个数组中

// 所以的东西都搁System类里面了
class System {
private :
aCluster Cluster[MAXCLUSTER]; // 聚类数组
int NumPatterns; // 输入数据的数量
int SizeVector; // 数据的维数
int NumClusters; // 数据的聚类数
void DistributeSamples(); // 根据中心聚类,重新分配数据到不同的聚类
int CalcNewClustCenters(); // 重新计算新的聚类中心
double EucNorm(int, int); // 误差准则
int FindClosestCluster(int); // 查找最接近的聚类
public :
System() {};
int LoadPatterns(char * fname); // 从文件中读取数据
void InitClusters(); // 初始化聚类
void RunKMeans(); // 执行K-Means算法
void ShowClusters(); // 显示聚类
void SaveClusters(char * fname); // 保存聚类到文件中
void ShowCenters(); // 显示聚类中心数据
};

void System::ShowCenters() {
int i;
printf("Cluster centers:\n");
for (i = 0; i < NumClusters; i++) {
Cluster[i].Member[0] = i;
printf("ClusterCenter[%d]=(%f,%f)\n", i, Cluster[i].Center[0],Cluster[i].Center[1]);
int b=0;
}
printf("\n");
}
int System::LoadPatterns(char * fname) {
FILE * InFilePtr;
int i, j;
double x;
if ( (InFilePtr = fopen(fname, "r")) == NULL)
return FAILURE;
// 读入数据的数量,维度和聚类数的数量
fscanf(InFilePtr, "%d", & NumPatterns);
fscanf(InFilePtr, "%d", & SizeVector);
fscanf(InFilePtr, "%d", & NumClusters);
// 读入数据
for (i = 0; i < NumPatterns; i++) {
for (j = 0; j < SizeVector; j++) {
fscanf(InFilePtr, "%lg", & x);
Pattern[i][j] = x;
}
}
// 打印读入的数据
printf("Input patterns:\n");
for (i = 0; i < NumPatterns; i++) {
printf("Pattern[%d]=(%2.3f,%2.3f,%d,%d)\n", i, Pattern[i][0], Pattern[i][1],Pattern[i][2], Pattern[i][3]);
}
printf("\n--------------------\n");
return SUCCESS;
}
void System::InitClusters() {
int i, j;
SizeVector=2; // 看来开始数据维数固定为2,后来想改成4以下的任意维度,但没有改完
printf("Initial cluster centers:\n");
// 把前NumClusters个数据作为NumClusters个聚类的数据中心
for (i = 0; i < NumClusters; i++) {
Cluster[i].Member[0] = i; // 记录这个数据的索引到第i个聚类中
for (j = 0; j < SizeVector; j++) {
Cluster[i].Center[j] = Pattern[i][j]; // 把这个数据作为数据中心
}
}
// 打印聚类的数据中心
for (i = 0; i < NumClusters; i++) {
printf("ClusterCenter[%d]=(%f,%f)\n", i, Cluster[i].Center[0], Cluster[i].Center[1]);
}
printf("\n");
}
void System::RunKMeans() {
int converged; // 是否收敛
int pass; // 计算的趟数
pass = 1; // 第一趟
converged = FALSE; // 没有收敛
while (converged == FALSE) { // 没有收敛的情况下反复跑
printf("PASS=%d\n", pass++); // 打印趟数
DistributeSamples(); // 重新分配数据
converged = CalcNewClustCenters(); // 计算新的聚类中心,如果计算结果和上次相同,认为已经收敛
ShowCenters(); // 显示聚类中心
}
}
// 第p个数据到第c个聚类中心的误差准则(距离的平方)
double System::EucNorm(int p, int c) {
double dist, x; // x可能是调试用,没有实际作用
int i;
dist = 0;
// 将每个维度的差的平方相加,得到距离的平方
for (i = 0; i < SizeVector; i++) {
x = (Cluster[c].Center[i] - Pattern[p][i]) *
(Cluster[c].Center[i] - Pattern[p][i]);
dist += (Cluster[c].Center[i] - Pattern[p][i]) *
(Cluster[c].Center[i] - Pattern[p][i]);
}
return dist;
}
// 查找第pat个数据的最近聚类
int System ::FindClosestCluster(int pat) {
int i, ClustID/*最近聚类的ID*/;
double MinDist/*最小误差*/, d;
MinDist = 9.9e+99; // 初始为一个极大的值
ClustID = -1;
// 依次计算3个聚类到第pat个数据的误差,找出最小值
for (i = 0; i < NumClusters; i++) {
d = EucNorm(pat, i);
printf("Distance from pattern %d to cluster %d is %f\n", pat, i, sqrt(d));
if (d < MinDist) { // 如果小于前最小值,将改值作为当前最小值
MinDist = d;
ClustID = i;
}
}
if (ClustID < 0) { // 没有找到??! —— 这个应该不可能发生,如果出现表示出现了不可思议的错误
printf("Aaargh");
exit(0);
}
return ClustID;
}

void System ::DistributeSamples() {
int i, pat, Clustid, MemberIndex;
// 将上次的记录的该聚类中的数据数量清0,重新开始分配数据
for (i = 0; i < NumClusters; i++) {
Cluster[i].NumMembers = 0;
}
// 找出每个数据的最近聚类数据中心,并将该数据分配到该聚类
for (pat = 0; pat < NumPatterns; pat++) {
Clustid = FindClosestCluster(pat);
printf("patern %d assigned to cluster %d\n\n", pat, Clustid);
MemberIndex = Cluster[Clustid].NumMembers; // MemberIndex是当前记录的数据数量,也是新加入数据在数组中的位置
Cluster[Clustid].Member[MemberIndex] = pat; // 将数据索引加入Member数组
Cluster[Clustid].NumMembers++; // 聚类中的数据数量加1
}
}

int System::CalcNewClustCenters() {
int ConvFlag, VectID, i, j, k;
double tmp[MAXVECTDIM]; // 临时记录新的聚类中心,因为需要比较,不能直接记录
char xs[255];
char szBuf[255];
ConvFlag = TRUE;
printf("The new cluster centers are now calculated as:\n");
// 逐个计算NumClusters个聚类
for (i = 0; i < NumClusters; i++) {
strcpy(xs,"");
printf("Cluster Center %d (1/%d):\n",i,Cluster[i].NumMembers);
// tmp所有维度数值清0
for (j = 0; j < SizeVector; j++) {
tmp[j] = 0.0;
}
// 计算聚类中所有数据的所有维度数值的和,为下一步计算均值做准备
for (j = 0; j < Cluster[i].NumMembers; j++) {
VectID = Cluster[i].Member[j];
for (k = 0; k < SizeVector; k++) {
tmp[k] += Pattern[VectID][k];
sprintf(szBuf,"%d ",Pattern[VectID][k]);
strcat(xs,szBuf);
}
printf("%s\n",xs); // 输出刚才计算的数据
strcpy(xs,"");
}
// 求出均值,并判断是否和上次相同
for (k = 0; k < SizeVector; k++) {
if(Cluster[i].NumMembers!=0)
tmp[k] = tmp[k] / Cluster[i].NumMembers;
if (tmp[k] != Cluster[i].Center[k]) // 如果不同,则认为没有收敛
ConvFlag = FALSE;
Cluster[i].Center[k] = tmp[k]; // 用新值代替旧值
}
printf("%s,\n", xs);
}
return ConvFlag; // 返回收敛情况
}
// 显示聚类中心数据
void System::ShowClusters() {
int cl;
for (cl = 0; cl < NumClusters; cl++) {
printf("\nCLUSTER %d ==>[%f,%f]\n", cl, Cluster[cl].Center[0],
Cluster[cl].Center[1]);
}
}
// 没有实现的函数
void System::SaveClusters(char * fname) {
}
#include <windows.h>
void main(int argc, char * argv[]) {
System kmeans;
// 如果没有提供参数,显示用法
if (argc < 2) {
printf("USAGE: KMEANS PATTERN_FILE\n");
exit(0);
}
// 参数1 为数据文件名,从中读入数据
if (kmeans.LoadPatterns(argv[1]) == FAILURE) {
printf("UNABLE TO READ PATTERN_FILE:%s\n", argv[1]);
exit(0);
}
kmeans.InitClusters();
kmeans.RunKMeans();
kmeans.ShowClusters();
kmeans.ShowCenters();
return ;
}
KMeans聚类算法,简短易懂的python代码

1. 初始化:随机选择k个样本点作为初始聚类中心。2. 聚类过程:计算每个样本点到各个聚类中心的距离,并将样本指派到最近的聚类中心所在的类别。3. 计算新的聚类中心:对于每个聚类结果,计算该类中所有样本的均值,作为新的聚类中心。4. 判断迭代是否收敛:如果新旧聚类中心没有变化或者满足迭代条件,则...

matlab里的kmeans算法使用案例不理解丘解释

kmeans:K-均值聚类 data是你自己的输入数据 3 是你要聚成3类 dist sqEuclidean 这2个参数,表示距离函数为欧式距离。什么是欧式距离自己百度 ’rep’,4 聚类重复次数4次。因为要反复算直到选出最好的结果,至多反复算4次 等号左边:Idx 是你聚类的标号 C 是聚类之后质心的位置 sumD是所有点到质...

kmeans是分类算法吗

kmeans不是分类算法,是一种无监督学习的聚类算法,kmeans算法的核心目的是将数据划分为不同的组或“簇”,这些组是基于数据点之间的相似性来形成的,而不是用于将数据点归类为预先定义的类别。kmeans算法通过计算数据点之间的距离并将它们分配到最近的聚类中心来工作,然后重新计算每个聚类的中心,直到达...

聚类算法kmeans及kmeans++介绍(含python实现)

本文主要介绍了k-means聚类算法及其改进版kmeans++,以及评估聚类效果的方法。k-means是一种通过寻找数据集中k个簇的质心来描述数据分布的算法,其步骤包括随机选取k个种子,计算点与质心的距离,更新质心直至收敛。选择k值时,可以通过观察模型性能曲线的拐点决定。kmeans++针对k-means的随机初始值问题进行...

kmeans算法是什么?

K-means算法是一种基于距离的聚类算法,也叫做K均值或K平均,也经常被称为劳埃德(Lloyd)算法。是通过迭代的方式将数据集中的各个点划分到距离它最近的簇内,距离指的是数据点到簇中心的距离。K-means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本划分为K个簇。将簇内的数据尽量...

Kmeans聚类算法简介(有点枯燥)

1. Kmeans聚类算法简介 由于具有出色的速度和良好的可扩展性,Kmeans聚类算法算得上是最著名的聚类方法。Kmeans算法是一个重复移动类中心点的过程,把类的中心点,也称重心(centroids),移动到其包含成员的平均位置,然后重新划分其内部成员。k是算法计算出的超参数,表示类的数量;Kmeans可以自动分配样本到不同的类,但...

KmeansKmeans算法

K-means算法是一种经典的基于划分的聚类方法,位列十大经典数据挖掘算法之一。它以核心参数k为基础,目标是将预先输入的n个数据对象划分为k个互相区分的聚类,确保同一聚类内的对象具有较高的相似性,而不同聚类间的相似性较低。聚类的相似度是通过计算每个聚类的"中心对象",也就是引力中心,来衡量的...

机器学习算法—KMEANS算法原理

KMEANS算法,一种无监督学习下的聚类算法,基于选定的参数K,将数据集划分成K类。其原理始于随机选取K个初始中心点,计算数据点与中心点的距离,将距离最近的数据点归入同一类。随着迭代,类中心根据类内所有点的平均值更新,直至类中心位置稳定或达到指定迭代次数。在K值确定后,算法流程如下:首先,选择...

kmeans算法原理

kmeans算法原理如下:K-means算法是一种典型的基于划分的聚类算法该算法具有运算速度快,执行过程简单的优点,在很多大数据处理领域得到了广泛的应用。利用相似性度量方法来衡量数据集中所有数据之间的关系,将关系比较密切的数据划分到一个集合中。K-means算法首先需要选择K个初始化聚类中,计算每个数据对象到...

kmeans算法名词解释

Kmeans是聚类算法的一种,在工业界应用广泛,简单效果好,ps:企业拥有大数据量可以弥补Kmeans算法过于简单的性能劣势。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
河北到北京西站k402 几点到 铁岭软笔书法班哪家好 除了父母的号码外,小位儿童手表能屏蔽其他陌生人的号码吗? 为何冷冻室温度非得是零下18℃? 我打赌你不知道电冰箱应该怎样使用 细菌生长繁殖的条件的叙述,下列说法错误的是 ...晚会的作文,450字左右就行,写的好加分,我很急,过几天就要开学了_百... 折旧费用分配 1 2 3 4 5 6 7 8 9=100 (在数中间填上加号或减号)不能交换数的位置 allowance for depreciation的意思 有没有拼多多新用户,跪求? 拼多多上的助力享免单是真的不用钱吗 拼多多助力享免单,有人帮忙吗? 拼多多里的助力享免单真滴假滴? 拼多多免单怎么弄啊? 拼多多的免单活动怎么放弃免单 拼多多助力免单的入口在哪? 拼多多中助力,免单秘籍这一关怎么过 拼多多上,助力享免单是什么含义?! 拼多多助力享免单是真的吗? 苹果11怎么用siri说话 苹果11siri怎么不用按 一直对话? kmeans聚类和共现聚类的区别 天下三情侣名字,女的名字带灵字,男的名字带朦字,谢谢大家了! 取名字啊,姓方,最好有个灵字,谢谢大家 杨姓女孩取名带灵字的 邹姓女孩取名,10年7月出生,缺火,想在名字中带个灵字或者熠字。 姓曹起个带灵字的女孩名字 以“灵&quot;字或者带火字旁取名。 想给女儿起名字什么起都不好听,姓黄带灵字的,谢谢了! 怎么设置淘宝子账号公益宝贝权限 网店怎样设置公益宝贝 拼多多有公益宝贝吗 公益宝贝对卖家有没有什么好处?怎么加入? 淘宝公益宝贝怎么设置 什么是法国? 法国的风俗? 法国是个什么样的国家? 法国有哪些十大城市? 关于法国的常识有哪些? 法国发展史(详细点的) 法国的习俗 法国有哪些名人? 法国最值得去的地方? 法国旅行简介 法国有什么 法国特点 建行信用卡刷卡显示持卡人认证失败05怎么办?卡被冻结 持卡人认证失败05是什么意思 简述K-means算法的基本过程及其不足。《数据挖掘》作业题追分100