K-Means算法
K-Means算法
K-Means算法的输入N,K和一个size为N的向量组vector.输出K个两两互不相交的向量组.其本质是将给定的向量组划分成K个类别,使得同类别的向量相似度比较大,而不同类别的向量之间的相似度较小.
比如以下这个图,人肉眼能看出有四个点团,但计算机不知道,为了让计算机明白这一点,可以将点的坐标提取到向量组中,而向量之间的相似度定义为点之间的距离的相反数或者倒数.从而将这些点分开.
实现过程:
(1)从n个数据对象任意选择k个对象作为初始聚类中心;
(2)根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离,并根据最小距离重新对相应对象进行划分;
(3)重新计算每个(有变化)聚类的均值(中心对象);
(4)计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止,如果条件不满足则回到步骤(2).
实际应用中的问题:
事实上,我是一个做ACM的选手,所以我比较感兴趣的是K-Means能否求得一个最优解.对于这样一个问题:从N个点取出K个作为核心,定义两个向量之间的相似度函数f(vector1,vector2),使得所有点与其所对应的核心的相似度之和最大.然而事实让我大失所望,K-Means算法对种子点的选取十分敏感,不同的种子会导致不同的解.

#include<math.h>
#include<stdio.h>
#include<string.h>
#define Convergence (fabs(last-cur)<1e-8)
#define dist(a,b) (sqrt((x[a]-px[b])*(x[a]-px[b])+(y[a]-py[b])*(y[a]-py[b])))
int x[50000],y[50000],qx[50000],qy[50000],px[100],py[100],assign[50000];
int main()
{
freopen("data.txt","r",stdin);
FILE *fp=fopen("output.txt","w");
int N,K,i,j,k;
double ave=0,MIN=1e15;
scanf("%d%d",&N,&K);
for (i=1;i<=N;i++) scanf("%d%d",&x[i],&y[i]);
for (int asd=0;asd<N;asd++)
{
printf("Executing case #%d\n",asd);
if (asd) printf("Current Average:%.6lf\n",ave/asd);
printf("Current Minimize:%.6lf\n",MIN);
printf("----------------------------------------\n");
fprintf(fp,"Executing case #%d\n",asd);
if (asd) fprintf(fp,"Current Average:%.6lf\n",ave/asd);
fprintf(fp,"Current Minimize:%.6lf\n",MIN);
fprintf(fp,"----------------------------------------\n");
for (i=1;i<=K;i++)
{
px[i]=x[(i+asd)%N+1];
py[i]=y[(i+asd)%N+1];
}
double last=1e15,cur=0;
while (!Convergence)
{
printf("%.6lf\n",last);
last=cur;
for (i=1;i<=N;i++)
{
double Min=1e15;
int v;
for (j=1;j<=K;j++)
{
double d=dist(i,j);
if (d<Min)
{
Min=d;
v=j;
}
}
assign[i]=v;
}
for (i=1;i<=K;i++)
{
int cnt=0;
for (j=1;j<=N;j++)
if (assign[j]==i)
{
qx[++cnt]=x[j];
qy[ cnt ]=y[j];
}
double Min=1e15;
int v;
for (j=1;j<=cnt;j++)
{
double tmp=0;
for (k=1;k<=cnt;k++)
tmp+=(sqrt((qx[j]-qx[k])*(qx[j]-qx[k])+(qy[j]-qy[k])*(qy[j]-qy[k])));
if (tmp<Min)
{
Min=tmp;
v=j;
}
}
px[i]=qx[v];
py[i]=qy[v];
}
cur=0;
for (i=1;i<=N;i++) cur+=dist(i,assign[i]);
}
ave+=cur;
MIN=MIN<cur ? MIN:cur;
}
printf("Total average:%.6lf\n",ave/N);
printf("Total MIN:%.6lf\n",MIN);
fprintf(fp,"Total average:%.6lf\n",ave/N);
fprintf(fp,"Total MIN:%.6lf\n",MIN);
return 0;
}

运行结果如图所示:
.bmp)
另一个问题是算法的收敛速度,重新算了一下,结果如下图所示:

这个结果让我大吃一惊啊,每次迭代之后更新量都很小,而且最终的值(9259914.963696)跟第一个有意义的值(10352922.175732)相差并不是很多.后来我仔细想了一下,应该是跟输入数据有关,我的数据完全是在一定范围内随机生成的,分布比较均匀,所以即使随便选也可以得到相当不错的效果,这是我生成数据的程序:
program makedata;
var i,N,K:longint;
begin
assign(output,'data.txt');
rewrite(output);
randomize;
N:=random(10000);
K:=random(10000);
writeln(N,' ',K);
for i:=1 to N do
writeln(random(10000),' ',random(10000));
close(output);
end.
于是我重新写了makedada程序,想法是先随机生成K个核心,再在其周围生成其他的点:
#include<stdio.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
srand(unsigned(time(0)));
freopen("data.txt","w",stdout);
printf("15000 15\n");
for (int i=1;i<=15;i++)
{
int X=rand()%1000000,Y=rand()%1000000;
for (int j=1;j<=1000;j++)
{
int dx=rand()%10000,dy=rand()%10000;
if (rand()&1) dx*=-1;
if (rand()&1) dy*=-1;
printf("%d %d\n",X+dx,Y+dy);
}
}
return 0;
}
再重新运行一下,得到如下结果:
.bmp)
可以看出,收敛的速度还是可以的,而且最终结果几乎只有最初解得一半.
初除此之外,还有一个重要问题,核心数K是作为输入给定的,而在实际应用中是无法预知的.对此可以用ISODATA算法作为补充.
K-Means算法的更多相关文章
- KNN 与 K - Means 算法比较
KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...
- K-means算法
K-means算法很简单,它属于无监督学习算法中的聚类算法中的一种方法吧,利用欧式距离进行聚合啦. 解决的问题如图所示哈:有一堆没有标签的训练样本,并且它们可以潜在地分为K类,我们怎么把它们划分呢? ...
- 机器学习实战笔记--k近邻算法
#encoding:utf-8 from numpy import * import operator import matplotlib import matplotlib.pyplot as pl ...
- 《机器学习实战》学习笔记一K邻近算法
一. K邻近算法思想:存在一个样本数据集合,称为训练样本集,并且每个数据都存在标签,即我们知道样本集中每一数据(这里的数据是一组数据,可以是n维向量)与所属分类的对应关系.输入没有标签的新数据后,将 ...
- [Machine-Learning] K临近算法-简单例子
k-临近算法 算法步骤 k 临近算法的伪代码,对位置类别属性的数据集中的每个点依次执行以下操作: 计算已知类别数据集中的每个点与当前点之间的距离: 按照距离递增次序排序: 选取与当前点距离最小的k个点 ...
- k近邻算法的Java实现
k近邻算法是机器学习算法中最简单的算法之一,工作原理是:存在一个样本数据集合,即训练样本集,并且样本集中的每个数据都存在标签,即我们知道样本集中每一数据和所属分类的对应关系.输入没有标签的新数据之后, ...
- 基本分类方法——KNN(K近邻)算法
在这篇文章 http://www.cnblogs.com/charlesblc/p/6193867.html 讲SVM的过程中,提到了KNN算法.有点熟悉,上网一查,居然就是K近邻算法,机器学习的入门 ...
- 聚类算法:K-means 算法(k均值算法)
k-means算法: 第一步:选$K$个初始聚类中心,$z_1(1),z_2(1),\cdots,z_k(1)$,其中括号内的序号为寻找聚类中心的迭代运算的次序号. 聚类中心的向量值可任意设 ...
- 从K近邻算法谈到KD树、SIFT+BBF算法
转自 http://blog.csdn.net/v_july_v/article/details/8203674 ,感谢july的辛勤劳动 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章 ...
- Python实现kNN(k邻近算法)
Python实现kNN(k邻近算法) 运行环境 Pyhton3 numpy科学计算模块 计算过程 st=>start: 开始 op1=>operation: 读入数据 op2=>op ...
随机推荐
- POI导出Excel文档通用工具方法
import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; imp ...
- 移动小bug
1. 在三星note2,小米2,页面加载后,页面有黑块. 那么提高被盖住的部分z-index. 2. iphone5 ,ios7.0.4,上文字显示不出 那么就先hide,setTimeout几百毫秒 ...
- JS分析URL字符串,取得参数名,AJAX传参请求代码示例
//当前页面URL中参数分析函数,正则校验 function getQueryString(name) { var reg = new RegExp("(^|&)" + n ...
- high performance program (SSE4.2 intrin instruction)
In file included from mm_lddqu.si128.c:2:0: /usr/local/lib/gcc/x86_64-redhat-linux/4.7.1/include/nmm ...
- php 模拟POST提交的2种方法
1.通过curl函数 $post_data = array(); $post_data['clientname'] = "test08"; $post_data['clientpa ...
- tomcat源代码Catalina
Catalina的作用是初始化各个组件,并開始启动各个组件. 上文中介绍了Bootstrap是怎样启动Catalina的,如今来看看Catalina的作用: 1,Catalina通过Digester类 ...
- JavaScript的基准测试
JavaScript的基准测试 原文:Bulletproof JavaScript benchmarks 做JavaScript的基准测试并没有想的那么简单.即使不考虑浏览器差异所带来的影响,也有很多 ...
- Linux Telnet安装配置
本文以红帽6.2 64位版本为例,其它linux类似: linux默认是使用SSH服务的 而不安装telnet服务 ,所以需要手动安装telnet. 1.telnet的安装包有两个,分别是: teln ...
- Oracle中注意用户的访问权限
新增表.序列.存储过程等,要注意用户(例如System)的权限.如果在增删改查过程中出现数据库读写权限的报错,则在建表(或者序列.存储过程等)时,在脚本前面加 GRANT CREATE TABLE T ...
- 【工作笔记二】ASP.NET MVC框架下使用MVVM模式
ASP.NET MVC框架下使用MVVM模式 原文:http://www.cnblogs.com/n-pei/archive/2011/07/21/2113022.html 对于asp.net mvc ...