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 
#include 
#include 
#include 
#include 
//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
class KCenter {
public:
	int index;		//编号 
	vector4 center;		//中心 
	int num;		//成员数 
	
	
	void set_kcenter(int index,vector4 center){
		this->index = index;
		this->center = center;
	}
	typename list::iterator is_member(T_ map) {
		for(typename list::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::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::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::iterator itr = member.begin(); itr!=member.end() ; itr++) {
			dist += distance_from_map(*itr);
		}
		return dist;
	}
	
private:
	list member;
	
};

const int N_K = 4; //K中心个数 
KCenter 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 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


 

 

 

 

分析结果为每种聚类赋一种颜色。

 

你可能感兴趣的:(Algorithm,AI,数据分析)