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 ...
随机推荐
- 详解Object.create(null)
在Vue和Vuex的源码中,作者都使用了Object.create(null)来初始化一个新对象.为什么不用更简洁的{}呢? 在SegmentFault和Stack Overflow等开发者社区中也有 ...
- Non-standard serial port baud rate setting
////combuad_recv.cpp #include <stdio.h> /*标准输入输出定义*/ #include <stdlib.h> /*标准函数库定义*/ #in ...
- 一个参数既可以是const还可以是volatile
可以的,例如只读的状态寄存器.它是volatile因为它可能被意想不到地改变.它是const因为程序不应该试图去修改它. 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器 ...
- Pytest学习笔记(一) 环境安装及入门
简介 pytest是python的一个单元测试框架,类似于unittest,相对unittest来说,pytest使用更简单,功能更强大. 安装 pip3 install -U pytest 查看版本 ...
- php-m 与 phpinfo 不一致的解决办法
1.查看PHP当前加载的php.ini文件地址,在控制台输入以下命令: 1 php -i | grep php.ini 2.控制台返回的信息 1 2 Configuration File (php.i ...
- Java基础_线程的使用及创建线程的三种方法
线程:线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 进程:进 ...
- AGC033D Complexity
题意 给出一个\(n*m\)的\(0,1\)矩阵,若一个矩阵中的所有元素都相同,则这个矩阵的代价为\(0\),如果不是则选择一种将它分成两个子矩阵的方案,代价为所有方案中(两个子矩阵的代价的较大值+\ ...
- Java中boolean类型占用多少个字节?我说一个,面试官让我回家等通知
摘自:https://www.cnblogs.com/qiaogeli/p/12004962.html 程序员乔戈里 腾讯面试官问我Java中boolean类型占用多少个字节?我说一个,面试官让我回家 ...
- app支付宝充值
首先支付宝需要开通app 支付 然后登录支付宝 ,点击合作伙伴, 进入 开放平台,申请一个应用. 下载支付宝开放平台助手, 生成应用公钥,点击上传 设置进入之前申请的应用,支付宝自动生成支付宝公钥,设 ...
- OUC_Summer Training_ DIV2_#14 724
又落下好多题解啊...先把今天的写上好了. A - Snow Footprints Time Limit:1000MS Memory Limit:262144KB 64bit IO F ...