Kmeans算法及其示例
Kmeans算法
Kmeans是简单的聚类分析算法。其常用在数据分析与人工智能中。
简单说,Kmeans算法就是把一个集合中的东西分为若干子集,这几个子集内的元素具有空间相近或者特点相近。
做法:
1. 随机选取K各中心点,生成对应的k个簇。
2. 遍历所有的数据点,依据“距离’”将每一个数据点划分到最近的中心点所在的簇。
3. 计算每个簇所有的数据点的平均值,并作为该簇新的中心。
4. 重复2-3步,直到这k个簇的中心点不再变化,或者达到我们规定的迭代次数。
注意:
1. kmean算法思想本身比较简单,但是设置k数量与初始中心点却比较难以确定。
2. 需要判断处理空聚类以防某个初始中心点设置不合理。
3. 这里的“距离”指欧氏距离或者是余弦相似度,也可以指某种特征,不要被“距离”二字局限
4. 每个数据点是几维的,那么数据中心也应该是几维的,这里kmeans可以想象成将高维空间中的若干个数据点分为若干团。(其实也有特殊情况)
Kmeans++算法
Kmeans++算法,主要可以解决初始中心的选择问题,不可解决k的个数。
Kmeans++主要思想是选择的初始聚类中心要尽量的远。
做法:
1. 在输入的数据点中随机选一个作为第一个聚类中心。
2. 对于所有数据点,计算它与最近的聚类中心的距离D(x)
3. 重新选择一个数据点作为聚类中心,选择原则:D(x)较大的点被选为聚类中心的概率较大。
4. 重复2-3直到选出k个聚类中心。
5. 运行Kmeans算法。
kmeans示例
PS:其初始中心的设置我在这直接取了数据点中最大与最小点的等分值,数据预处理部分代码去掉。
题目是对一个具有四波段的海洋遥感图做聚类分析。
将整幅图划分为若干块,然后对每个块取其波段均值,然后做聚类分析。
#include <iostream>
#include <cmath>
#include <list>
#include <fstream>
#include <cstdlib>
//kmeans算法
//数据预处理代码已去除
using namespace std;class Map{
public:int row,col;int valid; //有效值float value[4];int which_center = -1; public:Map() {row = 0;col = 0;valid = 0;value[0] = value[1] =value[2] =value[3]= 0;} void calc_row_column(int x,int y) {row = x*300;col = y*300;}bool is_valid() {return (value[0]!=0||value[1]!=0||value[2]!=0||value[3]!=0);}
};class vector4 {
public:float val[4];float& operator[](int n) {return val[n];}vector4() {val[0] = val[1] = val[2] = val[3] =0;}
};template<typename T_>
class KCenter {
public:int index; //编号 vector4 center; //中心 int num; //成员数 void set_kcenter(int index,vector4 center){this->index = index;this->center = center;}typename list<T_>::iterator is_member(T_ map) {for(typename list<T_>::iterator itr = member.begin(); itr!=member.end() ; itr++) {if(*itr == map) {return itr;}}return member.end();}void push(T_ map) {member.push_back(map);map->which_center = index;num ++;}void pop(T_ map) {typename list<T_>::iterator pos = is_member(map);if(pos != member.end()) {(*pos)->which_center = -1;member.erase(pos);num--;}}float distance_from_map(T_ samp) {//计算samp距离KCenter的距离 float dist = 0;dist += pow( (center[0]- (samp->value)[0]), 2);dist += pow( (center[1]- (samp->value)[1]), 2);dist += pow( (center[2]- (samp->value)[2]), 2);dist += pow( (center[3]- (samp->value)[3]), 2);return sqrt(dist);}void adjust_center() {//依据成员重新调整自身中心 center[0] = center[1] = center[2] = center[3] = 0;for(typename list<T_>::iterator itr = member.begin(); itr!=member.end() ; itr++) {for(int j=0; j<4; j++)center[j] += ((*itr)->value)[j];}for(int j=0; j<4; j++)center[j] /= num;}float all_distance() {float dist = 0;for(typename list<T_>::iterator itr = member.begin(); itr!=member.end() ; itr++) {dist += distance_from_map(*itr);}return dist;}private:list<T_> member;};const int N_K = 4; //K中心个数
KCenter<Map*> kcenters[N_K];//寻找初始簇的质心
void find_centers(vector4 centers[],int n,Map maps[],int n_maps) {//平均取样值作为簇中心 (预先计算了数据中最大147最小值0) int span = 147;for(int i=0;i<n;i++) {for(int j=0;j<4;j++)centers[i][j] = i*span/(N_K-1);}for(int i=0;i<N_K;i++)cout<<"cu "<<centers[i][0]<<' '<<centers[i][1]<<' '<<centers[i][2]<<' '<<centers[i][3]<<endl;
}void init_centers(vector4 centers[],int n) {//设置初始簇的质心 for(int i=0; i<n; i++) {kcenters[i].set_kcenter(i,centers[i]);}
}bool divide(Map maps[],int n) {//为每个样本分类 //并返回这次是否重新调整过的标志 float dist = 0;int num_select = 0; bool is_adjust = false;for(int i=0; i<n; i++) {//寻找最近簇 dist = kcenters[0].distance_from_map(maps+i);num_select = 0;for(int j=1; j<N_K; j++) {if( dist > kcenters[j].distance_from_map(maps+i) ) {dist = kcenters[j].distance_from_map(maps+i);num_select = j; }}if(maps[i].which_center == -1) {//从未分类过 kcenters[num_select].push(maps+i);is_adjust = true;} else if (maps[i].which_center != num_select){//被分到其他簇//从之前簇取出 kcenters[maps[i].which_center].pop(maps+i);//压入新簇 kcenters[num_select].push(maps+i);is_adjust = true;}}for(int i=0; i<N_K; i++)kcenters[i].adjust_center();return is_adjust;
}/ 以下为获得有效数据 //
int n_maps = -1; //有效矩阵数
Map *maps;int main() {//get_data(maps,&n_maps);//读入原始数据 maps数组保存,n_maps表示元素个数 vector4 centers[5];find_centers(centers,N_K,maps,n_maps);init_centers(centers,N_K);//各簇内数据不再变动作为迭代判断 while(divide(maps,n_maps));for(int i=0;i<N_K;i++) {cout<<kcenters[i].num<<' ';for(int j=0;j<4;j++) cout<<kcenters[i].center[j]<<' ';cout<<endl;}delete [] maps;return 0;
}
分析结果为每种聚类赋一种颜色。
Kmeans算法及其示例相关推荐
- k-means算法实际应用
原文链接:http://www.cnblogs.com/leoo2sk/archive/2010/09/20/k-means.html 4.1.摘要 在前面的文章中,介绍了三种常见的分类算法.分类作为 ...
- 【数据挖掘】数据挖掘算法 组件化思想 示例分析 ( 组件化思想 | Apriori 算法 | K-means 算法 | ID3 算法 )
文章目录 一. 数据挖掘算法组件化思想 二. Apriori 算法 ( 关联分析算法 ) 三. K-means 算法 ( 聚类分析算法 ) 四. ID3 算法 ( 决策树算法 ) 一. 数据挖掘算法组 ...
- java k均值相异度计算_K-NN算法与K-Means算法的原理与区别(附带源码示例)
KNN算法 K-Means算法 目标 确定某个元素所属的分类 将已存在的一系列元素分类 算法类别 监督的分类算法 无监督的聚类算法 数据区别 训练数据中,有明确的标签. 如:一个数据集中有几万张图片, ...
- K-means算法在手写体数字图像数据上的使用示例-代码详解
对应书上的P84页的代码 # coding: utf-8 # 分别导入numpy.matplotlib以及pandas,用于数学运算.作图以及数据分析. import numpy as np impo ...
- R语言KMeans聚类模型示例
R语言KMeans聚类模型示例 K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大.该算法认为簇是由距离靠近的对象组成的,因此把得到 ...
- 【数据挖掘】K-Means 二维数据聚类分析 ( K-Means 迭代总结 | K-Means 初始中心点选择方案 | K-Means 算法优缺点 | K-Means 算法变种 )
文章目录 K-Means 二维数据 聚类分析 数据样本及聚类要求 二维数据曼哈顿距离计算 K-Means 算法 步骤 第一次迭代 : 步骤 ( 1 ) 中心点初始化 第一次迭代 : 步骤 ( 2 ) ...
- 机器学习sklearn19.0聚类算法——Kmeans算法
一.关于聚类及相似度.距离的知识点 二.k-means算法思想与流程 三.sklearn中对于kmeans算法的参数 四.代码示例以及应用的知识点简介 (1)make_blobs:聚类数据生成器 sk ...
- 聚类(Clustering): K-means算法
聚类(Clustering): K-means算法 1.归类: 聚类(clustering)属于非监督学习(unsupervised learning) 无类别标记( class label) 3. ...
- scikit-learn学习之K-means聚类算法与 Mini Batch K-Means算法
====================================================================== 本系列博客主要参考 Scikit-Learn 官方网站上的 ...
最新文章
- variant 字符串数组_VB数组部分核心知识总结
- 安装modelsim
- ime-mode:disabled 禁止表单使用文本框输入法
- 小程序功能模块-在线考试2.10.3源码
- JVM GC一篇通 - 基础与调优
- 闪回flashback table配合flashback versions query的注意事项
- php设置mysql 编码_PHP和Mysql中转UTF8编码问题汇总
- 为什么自建深度学习机器?因为比AWS便宜10倍啊!
- iozone文件系统测试工具
- layui 表格前端分页
- 前馈pid系数_前馈PID控制
- 我的JAVA面试经验(5年左右工作经验)
- 什么是单工、半双工和双工通信(最详细)
- 基于移动端的快递物流信息管理系统Uniapp
- python反爬虫原理与绕过实战pdf-antispider
- Java项目:ssm+mysql医药进销存系统
- 通过FPGA计算矩阵的伪逆pinv
- seo全攻略_Shopify店铺SEO最全攻略(新手必看!!)
- 解决使用打印机打印网页时字体颜色变淡的问题
- 五子棋1.0(Java单机版)