zoukankan      html  css  js  c++  java
  • FuzzyKmeans,mahout实现

    首先介绍一下,FuzzyKMeans算法的主要思想。

    模糊 C 均值聚类(FCM),即众所周知的模糊 ISODATA,是用隶属度确定每个数据点属于某个聚类的程度的一种聚类算法。1973 年,Bezdek 提出了该算法,作为早期硬 C 均值聚类(HCM)方法的一种改进。FCM 把 n 个向量 xi(i=1,2,...,n)分为 c 个模糊组,并求每组的聚类中心,使得非相似性指标的价值函数达到最小。FCM 使得每个给定数据点用值在 0,1 间的隶属度来确定其属于各个组的程度。与引入模糊划分相适应,隶属矩阵 U 允许有取值在 0,1 间的元素。不过,加上归一化规定,一个数据集的隶属度的和总等于 1:

    那么,FCM 的价值函数(或目标函数)就是下式一般化形式:

    这里 uij 介于 0,1 间;ci 为模糊组 i 的聚类中心,dij=||ci-xj||为第 i 个聚类中心与第 j 个数据点间的欧几里德距离;且 m (属于1到无穷) 是一个加权指数。
    构造如下新的目标函数,可求得使下式达到最小值的必要条件:其实就是拉格朗日乘子法

    对上式所有输入参量求导,使上式达到最小的必要条件为:

    由上述两个必要条件,模糊 C 均值聚类算法是一个简单的迭代过程。在批处理方式运行时,
    FCM 用下列步骤确定聚类中心 ci 和隶属矩阵 U[1]:
    步骤 1:用值在 0,1 间的随机数初始化隶属矩阵 U
    步骤 2:用式(3)计算 c 个聚类中心 ci,i=1,...,c。
    步骤 3:根据式(1)计算价值函数。如果它小于某个确定的阀值,或它相对上次价
    值函数值的改变量小于某个阀值,则算法停止。
    步骤 4:用(4)计算新的 U 矩阵和。返回步骤 2。
    上述算法也可以先初始化聚类中心,然后再执行迭代过程。由于不能确保 FCM 收敛于一个最优解。算法的性能依赖于初始聚类中心。因此,我们要么用另外的快速算法确定初始
    聚类中心,要么每次用不同的初始聚类中心启动该算法,多次运行 FCM。

    notes: 上面讨论不难看出二个参数比较重要:1.聚类的数目,2.控制算法的柔软参数m,如果m过大,则聚类的效果很差,如果m过小,则算法接近Kmeans算法。

     

    mahout实现:

    在mahout中,控制参数m=2;定义如下:private double m = 2.0; // default value

    其整个代码如下:

     1 public class FuzzyKMeans{
     2     
     3     public static void main(String args[]) throws Exception {
     4         int k = 3;
     5         List<Vector> sampleData = new ArrayList<Vector>();
     6         RandomPointsUtil.generateSamples(sampleData, 400, 1, 1, 3);
     7         RandomPointsUtil.generateSamples(sampleData, 300, 1, 0, 0.5);
     8         RandomPointsUtil.generateSamples(sampleData, 300, 0, 2, 0.1);
     9         List<Vector> randomPoints = RandomPointsUtil.chooseRandomPoints(
    10                 sampleData, k);
    11         List<SoftCluster> clusters = new ArrayList<SoftCluster>();
    12         int clusterId = 0;
    13         for (Vector v : randomPoints) {
    14             clusters.add(new SoftCluster(v, clusterId++,
    15                     new EuclideanDistanceMeasure()));
    16         }
    17         List<List<SoftCluster>> finalClusters = FuzzyKMeansClusterer
    18                 .clusterPoints(sampleData, clusters,
    19                         new EuclideanDistanceMeasure(), 0.01, 3, 10);
    20         for (SoftCluster cluster : finalClusters.get(finalClusters.size() - 1)) {
    21             System.out.println("Fuzzy Cluster id: " + cluster.getId()
    22                     + " center: " + cluster.getCenter().asFormatString());
    23         }
    24     }
    25 }

     对上面几行代码进行说明:

    类RandomPointsUtil中静态方法generateSamples是产生随机样本,并存在sampleData中。
    类RandomPointsUtil中静态方法chooseRandomPoints是随机选择k个样本作为初始点。
    其类RandomPointsUtil代码如下:
     1 public class RandomPointsUtil {
     2     public static List<Vector> chooseRandomPoints(List<Vector> srcVector, int k) {
     3         List<Vector> destVector = new ArrayList<Vector>();
     4         for (int i = 0; i < k; i++) {
     5             int index = (int) (Math.random() * srcVector.size());
     6             destVector.add(srcVector.get(index));
     7         }
     8         return destVector;
     9     }
    10 
    11     private  static void generateSamples(List<Vector> sampleData, int num, double mx,
    12             double my, double sd, int card) {
    13         for (int i = 0; i < num; i++) {
    14             DenseVector v = new DenseVector(card);
    15             for (int j = 0; j < card; j++) {
    16                 v.set(j, UncommonDistributions.rNorm(mx, sd));
    17             }
    18             sampleData.add(v);
    19         }
    20     }
    21 
    22     /**
    23      * Generate 2-d samples for backwards compatibility with existing tests25      * @param numint number of samples to generate
    27      * @param mx double x-value of the sample mean
    29      * @param mydouble y-value of the sample mean
    31      * @param sddouble standard deviation of the samples
    33      */
    34     public static void generateSamples(List<Vector> sampleData, int num, double mx,
    35             double my, double sd) {
    36         
    37         generateSamples(sampleData, num, mx, my, sd, 2);
    38     }
    39 }
    所以mahout算法实现fuzzyKmeans最核心的函数为FuzzyKMeansClusterer.clusterPoints, 下面对方法FuzzyKMeansClusterer.clusterPoints进行分析。

    以上是我个人的理解,如有错误,请留言告诉我,本人感激不尽。作者:BIGBIGBOAT/Liqizhou

  • 相关阅读:
    JAVA 8 主要新特性 ----------------(一)总纲
    STARTTLS is required but host does not support STARTTLS
    Request processing failed; nested exception is java.lang.IllegalStateException: getOutputStream() has already been called for this response
    MyBatis-Plus 多库部署方式;spring mvc 多库部署方式
    Mac could not read from remote repository
    IntelliJ IDEA 2017版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA sort排序方法使用方式, 添加关联表的 order by
    CentOS7 安装可视化脚本安装包Webmin
    VSCode 设置侧边栏字体大小;Visual Studio Code改变侧边栏大小
    java 开发中经常问到得懒汉模式 (单利模式)
    java 中多线程的同步函数的运用
  • 原文地址:https://www.cnblogs.com/liqizhou/p/2473174.html
Copyright © 2011-2022 走看看