mahout中kmeans算法和Canopy算法实现原理
本文讲一下mahout中kmeans算法和Canopy算法实现原理。
一. Kmeans是一个很经典的聚类算法,我想大家都非常熟悉。虽然算法较为简单,在实际应用中却可以有不错的效果;其算法原理也决定了其比较容易实现并行化。
学习mahout就先从简单的kmeans算法开始学起,就当抛砖引玉了。
1. 首先来简单的回顾一下KMeans算法:
(1) 根据事先给定的k值建立初始划分,得到k个Cluster,比如,可以随机选择k个点作为k个Cluster的重心,又或者用其他算法得到的Cluster作为初始重心;
(2)、计算每个点到各个Cluster重心的距离,将它加入到最近的那个Cluster;
(3)、重新计算每个Cluster的重心;
(4)、重复过程2~3,直到各个Cluster重心在某个精度范围内不变化或者达到最大迭代次数;
其时间复杂度是:O(nkt),其中:n是聚类点个数,k是Cluster个数,t是迭代次数。容易并行化,
kmeans缺点是:对孤立点敏感,K值难以估计
2. kmeans的算法思想决定了其实现并行化还是比较容易的,主要是在迭代中计算某个点属于哪一个新的聚类中心的过程是可以并行化的。
主要分成以下几个步骤:
(1)datanode在map阶段读出位于本地的数据集,并且从HDFS中读到上一次聚类后的聚类中心(从cluster-N-1的目录中),计算并输出每个点及其对应的Cluster;
(2)combiner操作对位于本地包含在相同Cluster中的点进行reduce操作并输出,
(3)reduce操作得到全局Cluster集合并写入HDFS的指定目录(cluster-N)。
Kmeans每一轮迭代会生成新的全局聚类中心,这个聚类中心在下一次迭代的时候是会使用到的,所以每一轮迭代(实际上每一轮迭代是一个新mapreduce job)之后,reduce任务会负责将此次的聚类中心输出到集群中。命名是以cluster加上迭代次数命名的。为:Cluster-N
由于每次迭代是起了一个job,mahout中有一个KMeansDriver的类来对整个过程进行控制。抽象过程。最后,当获得了稳定的全局聚类中心后,简单的想想就能知道,只要用一个Map过程就可以实现对全体数据的分类。具体流程如下图:
二. 在开始的时候说过,Kmeans算法收初始点的影响较大,如果起始点是一个孤立点是一个很麻烦的事情。解决的办法是先对数据集进行一个较为“粗”的聚类算法。目的是对全体数据集进行一个大致的分组过程,然后这些组为单位选取Kmeans的初始聚类中心点,这样初始点的选择就不至于因为随即而偏离的太远。Mahout里面是使用Canopy算法来实现这一初始聚类过程的,当然mahout中也会提供随机选取初始中心点的方法,用的是RandomSeedGenerator类。(运行mahout kMeans时会默认选择Canopy算法作为聚类中心选择的初始算法,但当你提供-k参数,即指明有几个聚类中心时,则会选择随机的方式生成初始中心点)
1. Canopy算法其实本身也可以用于聚类,但它的结果可以为之后代价较高聚类提供帮助,其用在数据预处理上要比单纯拿来聚类更有帮助;
Canopy算法的步骤如下:
(1) 将所有数据放进list中,选择两个距离,T1,T2,T1>T2
(2)While(list不为空)
{
随机选择一个节点做canopy的中心;并从list删除该点;
遍历list:
对于任何一条记录,计算其到各个canopy的距离;
如果距离<T2,则给此数据打上强标记,并从list删除这条记录;
如果距离<T1,则给此数据打上弱标记;
如果到任何canopy中心的聚类都>T1,那么将这条记录作为一个新的canopy的中心,并从list中删除这个元素;
}
同样,Canopy算法的实现也比较简单,其使用T1和T2两个距离来实现对数据集的一个粗略的划分,表现为最终会生成几个Canopy下面举一个例子。
8.1,8.1
7.1,7.1
6.2,6.2
7.1,7.1
2.1,2.1
1.1,1.1
0.1,0.1
3.0,3.0
一共有8个二维的点,为了计算简便,我们选择曼哈顿距离作为距离的量度,即|x1 – x2| + |y1 – y2|。选取T1=8,T2=4。mahout里面是可以为Kmeans算法设置不同的距离计算方法的,如欧式距离,向量夹角,曼哈顿距离,雅克比系数等。
首先选取(8.1, 8.1)作为第一个Canopy的中心,并从list中删除这个点。
然后开始遍历整个list。
第二个点(7.1,7.1)
距离Canopy 1 (8.1,8.1)的距离是2,2<T2,所以第二个点属于Canopy 1,将其加入Canopy 1,并从list中删除该点;
第三个点(6.2,6.2)
距离Canopy 1 (8.1,8.1)的距离是3.8,3.8<T2,所以第三个点也是属于Canopy 1。同样将其加入Canopy 1,并从list删除该点;
第四个点(7.1,7.1)与第一个点是相同的。
第五个点(2.1,2.1)
其余Canopy 1的距离是12,大于T1,所以第五个点不属于任何Canopy,新生成一个Canopy,其中心是(2.1,2.1),并从list中删除该点,因为这个点不会属于其他Canopy了。
第六个点(1.1,1.1)
到Canopy 1 (8.1,8.1)的距离是14,14> T1,到Canopy 2(2.1,2.1)的距离是2,2<T2,所以第六个点属于Canopy 2(2.1,2.1),并从list中删除这个点。
第七个点(0.1,0.1 )
到Canopy 1 (8.1,8.1)的距离是16,16> T1,到Canopy 2(2.1,2.1)的距离是4,4=T2,所以将第七个点打上属于Canopy 2(2.1,2.1)的弱标记,但并不从集群中删除该点;
第八个点(3.0,3.0)
到Canopy 1 (8.1,8.1)的距离是10.2,10.2> T1,到Canopy 2(2.1,2.1)的距离是1.8,1.8<T2,所以将第八个点加入到Canopy 2(2.1,2.1)中。
此时所有Canopy的状态是:
Canopy 1 (8.1,8.1) :[ (8.1,8.1), (7.1,7.1), (6.2,6.2) ,(7.1,7.1) ]
Canopy 2 (2.1,2.1) :[ (2.1,2.1), (1.1,1.1) ,(0.1,0.1), (3.0,3.0) ]
并且算法的第一词While循环已经跑过,此时list中还剩下的元素是(0.1,0.1)
将他自己作为一个新的Canopy,Canopy 3(0.1,0.1),集群中Canopy的最后状态是
Canopy 1 (8.1,8.1) :[ (8.1,8.1), (7.1,7.1), (6.2,6.2) ,(7.1,7.1) ]
Canopy 2 (2.1,2.1) :[ (2.1,2.1), (1.1,1.1) ,(0.1,0.1), (3.0,3.0) ]
Canopy 3 (0.1,0.1) :[ (0.1,0.1)]
所以最终的Canopy聚类中心是(7.125,7.125),(1.575,1.575),(0.1,0.1)
2. Canopy算法的并行化:
Canopy算法的并行点也是比较明显的,即生成Canopy的过程可以并行,
(1) 各个mapper可以依据存储在本地的数据,各自在本地用上述算法生成若干Canopy;(2) reducer将这些Canopy用相同算法汇总后计算出最终的Canopy集合;
下图可以较好的反应并行化的过程:
举个例子,我们只有两个map任务:
第一个map的数据是
8.1,8.1
7.1,7.1
6.2,6.2
7.1,7.1
2.1,2.1
1.1,1.1
0.1,0.1
3.0,3.0
根据上文的计算,我们得到其Canopy中心是(7.125,7.125),(1.575,1.575),(0.1,0.1)
那么第一个map的数据就是(7.125,7.125),(1.575,1.575),(0.1,0.1)
第二个map的数据是
8,8
7,7
6.1,6.1
9,9
2,2
1,1
0,0
2.9,2.9
运用Canopy算法我们可以到,其Canopy中心是(7.525,7.525),(1.475,1.475),(1.45,1.45)
第二个map的输出数据就是(7.525,7.525),(1.475,1.475),(1.45,1.45)
那么Reduce中获得数据就是(7.125,7.125),(1.575,1.575),(0.1,0.1),(7.525,7.525),(1.475,1.475),(1.45,1.45)
Reduce任务会用Canopy算法对这个六个点进行Canopy划分。从而得到全局的Canopy中心。
mahout中kmeans算法和Canopy算法实现原理的更多相关文章
- 强化学习中REIINFORCE算法和AC算法在算法理论和实际代码设计中的区别
背景就不介绍了,REINFORCE算法和AC算法是强化学习中基于策略这类的基础算法,这两个算法的算法描述(伪代码)参见Sutton的reinforcement introduction(2nd). A ...
- mahout中KMeans算法
本博文主要内容有 1.kmeans算法简介 2.kmeans执行过程 3.关于查看mahout中聚类结果的一些注意事项 4.kmeans算法图解 5.mahout的kmeans算法实现 ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- 使用Apriori算法和FP-growth算法进行关联分析
系列文章:<机器学习实战>学习笔记 最近看了<机器学习实战>中的第11章(使用Apriori算法进行关联分析)和第12章(使用FP-growth算法来高效发现频繁项集).正如章 ...
- 转载:最小生成树-Prim算法和Kruskal算法
本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...
- 0-1背包的动态规划算法,部分背包的贪心算法和DP算法------算法导论
一.问题描述 0-1背包问题,部分背包问题.分别实现0-1背包的DP算法,部分背包的贪心算法和DP算法. 二.算法原理 (1)0-1背包的DP算法 0-1背包问题:有n件物品和一个容量为W的背包.第i ...
- 用Spark学习FP Tree算法和PrefixSpan算法
在FP Tree算法原理总结和PrefixSpan算法原理总结中,我们对FP Tree和PrefixSpan这两种关联算法的原理做了总结,这里就从实践的角度介绍如何使用这两个算法.由于scikit-l ...
- 字符串查找算法总结(暴力匹配、KMP 算法、Boyer-Moore 算法和 Sunday 算法)
字符串匹配是字符串的一种基本操作:给定一个长度为 M 的文本和一个长度为 N 的模式串,在文本中找到一个和该模式相符的子字符串,并返回该字字符串在文本中的位置. KMP 算法,全称是 Knuth-Mo ...
- 最小生成树之Prim算法和Kruskal算法
最小生成树算法 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决. Prim算法 ...
随机推荐
- iOS应用架构谈 本地持久化方案及动态部署
转载: iOS应用架构谈 本地持久化方案及动态部署 前言 嗯,你们要的大招.跟着这篇文章一起也发布了CTPersistance和CTJSBridge这两个库,希望大家在实际使用的时候如果遇到问题,就给 ...
- 20145218 《Java程序设计》第9周学习总结
20145218 <Java程序设计>第9周学习总结 教材学习内容总结 16.1.1 JDBC简介 JDBC全名Java DataBase Connectivity,是java联机数据库的 ...
- hdu 1021
刚开始直接按题意来写,WA了,唉,果然经验不够..然后开始找规律,本来一看到这种题,第一反应就是规律题,然后看看题意,貌似没啥规律哦!就像当时学DP一样,总是想当然被智商压制了啊喂! #include ...
- bug:C#线程间操作无效: 从不是创建控件" XX" 的线程访问它
今天遇到这个问题,百度了下,把解决的方法总结出来.我们在ui线程创建的子线程操作ui控件时,系统提示错误详细信息为:线程间操作无效: 从不是创建控件“XXX”的线程访问它. 就我知道的有三种方法,先看 ...
- ARM中的总线
ARM中的总线用于不同部件之间的通信.有两种不同类型的设备连接到总线:ARM处理器,它是总线的主设备,拥有对总线的仲裁权,可以通过同一总线主动发起数据传输请求:外围器件,是总线的从设备,在总线上是被动 ...
- 张艾迪Eidyzhang:解码天才Eidyzhang的诞生
AOA解码:天才Eidyzhang的诞生AOA深度解读:世界第一天才Eidyzhang: (TheWorldNo.1Girl+TheWorldNo.1InterentGirl+世界第一女孩+世界第一互 ...
- ASP.NET服务器控件数据绑定总结
using System; using System.Collections.Generic; using System.Text; using System.Web.UI.WebControls;/ ...
- 选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中
选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中 T-SQL核心语句形式: SELECT --指定要选择的列或行及其限定 [INTO ] --INTO子句 ...
- 循环语句while与for的穷举迭代
循环语句while while当...的时候 int n=1; while(n<6)//在括号内直接限制逻辑关系 {//需要在大括号内给出改变方式,否则将进入死循环 console.WriteL ...
- javascript 判断身份证的正确性
function isIdCardNo(vals) { var cardNum = vals; if (cardNum.length == 0) { return true; } // 11-15,2 ...