Hierarchical cluster算法介绍
突然想记录几个聚类算法,由于实力有限就先介绍一下层次聚类算法(Hierarchical cluster algorithm),这个聚类算法思想简单,但实现起来感觉复杂度挺大;以前看过《集体智慧编程》里介绍过,里面是用python实现的,由于python里面的列表和字典用起来方便,故实现该算法还行;这里我用c++重新写了一下,感觉代码蛮臃肿,可能是自己的c++没有学习好吧!!!对于容器的使用还不够熟练,这里贴出来的目的是希望哪位大牛看到了指导一二,这里感激不尽。废话不多说了,进入正题吧!
************************************************************************************************************
Hierarchical cluster Algorithm的大致介绍
层次聚类算法有两种实现思想,一种是初始时将每个待聚类的数据样本视为一个cluster,采用合并的方式,每次合并两个"距离"最近的cluster,直到合并成一个cluster为止(当然可以在达到自己设定想得到的cluster个数时终止迭代);另一种刚好与第一种相反,初始时将所有的数据样本视为一个cluster,采用分解的方式(这里没有实现就不说太多)。
************************************************************************************************************
算法的步骤及相关问题
算法步骤: (1)初始时,将每个数据样本视为一个cluster(选取一个度量两个cluster距离的方式),
(2)计算任意两个cluster之间的距离;每次选取距离最小的两个cluster,
(3)合并(2)中选择的两个cluster,将合并产生的新cluster加入cluster set中,并删除被合并的两个cluster,
(4)重复(2)(3),知道cluster set中元素只剩下一个为止。
相关问题: (1)度量两个cluster之间的距离,应该选择哪种距离???《集体智慧编程》中选择的是Pearson,当然也可以直接选用欧氏距离
(2)如何合并两个cluster,即新的cluster对应的属性值如何表示???这里是用被合并的两个cluster的平均值表示新的cluster
******************************************************************************************************************
/**
** Hierarchical cluster Algorithm
** step:(1)Firstly,regard each sample as a cluster, and
(2)Each time merge two clusters if the distance between them is lowest.
(3)then add the new cluster into cluster set, and delete two clusters merged from cluster set.
** method: (1)as to merging, here replace the old two clusters with their average;
(2)measure the distance with the Pearson similarity.
** Time:2013/7/10
**/
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <cstring>
#include <sstream>
#include <cmath>
#include <iterator>
using namespace std;
//cluster
typedef struct bicluster{
vector<double> attri;//attribute
int cid;//cluster id
}Bicluster;
//a pair
typedef struct lowpair{
int leftid;
int rightid;
double dist;
}Lpair; /*****************************************************************
** convert string(char*) to double(or other type)
** here should be included <sstream> before using the stringstream
******************************************************************/
double str2double(char* str){
stringstream ss;
ss << str;
double tmp;
ss >> tmp;
return tmp;
}
/*****************************************************************
** split the string containing some special tokens
******************************************************************/
string split(string &str, vector<double>& dvec, const char* tok){
char *pch = NULL;
pch = strtok(const_cast<char*>(str.c_str()), tok);
string stmp(pch);
while( pch != NULL ){
pch = strtok(NULL, tok);
if( !pch )
break;
dvec.push_back(str2double(pch));
}
return stmp;
}
/******************************************************************
** read data from 'blogdata.txt'
** @is ------- a reference to ifstream object(input)
** @data ----- a map used to store the data (output)
******************************************************************/
bool readfile(ifstream &is, map<string, vector<double> >& mydata){
if( is.fail() ){
cerr << "can't open the file !!!" << endl;
return false;
}
//ignore the first line of file
string str;
getline(is, str); //store the data read from file into mydata
while( !is.eof() ){
vector<double> dtmp;
string tmp;
getline(is, str);
tmp = split(str, dtmp, "\t");
mydata.insert(pair<string,vector<double> >(tmp, dtmp));
}
return true;
}
/*****************************************************************
** compute the distance between two clusters
** Note that Pearson value devotes to the similarity between
two clusters, that is, the greater the Pearson value, the
lower the distance between them.
*****************************************************************/
double distPearson(vector<double>& left, vector<double>& right){
double sum1 = ;
double sum2 = ;
int len = left.size();
for(int i=; i<len; ++i){
sum1 += left[i];
sum2 += right[i];
} /**
** maybe you will feel it's complex,
** and here we could replace Pearson with Euclidean distance
**/
double sum1Sq = ;
double sum2Sq = ;
for(int j=; j<len; ++j){
sum1Sq += pow(left[j], );
sum2Sq += pow(right[j], );
} double pSum = , num, den;
for(int k=; k<len; ++k)
pSum += left[k]*right[k];
num = pSum - sum1*sum2 / len;
den = sqrt((sum1Sq - pow(sum1,)/len) * (sum1Sq - pow(sum2,)/len));
if( den == )
return ;
return 1.0 - num/den;
}
/*************************************************************
** Given two clusters, the distance between them
should be checked whether it exists before compute it.
**************************************************************/
bool isExist(vector<Lpair> &lp, int leftid, int rightid, double &d){
vector<Lpair>::iterator it = lp.begin();
for(; it!=lp.end(); ++it){
if( (it->leftid==leftid) && (it->rightid==rightid) ){
d = it->dist;//if the distance has been computed, assign its value to d
return true;
}
}
d = ;
return false;
}
/*************************************************************
** Given a cluster's id, delete the cluster from cluster set
**************************************************************/
void Del(vector<Bicluster> &cvec, int clusterid){
vector<Bicluster>::iterator it = cvec.begin();
for(; it!=cvec.end(); ++it){
if( it->cid == clusterid )
break;
}
cvec.erase(it);
}
/*************************************************************
** Hierarchical Cluster Algorithm
**************************************************************/
void HierarchicalCluster(map<string, vector<double> > &mydata){
vector<Lpair> distances;//used to store the distance //firstly,regard each sample as a cluster
vector<Bicluster> cvec;
map<string, vector<double> >::iterator it = mydata.begin();
int myid = ;
for(; it!= mydata.end(); ++it){
Bicluster btmp;
btmp.attri = it->second;
btmp.cid = myid++;
cvec.push_back(btmp);
}
myid = -;
//search the pair
while( cvec.size()> ){
Lpair lowp;
double closedis = distPearson(cvec[].attri,cvec[].attri);
lowp.leftid = cvec[].cid, lowp.rightid = cvec[].cid;
lowp.dist = closedis; int leftps = , rightps = ;
for(int ix=; ix<cvec.size(); ++ix){
for(int iy=ix+; iy<cvec.size(); ++iy){
double d;
int lid = cvec[ix].cid, rid = cvec[iy].cid;
if( !isExist(distances,lid,rid,d) ){
Lpair lptmp;
lptmp.dist = distPearson(cvec[ix].attri, cvec[iy].attri);
lptmp.leftid = lid;
lptmp.rightid= rid;
distances.push_back(lptmp);
d = lptmp.dist;
}
if( d < lowp.dist ){
lowp.leftid = lid;
lowp.rightid = rid;
leftps = ix;
rightps = iy;
lowp.dist = d;
}
}
}
//create a new cluster
Bicluster ncluster;
for(int i=; i<cvec[].attri.size(); ++i){
double av;
av = (cvec[leftps].attri[i] + cvec[rightps].attri[i]) / 2.0;
ncluster.attri.push_back(av);
}
ncluster.cid = myid--;//assign negative to the new cluster's id
cout << "leftid: " << lowp.leftid << ", rightid: " << lowp.rightid << endl;
//delete the pair
Del(cvec, lowp.leftid);
Del(cvec, lowp.rightid);
cvec.push_back(ncluster);
}
}
int main()
{
ifstream is("blogdata.txt");
if( is.fail() ){
cerr << "error!!!" << endl;
exit(-);
}
map<string, vector<double> > mydata;
if(readfile(is, mydata))
HierarchicalCluster(mydata);
return ;
}
代码写的有点乱且复杂,最后显示的结果不是树状图(python很易实现),只是简单的显示了每次被合并的两个cluster的id.代码中用到的数据可以从http://kiwitobes.com/clusters/blog.txt下载得到。
Hierarchical cluster算法介绍的更多相关文章
- matlab下K-means Cluster 算法实现
一.概念介绍 K-means算法是硬聚类算法,是典型的局域原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则.K-means算法以欧 ...
- k-means|k-mode|k-prototype|PAM|AGNES|DIANA|Hierarchical cluster|DA|VIF|
聚类算法: 对于数值变量,k-means eg:k=4,则选出不在原数据中的4个点,计算图形中每个点到这四个点之间的距离,距离最近的便是属于那一类.标准化之后便没有单位差异了,就可以相互比较. 对于分 ...
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...
- KNN算法介绍
KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...
- ISP基本框架及算法介绍
什么是ISP,他的工作原理是怎样的? ISP是Image Signal Processor的缩写,全称是影像处理器.在相机成像的整个环节中,它负责接收感光元件(Sensor)的原始信号数据,可以理解为 ...
- Python之常见算法介绍
一.算法介绍 1. 算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输 ...
- RETE算法介绍
RETE算法介绍一. rete概述Rete算法是一种前向规则快速匹配算法,其匹配速度与规则数目无关.Rete是拉丁文,对应英文是net,也就是网络.Rete算法通过形成一个rete网络进行模式匹配,利 ...
- H2O中的随机森林算法介绍及其项目实战(python实现)
H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...
- STL 算法介绍
STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成. <algorithm ...
随机推荐
- ApplePay扩大全球发卡行合作,“苹果税”撑不住了?
5月11日Apple Pay全面登陆加拿大地区,更为重要的是,苹果终于在一些地区,开始和美国运通之外的发卡行达成了合作.这对于老是因为分账问题不愿意走出下一步的Apple Pay来说,已经是巨大的进步 ...
- AO创建IFeature的两种方法
原文地址:http://www.cnblogs.com/MyLucifer/archive/2010/12/01/1893212.html 在ArcGIS Resouce Center中,ESRI介绍 ...
- Unified Emoji表情for Android
这个是我做Android以来碰到的最烦的东西,该死的emoji表情,恨之入骨..无奈这个问题分配给我了.我也只能硬着头皮做. 0.吐个槽先 首先,你要明白什么是emoji表情,不知道的google,不 ...
- EJB--事务管理 .
在我们对事务的基本概念以及出现的问题和隔离级别有进一步的了解之后,接下来看看EJB是如何进行事务管理. 在EJB中有两种使用事务的方式.第一种方式通过容器管理的事务,叫CMT(Container-Ma ...
- 即时通信Spark安装和配置
spark:Cross-platform real-time collaboration client optimized for business and organizations.Spark i ...
- ActiveMQ之消息指针
消息指针(Message cursor)是activeMQ里一个非常重要的核心类,它是提供某种优化消息存储的方法.消息中间件的实现一般都是当消费者准备好消费消息的时候,它会从持久化存储中一批一批的读取 ...
- NDK(14)Native的char*和Java的String相互转换
转自: http://www.cnblogs.com/canphp/archive/2012/11/13/2768937.html 首先确保C/C++源文件的字符编码是UTF-8与JAVA的class ...
- [POJ3694]Network(LCA, 割边, 桥)
题目链接:http://poj.org/problem?id=3694 题意:给一张图,每次加一条边,问割边数量. tarjan先找出所有割边,并且记录每个点的父亲和来自于哪一条边,然后询问的时候从两 ...
- UVa 116 (多段图的最短路) Unidirectional TSP
题意: 有一个m行n列的正整数环形矩阵(即矩阵第一行的上一行是最后一行,最后一行的下一行是第一行),从第一列的任意位置出发,每次只能向右,右上,右下三个方向行走,输出路径及路径上所有数之和的最大值,多 ...
- UVa 12716 (GCD == XOR) GCD XOR
题意: 问整数n以内,有多少对整数a.b满足(1≤b≤a)且gcd(a, b) = xor(a, b) 分析: gcd和xor看起来风马牛不相及的运算,居然有一个比较"神奇"的结论 ...