birch聚类算法

参考百度百科http://baike.baidu.com/link?url=LDYen7bEqt8o2l5mUrnZjQk1topFi36-MwLuhjuGf-1z4sQFtFq1xCEe0TCJwYVjGbu0C6cpuVMFIxNglvSnoa

外加http://www.cnblogs.com/zhangchaoyang/articles/2200800.html

学习birch聚类最好有B-树的知识

结合了B-树的特性,birch算法适合于处理大数据。

原因是:

(1)CF 结构概括了簇的基本信息,并且是高度压缩的,它存储了小于实际数据点的聚类信息。每个新添加的数据其作为个体消失了,将信息融入的集合簇中

(2)增量式的学习方法,不用一次将数据全部加载到内存,可以一边添加数据一边进行学习


下面是我的实现


// birch-cluster.cpp : 定义控制台应用程序的入口点。
//

///************birch-cluster*************///
///*******   author Marshall     ********///
///*******   2015.9.18           ********///
///*******   version 1.0         ********///


#include "stdafx.h"
#include<vector>
#include<iostream>
#include<cstdlib>
#include<time.h>

#define BirchType int

using namespace std;



vector<BirchType> operator+(vector<BirchType>aa, vector<BirchType>&bb){
	_ASSERTE(aa.size() == bb.size());
	for (int i = 0; i < aa.size(); i++)
		aa[i] += bb[i];
	return aa;
}

vector<BirchType> operator*(vector<BirchType>aa, vector<BirchType>&bb){
	_ASSERTE(aa.size() == bb.size());
	for (int i = 0; i < aa.size(); i++)
		aa[i] *= bb[i];
	return aa;
}

vector<BirchType> operator-(vector<BirchType>aa, vector<BirchType>&bb){
	_ASSERTE(aa.size() == bb.size());
	for (int i = 0; i < aa.size(); i++)
		aa[i] -= bb[i];
	return aa;
}

vector<BirchType> operator*(vector<BirchType>aa, double k){

	for (int i = 0; i < aa.size(); i++)
		aa[i] = double(aa[i])* k;
	return aa;
}
vector<BirchType> operator*(int k, vector<BirchType>aa){

	for (int i = 0; i < aa.size(); i++)
		aa[i] *= k;
	return aa;
}
class birch
{
public:
	struct Attribute
	{
		unsigned int dim;
		vector<BirchType>data;
		Attribute(unsigned int d) :dim(d)
		{
			data.resize(dim);
		}
	};
	struct CF
	{
		unsigned int N;
		vector<BirchType> LS;
		vector<BirchType> SS;
		CF(unsigned int N,
			vector<BirchType> LS,
			vector<BirchType>SS) :N(N), LS(LS), SS(SS){}
		/*CF(CF& cc){//shallow copy is enough
			this->N = cc.N;
			this->LS = cc.LS;
			this->SS = cc.SS;
			}*/
		CF(unsigned int dim){
			N = 0;
			LS.resize(dim);
			SS.resize(dim);
		};
		CF(){};
	};

	struct Leaf;
	struct MinCluster
	{
		CF cf;
		Leaf*parent;
		MinCluster()
		{
			parent = NULL;
		}
		MinCluster(CF cf)
		{
			parent = NULL;
			this->cf = cf;
		}
	};

	struct Leaf
	{
		Leaf*pre, *next;//to make up a leaf-list.for Nonleaf,NULL
		Leaf*parent;
		vector<Leaf*>*child;//对Leaf而言为NULL
		vector<MinCluster>*cluster;//对NonLeaf而言为NULL
		CF cf;
		Leaf()
		{
			parent = pre = next = NULL;
			child = NULL;
			cluster = NULL;
		}
	};
	void generate_data(int num, int dim, vector<int>&span)
	{
		this->dim = dim;
		_ASSERTE(span.size() == dim);
		for (int i = 0; i < num; i++)
		{
			Attribute att(dim);
			for (int j = 0; j < dim; j++)
				att.data[j] = span[j] * double(rand()) / double(RAND_MAX + 1.0);
			dataset.push_back(att);
		}
	}
	vector<Attribute>dataset;

	int absorbnum;

public:
	birch(unsigned int b, unsigned int l, unsigned int t)
		:B(b), L(l), T(t){
		_ASSERTE(B > 2);
		_ASSERTE(L > 3);
		root = NULL;
		time_t tt;
		srand(time(&tt));
		absorbnum = 0;
	}
	~birch();
	void insert(Attribute att);


private:

	unsigned int B; //maximal num of child a Nonleaf will have
	unsigned int L;//maximal num of MinCluster a leaf will haveLeaf
	unsigned int T;// MinCluster的直径不能超过T
	Leaf*root;
	Leaf*head;//the head of the leaf-list at the bottom of the tree
	int dim;


private:
	inline double lengthofvec(vector<BirchType>&aa){
		double len = 0;
		for (int i = 0; i < aa.size(); i++)
			len += pow(aa[i], 2.0);
		return sqrt(len);
	}
	double sumofvec(vector<BirchType>&aa){
		double sum = 0;
		for (int i = 0; i < aa.size(); i++)
			sum += aa[i];
		return sum;
	}

	double cal_inter_cluster_dis(CF &cf1, CF &cf2);
	double cal_intra_cluster_dis();
	double merge_cluster_diameter(CF &cf1, CF &cf2);
	vector<BirchType>updateSS(vector<BirchType>&LS, vector<BirchType>&SS)
	{
		for (int i = 0; i < LS.size(); i++)
			SS[i] += pow(LS[i], 2.0);
		return SS;
	}
	CF updateCF(CF &c1, CF &c2)
	{
		return CF(c1.N + c2.N, c1.LS + c2.LS, c1.SS + c2.SS);
	}
	void updateCF(Leaf*leaf)
	{
		CF cf(dim);
		if (leaf->cluster != NULL)
		{

			for (int i = 0; i < leaf->cluster->size(); i++)
			{
				cf.N = cf.N + (*leaf->cluster)[i].cf.N;
				cf.LS = cf.LS + (*leaf->cluster)[i].cf.LS;
				cf.SS = cf.SS + (*leaf->cluster)[i].cf.SS;
			}
		}
		else if (leaf->child != NULL)
		{
			for (int i = 0; i < leaf->child->size(); i++)
			{
				cf.N = cf.N + (*leaf->child)[i]->cf.N;
				cf.LS = cf.LS + (*leaf->child)[i]->cf.LS;
				cf.SS = cf.SS + (*leaf->child)[i]->cf.SS;
			}
		}
		leaf->cf = cf;
	}

	MinCluster create_mincluster(Attribute att)
	{
		vector<BirchType>aa;
		aa.resize(att.dim);
		return MinCluster(CF(1, att.data, updateSS(att.data, aa)));
	}

	void insert(Leaf*close, bool &split, MinCluster &clu);



};

birch::~birch()
{
	Leaf*plist = head;
	while (plist != NULL)
	{
		delete plist->cluster;
		plist = plist->next;
	}
	vector<Leaf*>aa, bb;
	aa.push_back(root);
	while (!aa.empty())
	{
		Leaf*pleaf = aa.back();
		aa.pop_back();
		bb.push_back(pleaf);
		if (pleaf->child != NULL)
			aa.insert(aa.end(), pleaf->child->begin(), pleaf->child->end());
	}
	for (int i = 0; i < bb.size(); i++)
	{
		if (bb[i]->child != NULL)
			delete bb[i]->child;
		delete bb[i];
	}
}
/*double birch::merge_cluster_diameter(CF &cf1, CF &cf2)
{
return sqrt(sumofvec(cf1.SS *(1.0 / double(cf1.N))
+ cf2.SS *(1.0 / double(cf1.N)) -
2 * cf1.LS*cf2.LS*(1.0 / double(cf1.N + cf2.N))));
}*/

double birch::merge_cluster_diameter(CF &cf1, CF &cf2)
{
	return sqrt(sumofvec(cf1.SS *(1.0 / double(cf1.N))
		+ cf2.SS *(1.0 / double(cf1.N)) -
		2 * cf1.LS*cf2.LS*(1.0 / double(cf1.N + cf2.N))));
}


void birch::insert(Attribute att)
{
	if (root == NULL)
	{
		root = new Leaf;
		root->cluster = new vector < MinCluster > ;
		(*root->cluster).push_back(create_mincluster(att));
		root->cf = CF((*root->cluster)[0].cf);
		head = root;
		head->pre = NULL;
		head->next = NULL;
		return;
	}
	MinCluster clu = create_mincluster(att);
	Leaf*leaf = root;

	vector<int>path;

	while (leaf->cluster == NULL)
	{
		int k = -1;
		double mindis = 10000000000000;
		double dd;
		for (int i = 0; i < (*leaf->child).size(); i++)
		{
			double dis = cal_inter_cluster_dis(clu.cf, (*leaf->child)[i]->cf);
			if (dis < mindis)
			{
				mindis = dis;
				k = i;
			}
			dd = dis;
		}

		_ASSERTE(k >= 0);
		path.push_back(k);
		leaf = (*leaf->child)[k];
	}



	int k = -1;
	//mindis = 100000;
	double mindis = 100000;
	for (int i = 0; i < (*leaf->cluster).size(); i++)
	{
		double dis = cal_inter_cluster_dis(clu.cf, (*leaf->cluster)[i].cf);
		if (dis < mindis)
		{
			mindis = dis;
			k = i;
		}
		_ASSERTE(k >= 0);
	}
	//double ttt = merge_cluster_diameter(clu.cf, (*leaf->cluster)[k].cf);

	double ttt = cal_inter_cluster_dis(clu.cf, (*leaf->cluster)[k].cf);
	if (ttt < T)
	{
		//absorb
		(*leaf->cluster)[k].cf = updateCF((*leaf->cluster)[k].cf, clu.cf);
		absorbnum++;
	}
	else
	{
		(*leaf->cluster).push_back(clu);
	}
	//update CF value along the path
	Leaf*lea = root;
	(*lea).cf = updateCF((*lea).cf, clu.cf);
	for (int i = 0; i < path.size(); i++)
	{
		(*lea->child)[path[i]]->cf = updateCF((*lea->child)[path[i]]->cf, clu.cf);
		lea = (*lea->child)[path[i]];
	}

	if ((*leaf->cluster).size() > L)
	{
		double maxdis = 0;
		int th1 = -1;
		int th2 = -1;
		double**dismatrix = new double*[(*leaf->cluster).size()];
		for (int i = 0; i < (*leaf->cluster).size(); i++)
			dismatrix[i] = new double[(*leaf->cluster).size()];
		//找到距离最远的两个簇
		for (int i = 0; i < (*leaf->cluster).size() - 1; i++)
			for (int h = i + 1; h < (*leaf->cluster).size(); h++)
			{
				double dis = cal_inter_cluster_dis((*leaf->cluster)[i].cf, (*leaf->cluster)[h].cf);
				dismatrix[i][h] = dis;
				dismatrix[h][i] = dis;
				if (dis > maxdis)
				{
					maxdis = dis;
					th1 = i; th2 = h;
				}
			}
		Leaf*new_leaf = new Leaf;
		new_leaf->cluster = new vector < MinCluster > ;
		new_leaf->cluster->push_back((*leaf->cluster)[th2]);
		int len = (*leaf->cluster).size();
		(*leaf->cluster)[th2].parent = new_leaf;

		//根据各簇与两个新簇的距离分配到两个新簇中
		for (int i = 0; i < len; i++)
		{
			if (i == th1 || i == th2)
				continue;
			if (dismatrix[i][th2] < dismatrix[i][th1])
			{
				(*leaf->cluster)[i].parent = new_leaf;
				new_leaf->cluster->push_back((*leaf->cluster)[i]);

			}
		}
		for (int i = 0; i < (*leaf->cluster).size(); i++)
			delete[] dismatrix[i];
		delete[]dismatrix;

		vector < MinCluster >::iterator it, it1;
		it = (*leaf->cluster).begin();
		while (it != (*leaf->cluster).end())
		{
			if (it->parent == new_leaf)
				it = (*leaf->cluster).erase(it);
			else
			{
				it++;
			}
		}
		//不要忘了更新leaf和new_leaf的cf值
		updateCF(leaf);
		updateCF(new_leaf);
		//不要忘了将new_leaf加入到链表中
		Leaf*next = leaf->next;
		leaf->next = new_leaf;
		new_leaf->pre = leaf;
		new_leaf->next = next;
		if (next)
			next->pre = new_leaf;
		if (leaf->parent != NULL)
		{
			leaf->parent->child->push_back(new_leaf);
			new_leaf->parent = leaf->parent;
		}
		else//leaf is root,then a new root should be created
		{
			Leaf*new_root = new Leaf;
			new_root->child = new vector < Leaf* > ;
			new_root->child->push_back(leaf);
			new_root->child->push_back(new_leaf);
			leaf->parent = new_root;
			new_leaf->parent = new_root;
			updateCF(new_root);
			root = new_root;
			return;
		}
	}
	Leaf*cur = leaf->parent;
	while (cur != NULL&&cur->child->size() > B)
	{
		double maxdis = 0;
		int th1 = -1;
		int th2 = -1;
		double**dismatrix = new double*[cur->child->size()];
		for (int i = 0; i < cur->child->size(); i++)
			dismatrix[i] = new double[cur->child->size()];
		//找到距离最远的两个leaf
		for (int i = 0; i < cur->child->size() - 1; i++)
			for (int h = i + 1; h < cur->child->size(); h++)
			{
				double dis = cal_inter_cluster_dis((*cur->child)[i]->cf, (*cur->child)[h]->cf);
				dismatrix[i][h] = dis;
				dismatrix[h][i] = dis;
				if (dis > maxdis)
				{
					maxdis = dis;
					th1 = i; th2 = h;
				}
			}

		Leaf*new_leaf1 = new Leaf;
		new_leaf1->child = new vector < Leaf* > ;
		(*cur->child)[th2]->parent = new_leaf1;
		(*new_leaf1->child).push_back((*cur->child)[th2]);
		int len = (*cur->child).size();

		//rearrange other leaves to th1 th2 as their child
		for (int i = 0; i < len; i++)
		{
			if (i == th1 || i == th2)
				continue;
			if (dismatrix[i][th2] < dismatrix[i][th1])
			{
				(*cur->child)[i]->parent = new_leaf1;
				new_leaf1->child->push_back((*cur->child)[i]);

			}
		}
		for (int i = 0; i < (*cur->child).size(); i++)
			delete[] dismatrix[i];
		delete[]dismatrix;

		vector < Leaf* >::iterator it;
		it = (*cur->child).begin();
		while (it != (*cur->child).end())
		{
			if ((*it)->parent == new_leaf1)
				it = (*cur->child).erase(it);
			else
				it++;
		}
		//不要忘了更新cur和new_leaf1的cf值
		updateCF(cur);
		updateCF(new_leaf1);

		//if cur is root,then a new root should be created
		if (cur->parent == NULL)
		{
			Leaf*new_root = new Leaf;
			new_root->child = new vector < Leaf* > ;
			new_root->child->push_back(cur);
			new_root->child->push_back(new_leaf1);
			cur->parent = new_root;
			new_leaf1->parent = new_root;
			updateCF(new_root);
			root = new_root;
			return;
		}

		//cur is not root
		//不要忘了将new_leaf1加入cur的父亲节点的child
		cur->parent->child->push_back(new_leaf1);
		new_leaf1->parent = cur->parent;
		cur = cur->parent;
	}

}



//根据CF值计算簇间距离
/*double birch::cal_inter_cluster_dis(CF &cf1, CF &cf2)
{
return sqrt(sumofvec((2 * (cf1.N + cf2.N)*(cf1.SS + cf2.SS)
- 2 * (cf1.LS + cf2.LS)*(cf1.LS + cf2.LS))*
(1.0 / double(cf1.N + cf2.N)*(cf1.N + cf2.N - 1))));
}*/

double birch::cal_inter_cluster_dis(CF &cf1, CF &cf2)
{
	double dis = 0;
	double temp;
	for (int i = 0; i < dim; i++)
	{
		double t1 = double(cf1.LS[i]) / double(cf1.N);
		double t2 = double(cf2.LS[i]) / double(cf2.N);
		temp = t1 - t2;
		dis += temp*temp;
	}

	return sqrt(dis);
}




int _tmain(int argc, _TCHAR* argv[])
{
	//vector<int*>aa, bb;
	//int *p1 = new int;
	//int *p2 = new int;
	//int *p3 = new int;
	//*p1 = 8;
	//*p2 = 9;
	//*p3 = 88;
	//aa.push_back(p1);
	//aa.push_back(p2);
	//aa.push_back(p3);
	//*aa[2] = 999;
	//bb.push_back(p3);
	//vector<int*>::iterator it = aa.begin() + 1;
	////delete aa[0];
	//it = aa.erase(it);

	//cout << *bb[0] << endl;
	//cout << **it << endl;
	//for (it = aa.begin(); it != aa.end(); it++)
	//	cout << **it << endl;

	birch bir(5, 6, 20);
	int dim = 2;
	int num = 1000;
	vector<int>span;
	for (int i = 0; i < dim; i++)
		span.push_back(1000);
	bir.generate_data(num, dim, span);
	for (int i = 0; i < num; i++)
		bir.insert(bir.dataset[i]);
	cout << bir.absorbnum << endl;
	system("pause");
	return 0;
}


版权声明:

posted on 2015-09-20 20:19  moffis  阅读(653)  评论(1编辑  收藏  举报

导航