K-Means聚类算法及实现代码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
K-Means算法
k-means 算法接受参数k ;然后将事先输入的n个数据对象划分为k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。
假设要把样本集分为c个类别,算法描述如下:
(1)适当选择c个类的初始中心;
(2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类;
(3)利用均值等方法更新该类的中心值;
(4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。
#include
#include
#include
#define _NUM 3 //预定义划分簇的数目
using namespace std;
/**
特征对象,表示一个元组,一个元组有两个数值属性
**/
struct Tuple
{
int attr1;
int attr2;
};
/**
获取两个特征对象之间的距离,在此以欧基米德距离作为距离度量标准
**/
double getDistXY(Tuple t1, Tuple t2)
{
return sqrt((t1.attr1 - t2.attr1) * (t1.attr1 - t2.attr1) + (t1.attr2 - t2.attr2) * (t1.attr2 - t2.attr2));
}
/**
计算簇的中心点,在此以簇中所有对象的平均距离来计算中心点
**/
Tuple getMeansC(vector
{
int num = c.size();
double meansX = 0, meansY = 0;
Tuple t;
for (int i = 0; i < num; i++)
{
meansX += c[i].attr1;
meansY += c[i].attr2;
}
t.attr1 = meansX / num;
t.attr2 = meansY / num;
return t;
}
/**
获取算法的准则函数值,当准则函数收敛时算法停止
**/
double getE(vector
{
double sum = 0;
for (int i = 0; i < _NUM; i++)
{
vector
for (int j = 0; j< v.size(); j++)
{
sum += (v[j].attr1 - means[i].attr1) * (v[j].attr1 - means[i].attr1) + (v[j].attr2 - means[i].attr2) *(v[j].attr2 - means[i].attr2);
}
}
cout<<"sum:"< return sum; } /** 对当前的特征对象,查找与其最临近的簇,最临近即到簇中心点的距离最短**/ int searchMinC(Tuple t, Tuple means[_NUM]) { int c = 0; int d = (t.attr1 - means[0].attr1) * (t.attr1 - means[0].attr1) + (t.attr2 - means[0].attr2) * (t.attr2 - means[0].attr2); for (int i = 1; i < _NUM; i++) { int temp = (t.attr1 - means[i].attr1) * (t.attr1 - means[i].attr1) + (t.attr2 - means[i].attr2) * (t.attr2 - means[i].attr2); if (temp < d) { c = i; d = temp; } } return c; } /** k-Means算法 **/ void kMeans(vector { vector int c; Tuple means[_NUM]; //定义中心点数组,每个簇对应一个中心点 double newE, oldE = -1; //定义准则函数值 for (int i = 0; i < _NUM; i++) //对每个簇初始赋予一个特征对象 { cin >> c; classes[i].push_back(init[c - 1]); means[i] = getMeansC(classes[i]); //计算当前每个簇的中心点 cout<<"means["< } newE = getE(classes, means); //计算当前准则函数值 cout<<"newE:"< for (i = 0; i < _NUM; i++) //清空每个簇 { classes[i].clear(); } while(abs(newE - oldE) >= 1) //当新旧函数值相差不到1即准则函数值不发生明显变化时,算法终止 { for (int j = 0; j < init.size(); j++) //遍历所有特征对象,将其加入到离它最近的簇 { int toC = searchMinC(init[j], means); classes[toC].push_back(init[j]); } cout<<"--------------------"< for (i = 0; i < _NUM; i++) //打印出当前每个簇的特征对象 { vector cout<<"类"< for (j = 0; j < temp.size(); j++)