Hadoop实现Clustering by fast search and find of density peaks
本篇博客参考:Clustering by fast search and find of density peaks论文以及http://www.cnblogs.com/peghoty/p/3945653.html。
Hadoop版本:2.6.0,Myeclipse:10.0
代码可在https://github.com/fansy1990/fast_cluster (算法实现请参考http://blog.csdn.net/fansy1990/article/details/47041841)下载。
1. 实现思路
1.1. 输入数据
代码可以采用任意维度的数据,使用文本存储,其一般格式如下(为方便作图,使用两位数据):
6.5,18.9,2
6.6,17.65,2
6.65,18.3,2
7.3,18.35,2
7.85,18.3,2
7.15,17.8,2
7.6,17.7,2
。。。
1.2. 整体思路描述
1)计算每个点的“局部密度距离”(参考论文);
2)计算每个点的“超密度最小距离”(这里翻译有点问题,额可以参考原论文);
3)画出决策图来人工判断可以选取的聚类中心个数;
4)根据选择的聚类中心来使用临近点判别法循环使用已分类数据来分类未分类数据;
1.3. 计算“局部密度距离”
计算“局部密度距离”时,遍历输入文件,同时把输入文件当做参考。针对输入文件的每行数据inputI遍历所有输入文件(不包括inputI)来计算其和其他点的距离,如果小于给定的阈值dc,那么就把这个点的局部密度加1(这里计算局部密度有两种方式,参考博客前面给出的参考博客);其Mapper如下:
package fz.fast_cluster.mr;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import fz.fast_cluster.keytype.DoubleArrWritable;
import fz.utils.HUtils;
/**
* @author fansy
* @date 2015-5-28
*/
public class LocalDensityMapper extends Mapper<LongWritable, Text, DoubleArrWritable, DoubleWritable> {
private double dc;
private Path input;
private String splitter=",";
private String method =null;
private DoubleWritable sumAll= new DoubleWritable();
private DoubleArrWritable keyDoubleArr;
@Override
public void setup(Context cxt){
dc=cxt.getConfiguration().getDouble("DC", 0);
input=new Path(cxt.getConfiguration().get("INPUT"));//
splitter = cxt.getConfiguration().get("SPLITTER", ",");
method = cxt.getConfiguration().get("METHOD", "gaussian");
}
@Override
public void map(LongWritable key,Text value,Context cxt)throws InterruptedException,IOException{
// get the ith line of all data;
double[] inputI= HUtils.getInputI(value,splitter);
double sum=0;
// hdfs
try{
FileSystem fs = FileSystem.get(cxt.getConfiguration());
InputStream in = fs.open(input);
BufferedReader buff = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line=buff.readLine())!=null){
double[] inputLine = HUtils.getInputI(line,splitter);
double distance = HUtils.getDistance(inputI,inputLine);
if(distance<dc&&distance>0){ // distance should be grater than 0,
if(method.equals("gaussian")){
sum+=Math.pow(Math.E, -(distance/dc)*(distance/dc));
}else{
sum+=1;
}
}
}
}catch(Exception e){
e.printStackTrace();
}
// output if the point has at least one neighbor
if(sum>0){
sumAll.set(sum);
keyDoubleArr = new DoubleArrWritable(inputI);
cxt.write(keyDoubleArr, sumAll);
}
}
}
1.4. 计算“超密度最小距离”
根据1.3. 计算的结果,使用1.3.的输出作为输入,针对单个输入,遍历1.3.的所有输出并计算点之间的距离,找到距离最小的点,同时要求该距离最小的点对应的点的局部密度要大于当前点的局部密度。针对全局最大的局部密度的点,直接计算距离与其最远的距离即可。其Mapper代码如下:
package fz.fast_cluster.mr;
import java.io.IOException;
import org.apac