mahout 源码解析之聚类--聚类策略

来源:互联网 发布:淘宝信用账户开通要求 编辑:程序博客网 时间:2024/06/08 17:53

考虑到先前我们讲到的canopy算法的源码里面有关于CanopyClusteringPolicy的问题,以及后面将要讲到的K-means,fuzzy K-means都会出现聚类策略的问题,在这里我们就先将这些都拿来讲一讲。
聚类策略的代码全部都在包org.apache.mahout.clustering.iterator里面,下面我们来一一解读。


一、ClusteringPolicy
ClusteringPolicy接口定义了四个方法

/** * prior利用其里面的聚类模型,对样本进行分类,也就是计算每个聚类模型对于此样本的pdf或者其他的分类概率表示 */public Vector classify(Vector data, ClusterClassifier prior);/** * 获得带权重的pdf,基本上是将probabilities最大位置上的值置1.0,其他位置上的值置0.0,但是对于模糊k均值而言,就是直接返回结果。主要是因为很多算法一个样本最后只能属于一个簇,而模糊K均值一个样本能以某种概率属于多个簇。 */public Vector select(Vector probabilities);/** * 更新聚类策略 */public void update(ClusterClassifier posterior);/** * 关闭聚类策略,基本上更新参数 */public void close(ClusterClassifier posterior);

二、AbstractClusteringPolicy


AbstractClusteringPolicy抽象类实现了接口ClusteringPolicy,主要实现了四个方法中的三个。我们来一一分析。

classify函数主要用来计算样本属于每个聚类模型的概率。在实现的时候还对pdf进行了归一化处理,如下所示:

@Overridepublic Vector classify(Vector data, ClusterClassifier prior) {// 获取聚类分类的所有聚类模型List<Cluster> models = prior.getModels();int i = 0;Vector pdfs = new DenseVector(models.size());//记录每个聚类模型对此样本的pdffor (Cluster model : models) {pdfs.set(i++, model.pdf(new VectorWritable(data)));}return pdfs.assign(new TimesFunction(), 1.0 / pdfs.zSum());}

select函数主要是获得带权重的pdf,其输入可以是classify的结果,在此抽样类里面主要是将最大值置1.0,其他值置0.0处理。这个是一个样本只能属于一个簇的表现形式,,我们等下可以看到模糊k均值会有另外一种处理方式。

@Overridepublic Vector select(Vector probabilities) {//将probabilities最大元素位置置1.0,其他位置置0.0int maxValueIndex = probabilities.maxValueIndex();Vector weights = new SequentialAccessSparseVector(probabilities.size());weights.set(maxValueIndex, 1.0);return weights;}

update函数在此类中没有实现。
close函数也是简单将ClusterClassifier中的模型进行了参数的重新计算。关于ClusterClassifier,我们将在下一篇博客中进行讲解。

@Overridepublic void close(ClusterClassifier posterior) {for (Cluster cluster : posterior.getModels()) {cluster.computeParameters();}}

三、CanopyClusteringPolicy

CanopyClusteringPolicy类继承AbstractClusteringPolicy,在其基础上添加了两个参数t1和t2。实现了一个函数select,但是代码跟AbstractClusteringPolicy里面的完全一样(完全不知道为什么这么干)。


四、FuzzyKMeansClusteringPolicy

在类FuzzyKMeansClusteringPolicy中我们重点分析下函数classify,其主要是利用ClusterClassifier里面的聚类模型,先计算出样本向量与此聚类模型的距离,再将聚类模型列表和距离列表传给FuzzyKMeansClusterer进行处理,将其函数computePi的结果作为classify的返回值。

@Overridepublic Vector classify(Vector data, ClusterClassifier prior) {Collection<SoftCluster> clusters = Lists.newArrayList();//将prior中的聚类模型转换成SoftClusterList<Double> distances = Lists.newArrayList();//记录每个SoftCluster中心与向量的距离for (Cluster model : prior.getModels()) {SoftCluster sc = (SoftCluster) model;clusters.add(sc);distances.add(sc.getMeasure().distance(data, sc.getCenter()));}FuzzyKMeansClusterer fuzzyKMeansClusterer = new FuzzyKMeansClusterer();fuzzyKMeansClusterer.setM(m);return fuzzyKMeansClusterer.computePi(clusters, distances);}

我们再深入到类FuzzyKMeansClusterer看看。在此类中定义了两个属性,一个是聚类距离的最小值,当小于这个值时,可将距离视为0。还有一个模糊参数m,默认为2。
private static final double MINIMAL_VALUE = 0.0000000001;
private double m = 2.0; // 模糊参数
函数computePi其实就是调用computeProbWeight来计算样本点属于某个簇的概率。

public Vector computePi(Collection<SoftCluster> clusters,List<Double> clusterDistanceList) {//新建一个向量,其长度为聚类集合的大小Vector pi = new DenseVector(clusters.size());for (int i = 0; i < clusters.size(); i++) {double probWeight = computeProbWeight(clusterDistanceList.get(i),clusterDistanceList);pi.set(i, probWeight);}return pi;}/** Computes the probability of a point belonging to a cluster */public double computeProbWeight(double clusterDistance,Iterable<Double> clusterDistanceList) {//当聚类距离为0时,返回MINIMAL_VALUEif (clusterDistance == 0) {clusterDistance = MINIMAL_VALUE;}double denom = 0.0;for (double eachCDist : clusterDistanceList) {if (eachCDist == 0.0) {eachCDist = MINIMAL_VALUE;}denom += Math.pow(clusterDistance / eachCDist, 2.0 / (m - 1));}return 1.0 / denom;}


五、KMeansClusteringPolicy

KMeansClusteringPolicy中定义了一个属性convergenceDelta,表示聚类的偏差。
在其的close方法中,只是简单的调用ClusterClassifier里面的模型进行参数的重新计算。


六、MeanShiftClusteringPolicy

MeanShiftClusteringPolicy类继承AbstractClusteringPolicy,主要是提供了序列化和反序列化t1,t2,t3和t4的方法。


关于DirichletClusteringPolicy,我们后面再讲,结合算法讲.



原创粉丝点击