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

原文地址:https://www.cnblogs.com/zlslch/p/6673969.html