1. [代码][C/C++/Objective-C]代码
001 |
#include <stdio.h> |
002 |
#include <stdlib.h> |
003 |
#include <math.h> |
004 |
005 |
#define NA 4 /* 数据维数 */ |
006 |
#define K 3 /* 聚类数 */ |
007 |
#define Psize 50 /* 种群大小 */ |
008 |
#define T 30 /* 最大迭代数 */ |
009 |
#define ED 0.0000001 /* 结束条件 */ |
010 |
011 |
typedef struct { |
012 |
double p[NA]; |
013 |
double distance[K]; |
014 |
}Point; |
015 |
016 |
typedef struct { |
017 |
Point clu_cent[K]; /* 即cluster_center 簇类中心 */ |
018 |
int cluster[K][Psize]; /* 簇类数组 */ |
019 |
int cluster_num[K]; /* 簇类中一组数据的编号 */ |
020 |
double fitness; /* 样本适应度值,用于判断结束条件 */ |
021 |
double old_fitness; /* 前一次迭代的适应度值 */ |
022 |
double Je; /* 所有样本的平方误差和 */ |
023 |
}Pop; |
024 |
025 |
/* 声明函数 */ |
026 |
int Is_equal( int a[], int n, int b); |
027 |
double Euclid( int x, int y); |
028 |
void input_data(); |
029 |
void Init_center(); |
030 |
void calculate_distance(); |
031 |
void Make_new_cluster(); |
032 |
void Make_new_center(); |
033 |
void output_info( int flag); |
034 |
035 |
036 |
Point all_data[Psize]; /* 数据大小 */ |
037 |
Pop pop; |
038 |
039 |
/************************************************ |
040 |
* 从外部文件导入数据,对于没有数据文件将报错, * |
041 |
* 数据文件的格式根据 NA 决定,例如NA = 4时,测 * |
042 |
* 试数据为四维,则test.data 为: * |
043 |
* 1 2 3 4 * |
044 |
* 1.0 1.2 1.3 1.4 * |
045 |
* ...... * |
046 |
* ...... * |
047 |
***********************************************/ |
048 |
void input_data() |
049 |
{ |
050 |
FILE *infile; |
051 |
int i, j; |
052 |
double data; |
053 |
054 |
if ((infile = fopen ( "test.data" , "r" )) == NULL){ |
055 |
printf ( "没有test.data这个文件,无法导入数据\n" ); |
056 |
exit (1); |
057 |
} |
058 |
for (i = 0; i < Psize; i++) |
059 |
for (j = 0; j < NA; j++){ |
060 |
fscanf (infile, "%lf" , &data); |
061 |
all_data[i].p[j] = data; |
062 |
// printf("%d --%d %lf\n", i, j, all_data[i].p[j]); |
063 |
} |
064 |
fclose (infile); /* 关闭文件描述符 */ |
065 |
} |
066 |
067 |
/*************************************************** |
068 |
* 随机初始化聚类质心,当随机数有相同时跳过继续执行* |
069 |
**************************************************/ |
070 |
void Init_center() |
071 |
{ |
072 |
int i, j; |
073 |
int num = 0; |
074 |
int rand_num; |
075 |
int rand_num_tmp[K]; |
076 |
/* 随机产生三个0~Psize的数 */ |
077 |
while (num < K){ |
078 |
rand_num = rand () % Psize; |
079 |
if (!Is_equal(rand_num_tmp, num, rand_num)) |
080 |
rand_num_tmp[num++] = rand_num; |
081 |
} |
082 |
for (i = 0; i < K; i++){ |
083 |
// printf("初始化质心%d:\n", i + 1); |
084 |
for (j = 0; j < NA; j++){ |
085 |
pop.clu_cent[i].p[j] = all_data[rand_num_tmp[i]].p[j]; |
086 |
// printf("%lf ",pop.clu_cent[i].p[j]); |
087 |
} |
088 |
printf ( "\n" ); |
089 |
} |
090 |
} |
091 |
092 |
/********************************** |
093 |
* 检查数据是否有相等,相等返回1 * |
094 |
*********************************/ |
095 |
int Is_equal( int a[], int n, int b) |
096 |
{ |
097 |
int i; |
098 |
for (i = 0; i < n; i++) |
099 |
if (a[i] == b) return 1; |
100 |
return 0; |
101 |
} |
102 |
103 |
/******************************************** |
104 |
* 计算Psize组数据到K个质心的欧几里德距离* |
105 |
*******************************************/ |
106 |
void calculate_distance() |
107 |
{ |
108 |
int i, j; |
109 |
for (i = 0; i < Psize; i++) |
110 |
for (j = 0; j < K; j++){ |
111 |
all_data[i].distance[j] = Euclid(i, j); |
112 |
// printf("%d---%d--- %lf \n", i, j, all_data[i].distance[j]); |
113 |
} |
114 |
} |
115 |
116 |
/************************************************ |
117 |
* 此函数为欧几里德距离公式函数,此处用于计算* |
118 |
* 一组数据到对应簇中心的欧几里德距离。 * |
119 |
***********************************************/ |
120 |
double Euclid( int x, int y) |
121 |
{ |
122 |
int i; |
123 |
double distance = 0; |
124 |
for (i = 0; i < NA; i++){ |
125 |
distance += pow ((all_data[x].p[i] - pop.clu_cent[y].p[i]), 2); |
126 |
} |
127 |
distance = sqrt (distance); |
128 |
return distance; |
129 |
} |
130 |
131 |
132 |
/************************ |
133 |
* 将数据进行簇集归类 * |
134 |
***********************/ |
135 |
void Make_new_cluster() |
136 |
{ |
137 |
int i, j; |
138 |
139 |
double min; |
140 |
|
141 |
for (i = 0; i < K; i++) /* 初始化编号 */ |
142 |
pop.cluster_num[i] = 0; |
143 |
for (i = 0; i < Psize; i++){ |
144 |
int index = 0; |
145 |
min = all_data[i].distance[0]; |
146 |
for (j = 1; j < K; j++){ /* 筛选到簇心欧几里德最小的 */ |
147 |
if (all_data[i].distance[j] < min){ |
148 |
min = all_data[i].distance[j]; |
149 |
index = j; |
150 |
} |
151 |
} |
152 |
/* 划分簇集 */ |
153 |
pop.cluster[index][pop.cluster_num[index]++] = i; |
154 |
} |
155 |
/* 计算所有样本的平方误差和 */ |
156 |
pop.Je = 0; |
157 |
for (i = 0; i < K; i++) |
158 |
for (j = 0; j < pop.cluster_num[i]; j++){ |
159 |
/* 样本到簇心的值即为其欧几里德距离 */ |
160 |
pop.Je += pow (all_data[pop.cluster[i][j]].distance[i],2); |
161 |
} |
162 |
pop.old_fitness = pop.fitness; /* 前一次迭代适应度值 */ |
163 |
// printf("old_fitness = %lf\n", pop.old_fitness); |
164 |
pop.fitness = pop.Je; /* 所有样本平方误差和即为适应度值 */ |
165 |
} |
166 |
167 |
/************************************************* |
168 |
* 更新簇心,即求其群类的平均距离为新的簇心 * |
169 |
************************************************/ |
170 |
void Make_new_center() |
171 |
{ |
172 |
int i, j, n; |
173 |
double tmp_sum; |
174 |
175 |
for (i = 0; i < K; i++) |
176 |
for (j = 0; j < NA; j++){ |
177 |
tmp_sum = 0; |
178 |
for (n = 0; n < pop.cluster_num[i]; n++){ |
179 |
/* 第i个簇的第j维数的所有数据和 */ |
180 |
tmp_sum += all_data[pop.cluster[i][n]].p[j]; |
181 |
} |
182 |
/* 取平均数得到新的簇中心 */ |
183 |
pop.clu_cent[i].p[j] = tmp_sum / pop.cluster_num[i]; |
184 |
} |
185 |
} |
186 |
187 |
/******************************** |
188 |
* 输出信息函数 * |
189 |
* 显示格式为: * |
190 |
* 质心K: * |
191 |
* NA维的质心数据 * |
192 |
* 簇类K: * |
193 |
* NA维属于簇类K的数据 * |
194 |
* ...... * |
195 |
* ...... * |
196 |
*******************************/ |
197 |
void output_info( int flag) |
198 |
{ |
199 |
int i, j, n; |
200 |
201 |
202 |
for (i = 0; i < K; i++){ |
203 |
if (flag == 0){ |
204 |
printf ( "初始化质心%d:\n" , i + 1); |
205 |
for (n = 0; n < NA; n++) |
206 |
printf ( "%lf " ,pop.clu_cent[i].p[n]); |
207 |
} else if (flag == 1){ |
208 |
printf ( "最终质心%d:\n" , i + 1); |
209 |
for (n = 0; n < NA; n++) |
210 |
printf ( "%lf " ,pop.clu_cent[i].p[n]); |
211 |
} |
212 |
printf ( "\n簇类%d:\n" , i + 1); |
213 |
for (j = 0; j < pop.cluster_num[i]; j++){ |
214 |
for (n = 0; n < NA; n++){ |
215 |
printf ( "%lf " , |
216 |
all_data[pop.cluster[i][j]].p[n]); |
217 |
} |
218 |
printf ( "\n" ); |
219 |
} |
220 |
} |
221 |
} |
222 |
223 |
/******************************** |
224 |
* 主函数 * |
225 |
*******************************/ |
226 |
int main() |
227 |
{ |
228 |
int i; |
229 |
double differ = 1; /* 适应度差值 */ |
230 |
int flag = 0; /* 用来标示是显示初始数据还是聚类后的数据 */ |
231 |
input_data(); /* 导入数据 */ |
232 |
Init_center(); /* 初始化质心 */ |
233 |
234 |
for (i = 0; (i < T) && (differ > ED); i++){ |
235 |
calculate_distance(); /* 计算欧几里德距离 */ |
236 |
Make_new_cluster(); /* 产生新的聚类 */ |
237 |
if (flag == 0){ |
238 |
output_info(flag); /* 输出第一次聚类后的结果 */ |
239 |
flag = 1; |
240 |
} |
241 |
Make_new_center(); /* 对新的聚类产生新的质心 */ |
242 |
differ = pop.old_fitness - pop.fitness; /* 判断条件 */ |
243 |
differ = fabs (differ); |
244 |
245 |
// printf("differ = %lf\n", differ); |
246 |
// printf("old_fitness = %lf\n", pop.old_fitness); |
247 |
// printf("fitness = %lf\n", pop.fitness); |
248 |
} |
249 |
250 |
printf ( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" ); |
251 |
output_info(flag); /* 聚类后显示结果 */ |
252 |
253 |
return 0; |
254 |
} |
相关推荐
k-means算法是一种广泛应用的无监督学习方法,主要用于数据聚类。它的主要目标是将数据集分割成k个不同的簇,使得每个数据点都尽可能接近其所在簇的中心,而不同簇之间的数据点尽可能远离。在讲解k-means算法时,...
K-Means算法是机器学习领域中一种广泛应用的无监督聚类方法,它主要用于将数据集中的样本点划分到不同的类别或簇中。在模式识别中,K-Means算法常用于对未知分类的数据进行自动分组,以便于后续分析和理解。Matlab...
k-means算法是一种广泛应用的无监督学习方法,主要用于数据聚类。它的主要目标是将数据集分割成k个互不重叠的簇,使得每个数据点都属于与其最近的簇中心。在Java中实现k-means算法,我们可以遵循以下几个关键步骤: ...
K-means算法 K-means算法是一种常用的无监督机器学习算法,用于对数据进行聚类分析。该算法的主要步骤包括:读取数据、快速PCA降维、归一化、Kmeans聚类。 读取数据:读取数据是K-means算法的第一步骤。在这个步骤...
**K-means算法详解** K-means是一种广泛应用的无监督学习方法,主要用于数据的聚类分析。它通过迭代过程将数据点分配到预定义数量(K)的类别中,目标是使得同一类别内的数据点相互接近,不同类别之间的数据点尽...
### 初始聚类中心优化的k-means算法 #### 概述 传统的k-means算法是一种广泛应用的数据挖掘技术,主要用于解决聚类问题。该算法通过迭代过程将数据集分割成多个簇(cluster),使得簇内数据点之间的差异尽可能小,而...
k-means算法是一种广泛应用的无监督学习方法,主要用于数据聚类。它的主要目标是将数据集中的样本点分成k个不同的簇(clusters),使得每个样本点都属于与其最近的簇中心。这个过程涉及到两个核心概念:簇(cluster...
### 人工智能作业K-MEANS算法的试验报告和源代码 #### 一、问题描述 本次人工智能课程的大作业要求学生实现并分析K-Means聚类算法在Iris数据集上的应用。Iris数据集是一个经典的多类别数据集,包含了150个样本,每...
《一种改进的K-means算法》 K-means算法是一种广泛应用的无监督学习方法,主要用于数据的聚类分析。在大数据领域,它以其简单高效的特点,成为处理大规模数据集的有效工具。然而,K-means算法也存在一些固有的局限...
### 数据挖掘中的K-Means算法详解 #### 一、K-Means算法概述 K-Means算法作为数据挖掘领域中的一种基本聚类方法,主要用于无监督学习场景下的数据分析与处理。它能够将相似的对象归类到同一组内,不同组间差异尽...
在遥感图像处理领域,K-means算法是一种广泛使用的无监督机器学习方法,用于将数据自动聚类到预设的类别中。Matlab作为一种强大的数值计算和数据分析工具,提供了便捷的环境来实现K-means算法。这篇教程将深入探讨...
### 国外实现K-Means算法:Java版本解析 #### 概述 K-Means算法是一种广泛使用的聚类算法,在数据挖掘、机器学习等领域有着重要的应用价值。本篇文章将详细解读一个由国外开发者提供的K-Means算法Java实现案例,并...
基于 K-means 算法的校园微博热点话题发现系统 一、研究目的 微博由其 “短平快 ” 的信息能力和快速传播能力 ,已广泛流行于高校学生的常生活中。但微博上的负面舆情信息给社会 、学校和个人带来巨大的危害 。由于...
K均值聚类,也称为K-Means算法,是一种在数据挖掘和机器学习领域中应用广泛的无监督学习方法。通过聚类算法,我们可以将数据点分组成具有相似特性的簇,以揭示数据内在的结构和模式。K-Means因其简单高效而被广泛...
K-Means算法是一种在数据挖掘领域广泛应用的无监督学习方法,主要用于对数据进行聚类。这个Java实现的K-Means算法具有可视化功能,可以让用户直观地理解聚类过程和结果。以下是对该算法及其Java实现的详细解析: 1....