并行FP-Growth算法思路

上图的单线程形成的FP-Tree。

分布式算法事实上是对FP-Tree进行分割,分而治之

首先,假设我们只关心...|c这个conditional transaction,那么可以把每个transaction中的...|c保留,并发送到一个计算节点中,必然能在该计算节点构造出FG-Tree

root
| \
f:3 c:1
|
c:3

进而得到频繁集(f,c)->3.

同样,如果把所有transaction中的...|b保留,并发送到一个计算节点中,必然能在该几点构造出FG-tree

  root
/ \
f:2 c:1
| \ \
c:1 b:1 b:1
|
a:1
|
b:1

进而得到(b)->3。

以上两个例子得到了两个tree,并且分别得到了部分结果。

事实上算法的思路就是把transaction的conditional transaction进行分割(分组),分割的依据就是conditional transaction的suffix(的hash,如果直接是suffix也可以,但是使得spark任务有过多task)。对每个分组分别构建FP-tree,然后在每个子树中获得部分结果,合并得到最终结果。

Spark Mllib中算法

遍历一次数据集输出F-List,类似wordcount,得出频繁出现的items,将F-List划分为G-List,即将频繁items进行分组:

  • F-List包含item全集I中的频繁item,F-List={f_1,...},f_i在Transaction中出现的频率>support阈值。
  • G-List={g_1,...}, g_i=hash_of(f_i)=H(f_i).



    实际上,计算的f_i hash值作为partition_id,在MLLib过程中将conditional transaction f'1,f'2,...|f_i 分发到partition_id=H(f_i)对应的计算节点。
// data即所有的transaction,每个trans是Item数组
def run[Item: ClassTag](data: RDD[Array[Item]]): FPGrowthModel[Item] = {
// 计算support阈值
val count = data.count()
val minCount = math.ceil(minSupport * count).toLong
val numParts = if (numPartitions > 0) numPartitions else data.partitions.length
val partitioner = new HashPartitioner(numParts)
// 第一次遍历,统计frequency,过滤掉低于support阈值的item
val freqItems:Array[Item] = genFreqItems(data, minCount, partitioner)
// 第二次遍历
val freqItemsets = genFreqItemsets(data, minCount, freqItems, partitioner)
new FPGrowthModel(freqItemsets)
}

各组构建FP-tree

再次遍历数据集,每个trans中的items按照frequency进行降序排列,并构造conditional transactions,例如一个trans={a,b,c,d,e},a的frequency最高,以此降低,构造其相应的conditional transactions:

a,b,c,d,e:
condition trans ; partition_id
a,b,c,d|e ; partition = H(e)
a,b,c|d ; partition = H(d)
a,b|c ; partition = H(c)
a|b ; partition = H(b)
a ; partition = H(a)

对应code在genFreqItemsets.

  • 每个transaction的conditional transaction,并且按照suffix计算hash作为partition_id分组
  • 各个partition_id对应的[condition items]所有集合,即G-List,对G-List的agg即为构造FP-Tree过程
  • 在各个part中提取该part包含的频繁集。在part子树中,node x,若hash(x)=part_id,并且x到root路径能形成频繁集,则输出path(x->root)中的各个节点作为频繁集。
  • 将rank转为对应的item
private def genFreqItemsets[Item: ClassTag](
data: RDD[Array[Item]], // transactions
minCount: Long, // support threshold
freqItems: Array[Item], // FP-List
partitioner: Partitioner): RDD[FreqItemset[Item]] = {
// freqItems已经排序了,zip出每个Item的rank
val itemToRank = freqItems.zipWithIndex.toMap
// 形成partition_id->[condition items]
data.flatMap { transaction =>
// 计算conditional transactions
genCondTransactions(transaction, itemToRank, partitioner)
}
// 各个partition_id对应的[condition items]所有集合,即G-List,
// 对G-List的agg即为构造FP-Tree过程
.aggregateByKey(new FPTree[Int], partitioner.numPartitions)(
(tree, transaction) => tree.add(transaction, 1L),
(tree1, tree2) => tree1.merge(tree2))
// 在各个part中提取该part包含的频繁集
.flatMap { case (part, tree) =>
tree.extract(minCount, x => partitioner.getPartition(x) == part)
}
// 将rank转为对应的item
.map { case (ranks, count) =>
new FreqItemset(ranks.map(i => freqItems(i)).toArray, count)
}
}

计算conditional transactions

  • itemToRank,rank越小对应的frequency是越大的
  • 每个trans中筛出frequent Item,并对rank排序,得到的item即按照frequency由大到小排序
    • FP_list={a,b,c,d,e,f}
    • 一个trans=[f,e,d,a,c], 那么将得到[0,2,3,4,5]
  • 构造conditional transaction
    • 例如0,2|3 计算3的partition_id(3), 形成partition_id(3)->[0,2,3]
private def genCondTransactions[Item: ClassTag](
transaction: Array[Item],
itemToRank: Map[Item, Int],
partitioner: Partitioner): mutable.Map[Int, Array[Int]] = {
val output = mutable.Map.empty[Int, Array[Int]]
// Filter the basket by frequent items pattern and sort their ranks.
val filtered = transaction.flatMap(itemToRank.get)
ju.Arrays.sort(filtered)
val n = filtered.length
var i = n - 1
while (i >= 0) {
val item = filtered(i)
val part = partitioner.getPartition(item)
if (!output.contains(part)) {
output(part) = filtered.slice(0, i + 1)
}
i -= 1
}
output
}

FP-Growth in Spark MLLib的更多相关文章

  1. 《Spark MLlib机器学习实践》内容简介、目录

      http://product.dangdang.com/23829918.html Spark作为新兴的.应用范围最为广泛的大数据处理开源框架引起了广泛的关注,它吸引了大量程序设计和开发人员进行相 ...

  2. Spark MLlib 机器学习

    本章导读 机器学习(machine learning, ML)是一门涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多领域的交叉学科.ML专注于研究计算机模拟或实现人类的学习行为,以获取新知识.新 ...

  3. Spark MLlib - LFW

    val path = "/usr/data/lfw-a/*" val rdd = sc.wholeTextFiles(path) val first = rdd.first pri ...

  4. Spark MLlib 之 Basic Statistics

    Spark MLlib提供了一些基本的统计学的算法,下面主要说明一下: 1.Summary statistics 对于RDD[Vector]类型,Spark MLlib提供了colStats的统计方法 ...

  5. Spark MLlib Data Type

    MLlib 支持存放在单机上的本地向量和矩阵,也支持通过多个RDD实现的分布式矩阵.因此MLlib的数据类型主要分为两大类:一个是本地单机向量:另一个是分布式矩阵.下面分别介绍一下这两大类都有哪些类型 ...

  6. Spark MLlib - Decision Tree源码分析

    http://spark.apache.org/docs/latest/mllib-decision-tree.html 以决策树作为开始,因为简单,而且也比较容易用到,当前的boosting或ran ...

  7. Spark入门实战系列--8.Spark MLlib(上)--机器学习及SparkMLlib简介

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .机器学习概念 1.1 机器学习的定义 在维基百科上对机器学习提出以下几种定义: l“机器学 ...

  8. Spark入门实战系列--8.Spark MLlib(下)--机器学习库SparkMLlib实战

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .MLlib实例 1.1 聚类实例 1.1.1 算法说明 聚类(Cluster analys ...

  9. spark mllib配置pom.xml错误 Multiple markers at this line Could not transfer artifact net.sf.opencsv:opencsv:jar:2.3 from/to central (https://repo.maven.apache.org/maven2): repo.maven.apache.org

    刚刚spark mllib,在maven repository网站http://mvnrepository.com/中查询mllib后得到相关库的最新dependence为: <dependen ...

  10. Apache Spark源码走读之23 -- Spark MLLib中拟牛顿法L-BFGS的源码实现

    欢迎转载,转载请注明出处,徽沪一郎. 概要 本文就拟牛顿法L-BFGS的由来做一个简要的回顾,然后就其在spark mllib中的实现进行源码走读. 拟牛顿法 数学原理 代码实现 L-BFGS算法中使 ...

随机推荐

  1. mysql for update语句

    我们都知道for update语句会锁住一张表,锁表的细节很多人却不太清楚,下面我们举例看下. 在表上我们有个索引,如下: 现在在我们通过索引store_id锁表: 我们再开一个客户端,还是锁住同一个 ...

  2. LuoguP1126 机器人搬重物(BFS)

    题目链接:https://www.luogu.org/problemnew/show/P1126 思路:很不错的搜索题,用BFS,虐了我1天多才A掉 QAQ,细节很多. 1.每个状态包含行.列.方向. ...

  3. Spring_AOP动态代理详解(转)

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  4. php5.3 延迟静态绑定 static关键字

    //传统模式 --这段代码能很好工作,但大量的重复代码很烦人,不想为每个DomainObject子类都创建这段相同代码吧? /* abstract class DomainObject{} class ...

  5. PAT 1078 字符串压缩与解压(20)(代码+思路)

    1078 字符串压缩与解压(20 分) 文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示.例如 ccccc 就用 5c 来表 ...

  6. PAT 1064 朋友数(20)(代码)

    1064 朋友数(20 分) 如果两个整数各位数字的和是一样的,则被称为是"朋友数",而那个公共的和就是它们的"朋友证号".例如 123 和 51 就是朋友数, ...

  7. 现代编译原理--第二章(语法分析之LR(1))

    (转载请表明出处  http://www.cnblogs.com/BlackWalnut/p/4472772.html) 前面已经介绍过LL(1),以及如何使用LL(1)文法.但是LL(K)文法要求在 ...

  8. 向一个文件流写入一个数据块---fwrite

    函数原型:int fwrite(const void *buffer,size_t size,size_t count,FILE *stream); 参数说明:buffer:用于写入到文件的数据地址. ...

  9. ubuntu系统中安装RoboMongo

    1.下载RoboMongo RoboMongo官网下载链接.选择好相应版本. 2.解压文件 tar -xzf robomongo--linux-x86_64-.tar.gzcd robomongo-0 ...

  10. Ckeditor上传图片返回的JS直接显示出来,未执行!!!

    Ckeditor上传图片网上有很多教程. 下面是我今天下午遇到的一个坑...自己挖的坑. 在conotroller里 我开始习惯性的 response.setContentType("app ...