zoukankan      html  css  js  c++  java
  • mahout中KMeans算法

    本博文主要内容有

        1、kmeans算法简介

      2、kmeans执行过程

        3关于查看mahout中聚类结果的一些注意事项

      4、kmeans算法图解

         5、mahout的kmeans算法实现原理

         6、kmeans算法运行时参数介绍

       7、使用mahout自带的fpg算法来对我们的测数据retail.dat进行kmeans算法(但是0.9及其以后版本照样可以用,但是格式要注意)

       8、使用开始使用mahout自带的kmeans算法来对我们的测数据retail.dat进行kmeans算法!

    K-means算法

     

     Kmeans的介绍

       (1)Kmeans算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一。

         (2)Kmeans算法的基本思想是:以空间中k个点为中心聚类,对最靠近它们的对象归类。

         (3)通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。

       关于kmeans迭代的体验,可以见博客。

       mahout-distribution-0.9.tar.gz的安装的与配置、启动与运行自带的mahout算法

     Kmeans的执行过程

      1、假设要把样本集分为c个类别,算法描述如下:

        (1)适当选择c个类的初始中心;

        (2)在第k次迭代中,对任意一个样本,求其到c各中心的距离,将该样本归到距离最短的中心所在的类;

        (3)利用均值等方法更新该类的中心值;

        (4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。

       2、该算法的最大优势在于简介和快速。算法的关键在于初始中心的选择和距离公式。

    关于查看mahout中聚类结果的一些注意事项

       mahout seqdumper : 将SequenceFile文件转换成可读的文本形式,对应的源文件是org.apache.mahout.utils.SequenceFileDumper.java

       mahout vectordump : 将向量文件转成可读的文本形式,对应的源文件是org.apache.mahout.utils.vectors.VectorDumper.java

       mahout clusterdump : 分析最后聚类的输出结果,对应的源文件是org.apache.mahout.utils.clustering.ClusterDumper.java

        mahout-distribution-0.9.tar.gz的安装的与配置、启动与运行自带的mahout算法

      比如

    [hadoop@djt002 ~]$ $MAHOUT_HOME/bin/mahout seqdumper -i /user/hadoop/output/data/part-m-00000 -o ~/res.txt

            这里,我仅仅是用自带的来测试下。大家根据自己的实际去做。

      注意:

    /user/hadoop/output

      这个输出目录,是mahout自带的kmeans算法里已经写死了的,所以每次,必须清空。

      然后

    sz  res.txt
    
    
    或者
    
    
    cat res.txt

    例如:

      现有一份杂乱的样本数据,我们希望数据最后按照某些类别来划分(红豆分为红豆,绿豆分为绿豆等意思)。

      聚类算法会从n个类的初始中心开始(如果没有人为设置,其会按照随机的初始中心开始)

      什么意思呢?来看一张图。下面是kmeans算法图解

       第一张图(左1图)是,我没有指定中心点,让它自己去选,去聚类。

     

       第二张图(中1图),是我们定义的一个k。

     

     

      上图中,左一的圆圈图表示原始数据在随机的初始中心划分后的的分布,但是可以看出很明显cluster1中有很多是靠近cluster2的数据点

    所以kmeans会根据规则再次计算出更加合适的中心点来进行划分。

      这个规则就是:计算每个数据点,到原始中心cluster1和cluster2的距离,离谁比较近就划分到谁那边去(形如中间的圆圈图)。然后将cluster1和cluster2中的数据分别求平均值,得到的两个平均值成为新的cluster1和cluster2中心点。

      但是很明显这样划分还是不够合理,所以kmeans会继续迭代计算每个数据到新的中心点的距离,离谁比较近就划分给谁,然后在分别求平均值得到新的中心点

    直到cluster1和cluster2中的数据平均值不在发生变化时认为此时是最理想的划分方式(也可以进行人工的干预)。

    kmeans图解

          

       下面展示了对n个样本点进行kmeans聚类的效果,这里K取2。

       (a) 准备数据,比如样本数据如图所示。即未聚类的初始点集

       (b) 假设确定两个值,cluster1 和 cluster2。为什么是两个簇,是我们自己定义的。随机选取两个点作为聚类中心

      

        (c) mahout中kmeans会去找每个点, 比较距离1和距离2哪个近,依次迭代下去。计算每个点到聚类中心的聚类,并聚类到离该点最近的聚类中去

        

       (d)然后呢,把那些红点全部一起取个平均值,把那些蓝点也全部一起取个平均值。 计算每个聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心。

      (e) 同时,再根据这平均值后得到的这两个点,分别再算距离。依次迭代,。重复(c),计算每个点到聚类中心的聚类,并聚类到离该点最近的聚类中去

     

      (e) 进一步精确啦!

         (f)重复(d),计算每个聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心

     

       当然,我们若还要进一步更加精确的话,循环(a)(b)(c)(d)(e)这几步。

     Mahout kmeans的实现(其实就是源码过程)

      (1)参数input指定待聚类的所有数据点,clusters指定初始聚类中心

         如果指定参数k,由org.apache.mahout.clustering.kmeans.RandomSeedGenerator.buildRandom通过org.apache.hadoop.fs直接从input指定文件中随机读取k个点放入cluster中。

       (2)根据原数据点和上次迭代(或初始聚类)的聚类中心计算本次迭代的聚类中心,输出到cluster-N目录下。该过程由org.apache.mahout.clustering.kmeans下的KMeansMapperKMeansCombinerKMeansReducerKMeansDriver实现

        KMeansMapper:在configure中初始化mapper时读入上一次跌打产生或初始聚类中心(每个mapper都读入所有的聚类中心);

         map方法对输入的每个点,计算距离其最近的类,并加入其中输出key为该点所属聚类ID,value为KMeansInfo实例,包含点的个数和各分量的累加和。

        KMeansCombiner: 本地累积KMeansMapper输出的同一聚类ID下的点个数和各分量的和

        KMeansReducer : 累加同一聚类ID下的点个数和各分量的和,求本地迭代的聚类中心;并根据输入Delta判断该聚类是否收敛;上一次迭代聚类中心与本次迭代聚类中心距离  <  Delta;输出各聚类中心和其是否收敛标记。

              KMeansDriver : 控制迭代过程直至超过最大迭代次数或所有聚类都已收敛,每轮迭代后,KMeansDriver读取其clusters-N目录下的所有聚类,若所有聚类已经收敛,则整个kmeans聚类过程收敛了。

       参数调整:

        manhout kmeans聚类有两个重要参数: 收敛Delta 和 最大迭代次数。

     参数介绍

    bin/mahout  kmeans  
    -i <input vectors directory>
    -c <input clusters directory>
    -o <output working directory>
    -k <optional number of initial clusters to sample from input vectors>
    -dm <DistanceMeasure>
    -x <maximum number of iterations>
    -cd <optional output directory if present>
    -ow <overwrite output directory if present>
    -cl <run input vector clustering after computing Canopies>
    -xm <execution method : sequential or mapreduce>

       注意: 当-k被指定的时候, -c目录下的所有聚类都被重写,将从输入的数据向量中随机抽取-k个点作为初始聚类的中心。

     kmeans流程图

              

     案例零售retail.dat

    http://fimi.ua.ac.be/data/

      通过官网下载得到数据,或者拿最下面的数据也可以。

    测试数据下载tail.txt(电商购物车数据)

           点击打开链接

    [hadoop@djt002 mahoutData]$ pwd
    /usr/local/mahout/mahoutData
    [hadoop@djt002 mahoutData]$ ll
    total 284
    -rw-r--r-- 1 hadoop hadoop 288972 Apr 27 22:48 data.txt
    [hadoop@djt002 mahoutData]$ rz
    
    [hadoop@djt002 mahoutData]$ ll
    total 1428
    -rw-r--r-- 1 hadoop hadoop  288972 Apr 27 22:48 data.txt
    -rw-r--r-- 1 hadoop hadoop 1170296 Apr 28 10:18 tail.txt
    [hadoop@djt002 mahoutData]$ 

       将这个数据tail.txt上传到hdfs://djt002://9000/user/hadoop/testdata/下(通过以下命令)

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -put /usr/local/mahout/mahoutData/tail.txt  hdfs://djt002:9000/user/hadoop/testdata/

    或者


    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -copyFromLocal /usr/local/mahout/mahoutData/tail.txt  hdfs://djt002:9000/user/hadoop/testdata/

     

     

    [hadoop@djt002 mahoutData]$ pwd
    /usr/local/mahout/mahoutData
    [hadoop@djt002 mahoutData]$ ll
    total 1428
    -rw-r--r-- 1 hadoop hadoop  288972 Apr 27 22:48 data.txt
    -rw-r--r-- 1 hadoop hadoop 1170296 Apr 28 10:18 tail.txt
    [hadoop@djt002 mahoutData]$ rz
    
    [hadoop@djt002 mahoutData]$ ll
    total 5500
    -rw-r--r-- 1 hadoop hadoop  288972 Apr 27 22:48 data.txt
    -rw-r--r-- 1 hadoop hadoop 4167490 Apr 28 11:56 retail.dat
    -rw-r--r-- 1 hadoop hadoop 1170296 Apr 28 10:18 tail.txt

     

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -mkdir hdfs://djt002:9000/user/hadoop/mahoutData
    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -put /usr/local/mahout/mahoutData/retail.dat  hdfs://djt002:9000/user/hadoop/mahoutData/
    [hadoop@djt002 mahoutData]$ 

       

     注意,是不需输入路径和输出路径的啊!(自带的jar包里都已经写死了的)

      (注意:如果你是选择用mahout压缩包里自带的kmeans算法的话,则它的输入路径是testdata是固定死的,

            即hdfs:djt002://9000/user/hadoop/testdata/  )

      并且每次运行hadoop都要删掉原来的output目录!

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -rm hdfs://djt002:9000/user/hadoop/testdata/data.txt
    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -rm hdfs://djt002:9000/user/hadoop/testdata/tail.txt

         通过以下命令去清空输入目录(没办吧,因为mahout自带的kmeans算法已经写死了)(为了保证输入数据每次只有一个,不混淆)

       通过以下命令去清空输出目录(没办吧,因为mahout自带的kmeans算法已经写死了)

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop fs -rm -r hdfs://djt002:9000/user/hadoop/output/*

     

       使用mahout自带的fpg算法来对我们的测数据retail.dat进行kmeans算法(但是0.9及其以后版本照样可以用,但是格式要注意)

       这里选择mahout中的自带的FpGrowth算法

    $MAHOUT_HOME/bin/mahout fpg -i  /user/hadoop/mahoutData/retail.dat  -0  /user/hadoop/output  -method  mapreduce  -s  1000  -regex  '[]'

    各个参数的意义:

      -i:指定输入数据的路径

      -o:指定输出结果的路径

      -method:指定使用mapreduce方法

      -s:最小支持度

      -regex:使用指定的正则来匹配过滤数据

      我这里是,用的是自定义的是输入路径和输出路径。

          当然你也可以,用默认的输入路径是/user/hadoop/testdata    ,   默认的输出路径是/user/hadoop/output

    $MAHOUT_HOME/bin/mahout fpg -i  /user/hadoop/testdata/retail.dat  -0  /user/hadoop/output  -method  mapreduce  -s  1000  -regex  '[]'

    [hadoop@djt002 mahoutData]$ $MAHOUT_HOME/bin/mahout fpg -i  /user/hadoop/mahoutData/retail.dat  -0  /user/hadoop/output  -method  mapreduce  -s  1000  -regex  '[]'
    Running on hadoop, using /usr/local/hadoop/hadoop-2.6.0/bin/hadoop and HADOOP_CONF_DIR=
    MAHOUT-JOB: /usr/local/mahout/mahout-distribution-0.9/mahout-examples-0.9-job.jar
    17/04/28 20:09:16 WARN driver.MahoutDriver: Unable to add class: fpg
    java.lang.ClassNotFoundException: fpg
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:191)
        at org.apache.mahout.driver.MahoutDriver.addClass(MahoutDriver.java:237)
        at org.apache.mahout.driver.MahoutDriver.main(MahoutDriver.java:128)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
        at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
    17/04/28 20:09:16 WARN driver.MahoutDriver: No fpg.props found on classpath, will use command-line arguments only
    Unknown program 'fpg' chosen.

       对于mahout0.9及其以后版本,不能直接这么来干。

      org.apache.mahout.fpm.pfpgrowth.FPGrowthDriver 等价于 fpg

        得换成如下

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop  jar  /usr/local/mahout/mahout-distribution-0.9/mahout-examples-0.9-job.jar org.apache.mahout.fpm.pfpgrowth.FPGrowthDriver -i  /user/hadoop/testdata/retail.dat  -o  /user/hadoop/output  -method  mapreduce  -s  1000  -regex  '[]'

      或者(自定义输入路径和输出路径)

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop  jar  /usr/local/mahout/mahout-distribution-0.9/mahout-examples-0.9-job.jar org.apache.mahout.fpm.pfpgrowth.FPGrowthDriver -i  /user/hadoop/mahoutData/retail.dat  -o  /user/hadoop/output  -method  mapreduce  -s  1000  -regex  '[]'
    [hadoop@djt002 ~]$ $HADOOP_HOME/bin/hadoop  jar  /usr/local/mahout/mahout-distribution-0.9/mahout-examples-0.9-job.jar org.apache.mahout.fpm.pfpgrowth.FPGrowthDriver -i  /user/hadoop/testdata/retail.dat  -o  /user/hadoop/output  --method mapreduce --s 200 --regex '[]' -k 20 

       现在开始使用mahout自带的kmeans算法来对我们的测数据retail.dat进行kmeans算法!

      这里是用默认的输入路径/user/hadoop/testdata 和 默认的输出路径 /user/hadoop/output

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop  jar  /usr/local/mahout/mahout-distribution-0.9/mahout-examples-0.9-job.jar   org.apache.mahout.clustering.syntheticcontrol.kmeans.Job

      或者,你可以用自定义的输入路径和输出路径

    [hadoop@djt002 mahoutData]$ $HADOOP_HOME/bin/hadoop  jar  /usr/local/mahout/mahout-distribution-0.9/mahout-examples-0.9-job.jar   org.apache.mahout.clustering.syntheticcontrol.kmeans.Job  -i  /user/hadoop/mahoutData/retail.txt   -o  /user/hadoop/output

       

      如果你在这一步,遇到这个问题,则见

    Error: org.apache.mahout.math.CardinalityException: Required cardinality 10 but got 30问题解决办法

      同样的,运行结果的数据要通过seqdumper来查看

    $MAHOUT_HOME/bin/mahout seqdumper -i /user/hadoop/output/data/part-m-00000 -o ~/retail_kmeans.txt

     或者

    $MAHOUT_HOME/bin/mahout seqdumper -i /user/hadoop/output/cluster-1/ -o ~/retail_kmeans.txt

       这些都是自己弄的。

    cat
    ~/retail_kmeans.txt

     

     

     http://www.cnblogs.com/fengfenggirl/p/associate_mahout.html

    http://book.51cto.com/art/201406/442565.htm

  • 相关阅读:
    cubestore driver 添加auth认证
    cubestore 添加auth 认证
    基于s3 扩展cubestore
    cube.js 预聚合检查
    cube.js 集成cubestore 时间格式问题的一些说明
    cube.js 集成cubestore 时间格式问题
    Building a GraphQL to SQL Compiler on Postgres, MS SQL and MySQL
    支持minio cubestore docker 镜像
    数据治理怎么做
    使用project制定项目计划可以分为六个步骤
  • 原文地址:https://www.cnblogs.com/zlslch/p/6673969.html
Copyright © 2011-2022 走看看