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

  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/liqizhou/p/2473174.html
Copyright © 2011-2022 走看看