k-means聚类分析范例程序
K-Means聚类算法原理参考以下链接:
https://www.cnblogs.com/pinard/p/6164214.html
2. 传统K-Means算法流程
在上一节我们对K-Means的原理做了初步的探讨,这里我们对K-Means的算法做一个总结。
首先我们看看K-Means算法的一些要点。
1)对于K-Means算法,首先要注意的是k值的选择,一般来说,我们会根据对数据的先验经验选择一个合适的k值,如果没有什么先验知识,则可以通过交叉验证选择一个合适的k值。
2)在确定了k的个数后,我们需要选择k个初始化的质心,就像上图b中的随机质心。由于我们是启发式方法,k个初始化的质心的位置选择对最后的聚类结果和运行时间都有很大的影响,因此需要选择合适的k个质心,最好这些质心不能太近。
好了,现在我们来总结下传统的K-Means算法流程。
输入是样本集D={x1,x2,...xm},聚类的簇树k,最大迭代次数N
输出是簇划分C={C1,C2,...Ck}
1) 从数据集D中随机选择k个样本作为初始的k个质心向量: {μ1,μ2,...,μk}
2)对于n=1,2,...,N
a) 将簇划分C初始化为Ct=∅ t=1,2...k
b) 对于i=1,2...m,计算样本xixi和各个质心向量μj(j=1,2,...k)的距离:dij=||xi−μj||2,将xixi标记最小的为dij所对应的类别λi。此时更新Cλi=Cλi∪{xi}Cλi=Cλi∪{xi}
c) 对于j=1,2,...,k,对CjCj中所有的样本点重新计算新的质心μj=1|Cj|∑x∈Cjxμj=1|Cj|∑x∈Cjx
e) 如果所有的k个质心向量都没有发生变化,则转到步骤3)
3) 输出簇划分C={C1,C2,...Ck}
程序代码如下:
//在矩阵img中随机分布白点
void myRandFill(Mat&img,int numPoint)
{
Vec3b white(,,);
for(int i=;i<numPoint;i++)
{
int x=rand()%+;
int y=rand()%+;
img.at<Vec3b>(y,x)=white; } }
Point getCentroid(std::vector<Point> C)
{
Point newPc(,);
for(int i=;i<(int)C.size();i++)
{
newPc.x += C[i].x;
newPc.y +=C[i].y;
}
newPc.x /=C.size();
newPc.y /=C.size();
return newPc;
}
void getCluster(const Mat&img,Mat&imgCopy,
vector<Point>C[],Point Pc[],
Vec3b color[],int numOfCluster)
{
for(int i=;i<img.rows;i++)
{
for(int j=;j<img.cols;j++)
{
Vec3b X=img.at<Vec3b>(i,j);
vector<float> d;//当前像素与所有质心距离组成的数组
if(X[]||X[]||X[])
{
for(int k=;k<numOfCluster;k++)
{
float dist=(Pc[k].x-j)*(Pc[k].x-j)+(Pc[k].y-i)*(Pc[k].y-i);
d.push_back(dist);
}
//获取数组d[]中最小值的位置
int minPos=(int)(min_element(d.begin(),d.end())-d.begin());
//将距离最小质心 对应颜色赋值给当前像素
imgCopy.at<Vec3b>(i,j)=color[minPos];
//将当前像素并入对应类的集合
C[minPos].push_back(Point(j,i)); } }
}
} void myKmeans(const Mat&img,//输入原图像
Mat&imgCopy,//分类后的图像输出
std::vector<Point>*C,//类别标记数组,
//数组中每个元素C[i]表示一类像素
//从图像中找到符合该类准则的像素
//保存在C[i]中,i=1,2,3...k。
Point*Pc,//初始质心坐标
Vec3b*color,//不同类别的像素,赋予不同的颜色
int numOfclusters)//预设的类别数
{
//将距离Pc1近的点染成红色,距离Pc2点距离近的染成蓝色
//
int stop=;
int countIte=;
while(!stop)
{ getCluster(img,imgCopy,C,Pc,color,numOfclusters);
//计算新的C1、C2质心,并在imgCopy上绘制黄色和青色新质心点
Point* newPc=new Point[numOfclusters];
for(int nc=;nc<numOfclusters;nc++)
{
newPc[nc]=getCentroid(C[nc]);
circle(imgCopy,newPc[nc],,Scalar(,,),);
}
vector<float>dc;
float sumDistance;
for(int k=;k<;k++)
{
float dp=(newPc[k].x-Pc[k].x)*(newPc[k].x-Pc[k].x)
+(newPc[k].y-Pc[k].y)*(newPc[k].y-Pc[k].y);
dc.push_back(dp);
}
sumDistance=accumulate(dc.begin(),dc.end(),); cout<<"sum distance="<<sumDistance<<endl;
countIte++;
for(int nc=;nc<numOfclusters;nc++)
{
Pc[nc]=newPc[nc];
}
if(sumDistance==)
{
stop=;
} }
cout<<"count of iteration="<<countIte<<endl;
} int main()
{
Mat img(,,CV_8UC3,Scalar::all());
Mat imgCopy=img.clone();
//创建两组随机分布的聚类点,一共200个白点
Mat rm1=img(Rect(,,,));
Mat rm2=img(Rect(,,,));
myRandFill(rm1,);
myRandFill(rm2,); //设有两个聚类颜色标记,分别用红、蓝两色表示
Vec3b color[]={ Vec3b(,,),Vec3b(,,)};
//与red和blue两种颜色对应的族类集合为C[0]和C[1]
std::vector<cv::Point> C[];
//随便定义两个坐标点,作为两个聚类质心的起始位置
Point *Pc=new Point[];
Pc[]=Point(,);//C1类像素的初始质心坐标
Pc[]=Point(,);//C2类像素的初始质心坐标
cv::circle(imgCopy,Pc[],,Scalar(,,),-);
cv::circle(imgCopy,Pc[],,Scalar(,,),-);
imshow("original img",img); myKmeans(img,imgCopy,C,Pc,color,);
imshow("new centroid position",imgCopy);
waitKey();
return ;
}
k-means聚类分析范例程序的更多相关文章
- RAD Studio XE8 技术研讨会讲义与范例程序下载
感谢各位程序猿亲临现场參加我们的公布会,现奉上会议当天的讲义与范例程序供大家參考: 2015/5/25~27北京.深圳 『RAD Studio XE8技术研讨会』 下载讲义:http://pan ...
- SPSS聚类分析:K均值聚类分析
SPSS聚类分析:K均值聚类分析 一.概念:(分析-分类-K均值聚类) 1.此过程使用可以处理大量个案的算法,根据选定的特征尝试对相对均一的个案组进行标识.不过,该算法要求您指定聚类的个数.如果知道, ...
- SAP ALV标准范例程序介绍
下面介绍几个学习ALV的SAP自带标准程序实例 1. BALVSD06 : Output flights (simple version + save)这是该系列范例最简单的一个,建议以此入门.使用的 ...
- KNN 与 K - Means 算法比较
KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...
- eval(function(p,a,c,k,e,r)解密程序
以eval(function(p,a,c,k,e,r){e=function(c)开头的js文件是经过加密的 使用下面方法可以对js文件进行加密.解密 步骤:1.新建html页面,内容如下列代码 2. ...
- 软件——机器学习与Python,聚类,K——means
K-means是一种聚类算法: 这里运用k-means进行31个城市的分类 城市的数据保存在city.txt文件中,内容如下: BJ,2959.19,730.79,749.41,513.34,467. ...
- R 语言实战-Part 5-1笔记
R 语言实战(第二版) part 5-1 技能拓展 ----------第19章 使用ggplot2进行高级绘图------------------------- #R的四种图形系统: #①base: ...
- 程序员编程艺术:第三章续、Top K算法问题的实现
程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha. 致谢:微软100题实现组,狂想曲创作组. 时间:2011年05月08日 ...
- 网络费用流-最小k路径覆盖
多校联赛第一场(hdu4862) Jump Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
随机推荐
- OI界的事
随时更新: 目前在中大型考试上已经因为freopen相关的锅导致此题爆零共有: 5次.并且因此参加不了提高组(菜到无人反驳) 本人:学oi半年的练习生)蒟蒻 ,擅长水红题,橙题,博客,以及电子方面. ...
- CSS基础学习 21.CSS居中总结
注意:*在IE中并不代表通配符的意思,是代表根元素的意思,所以为了匹配适应各种浏览器,进行页面初始化 <style> *{ margin:0; padding:0; } </styl ...
- Springboot打包成jar包形式发布
1.修改配置文件pom.xml 添加打包形式设置为jar形式 <packaging>jar</packaging> 2.在build标签内添加内容如下 finalname为打包 ...
- 洛谷P4001 [BJOI2006]狼抓兔子(平面图转对偶图)
传送门 明明只要最小割加点优化就能过的东西…… 然而我偏偏要去学平面图转对偶图结果发现课件关键地方看不清->这里 而且建图累的半死…… 说实话只要最大流建图的时候反向边直接设为当前边容量再加个当 ...
- C语言编译错误:Variably modified array at file scope
今天在编译一段C源程序时,遇到编译错误提示 error: variably modified 'data' at file scope.原因在于代码头部有这样几行: +; int data[maxsi ...
- 获取当前exe的绝对路径
string GetExePath(void) { ]={}; GetModuleFileNameA(NULL, szFilePath, MAX_PATH); (strrchr(szFilePath, ...
- 题解 [51nod1461] 稳定桌
题面 解析 一开始看上去毫无思路啊. 但想通了就很很简单. 我们枚举每种长度的边作为最大的边, 于是长度比当前大的边就要砍掉, 而长度比当前小的边只能留下小于等于当前长度的边数, 砍掉代价最小的几条就 ...
- hdu 6074 Phone Call
题 O∧O http://acm.hdu.edu.cn/showproblem.php?pid=6074 2017 Multi-University Training Contest - Team 4 ...
- 关于单片机特殊功能寄存器(SFR)和内存(RAM)公用地址:80-FF 如何区分
RAM 的 80-FF 需要间接寻址进行访问 如: MOV R0,#80H; MOV A,@R0 ; (内存 80H地址内的数据放到A中) SFR的80-FF需要直接寻址进行访问如: MOV ...
- Mysql 修改最大链接数
链接数过小经常出现ERROR 1040: Too many connections错误 show variables like '%max_connections%'; 查看当前的mysql链接值 ...