用Spark学习FP Tree算法和PrefixSpan算法

 在FP Tree算法原理总结PrefixSpan算法原理总结中,我们对FP Tree和PrefixSpan这两种关联算法的原理做了总结,这里就从实践的角度介绍如何使用这两个算法。由于scikit-learn中没有关联算法的类库,而Spark MLlib有,本文的使用以Spark MLlib作为使用环境。

1. Spark MLlib关联算法概述

    在Spark MLlib中,也只实现了两种关联算法,即我们的FP Tree和PrefixSpan,而像Apriori,GSP之类的关联算法是没有的。而这些算法支持Python,Java,Scala和R的接口。由于前面的实践篇我们都是基于Python,本文的后面的介绍和使用也会使用MLlib的Python接口。

     Spark MLlib关联算法基于Python的接口在pyspark.mllib.fpm包中。FP Tree算法对应的类是pyspark.mllib.fpm.FPGrowth(以下简称FPGrowth类),从Spark1.4开始才有。而PrefixSpan算法对应的类是pyspark.mllib.fpm.PrefixSpan(以下简称PrefixSpan类),从Spark1.6开始才有。因此如果你的学习环境的Spark低于1.6的话,是不能正常的运行下面的例子的。

     Spark MLlib也提供了读取关联算法训练模型的类,分别是 pyspark.mllib.fpm.FPGrowthModel和pyspark.mllib.fpm.PrefixSpanModel。这两个类可以把我们之前保存的FP Tree和PrefixSpan训练模型读出来。

2. Spark MLlib关联算法参数介绍

    对于FPGrowth类,使用它的训练函数train主要需要输入三个参数:数据项集data,支持度阈值minSupport和数据并行运行时的数据分块数numPartitions。对于支持度阈值minSupport,它的取值大小影响最后的频繁项集的集合大小,支持度阈值越大,则最后的频繁项集数目越少,默认值0.3。而数据并行运行时的数据分块数numPartitions主要在分布式环境的时候有用,如果你是单机Spark,则可以忽略这个参数。

    对于PrefixSpan类, 使用它的训练函数train主要需要输入四个参数:序列项集data,支持度阈值minSupport, 最长频繁序列的长度maxPatternLength 和最大单机投影数据库的项数maxLocalProjDBSize。支持度阈值minSupport的定义和FPGrowth类类似,唯一差别是阈值默认值为0.1。maxPatternLength限制了最长的频繁序列的长度,越小则最后的频繁序列数越少。maxLocalProjDBSize参数是为了保护单机内存不被撑爆。如果只是是少量数据的学习,可以忽略这个参数。

    从上面的描述可以看出,使用FP Tree和PrefixSpan算法没有什么门槛。学习的时候可以通过控制支持度阈值minSupport控制频繁序列的结果。而maxPatternLength可以帮忙PrefixSpan算法筛除太长的频繁序列。在分布式的大数据环境下,则需要考虑FPGrowth算法的数据分块数numPartitions,以及PrefixSpan算法的最大单机投影数据库的项数maxLocalProjDBSize。

3. Spark FP Tree和PrefixSpan算法使用示例

    这里我们用一个具体的例子来演示如何使用Spark FP Tree和PrefixSpan算法挖掘频繁项集和频繁序列。

    要使用 Spark 来学习FP Tree和PrefixSpan算法,首先需要要确保你安装好了Hadoop和Spark(版本不小于1.6),并设置好了环境变量。一般我们都是在ipython notebook(jupyter notebook)中学习,所以最好把基于notebook的Spark环境搭好。当然不搭notebook的Spark环境也没有关系,只是每次需要在运行前设置环境变量。

    如果你没有搭notebook的Spark环境,则需要先跑下面这段代码。当然,如果你已经搭好了,则下面这段代码不用跑了。

import os
import sys

#下面这些目录都是你自己机器的Spark安装目录和Java安装目录
os.environ[‘SPARK_HOME‘] = "C:/Tools/spark-1.6.1-bin-hadoop2.6/"

sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/bin")
sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python")
sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/pyspark")
sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/lib")
sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/lib/pyspark.zip")
sys.path.append("C:/Tools/spark-1.6.1-bin-hadoop2.6/python/lib/py4j-0.9-src.zip")
sys.path.append("C:/Program Files (x86)/Java/jdk1.8.0_102")

from pyspark import SparkContext
from pyspark import SparkConf

sc = SparkContext("local","testing")

    在跑算法之前,建议输出Spark Context如下,如果可以正常打印内存地址,则说明Spark的运行环境搞定了。

print sc

    比如我的输出是:

<pyspark.context.SparkContext object at 0x07D9E2B0>

    现在我们来用数据来跑下FP Tree算法,为了和FP Tree算法原理总结中的分析比照,我们使用和原理篇一样的数据项集,一样的支持度阈值20%,来训练数据。代码如下:

from  pyspark.mllib.fpm import FPGrowth
data = [["A", "B", "C", "E", "F","O"], ["A", "C", "G"], ["E","I"], ["A", "C","D","E","G"], ["A", "C", "E","G","L"],
       ["E","J"],["A","B","C","E","F","P"],["A","C","D"],["A","C","E","G","M"],["A","C","E","G","N"]]
rdd = sc.parallelize(data, 2)
#支持度阈值为20%
model = FPGrowth.train(rdd, 0.2, 2)

    我们接着来看看频繁项集的结果,代码如下:

sorted(model.freqItemsets().collect())

    输出即为所有 满足要求的频繁项集,大家可以和原理篇里面分析时产生的频繁项集比较。代码输出如下:

[FreqItemset(items=[u‘A‘], freq=8),
 FreqItemset(items=[u‘B‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘E‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘E‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘E‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘B‘, u‘E‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘C‘], freq=8),
 FreqItemset(items=[u‘C‘, u‘A‘], freq=8),
 FreqItemset(items=[u‘D‘], freq=2),
 FreqItemset(items=[u‘D‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘D‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘D‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘E‘], freq=8),
 FreqItemset(items=[u‘E‘, u‘A‘], freq=6),
 FreqItemset(items=[u‘E‘, u‘C‘], freq=6),
 FreqItemset(items=[u‘E‘, u‘C‘, u‘A‘], freq=6),
 FreqItemset(items=[u‘F‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘E‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘E‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘E‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘B‘, u‘E‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘E‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘E‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘E‘, u‘C‘], freq=2),
 FreqItemset(items=[u‘F‘, u‘E‘, u‘C‘, u‘A‘], freq=2),
 FreqItemset(items=[u‘G‘], freq=5),
 FreqItemset(items=[u‘G‘, u‘A‘], freq=5),
 FreqItemset(items=[u‘G‘, u‘C‘], freq=5),
 FreqItemset(items=[u‘G‘, u‘C‘, u‘A‘], freq=5),
 FreqItemset(items=[u‘G‘, u‘E‘], freq=4),
 FreqItemset(items=[u‘G‘, u‘E‘, u‘A‘], freq=4),
 FreqItemset(items=[u‘G‘, u‘E‘, u‘C‘], freq=4),
 FreqItemset(items=[u‘G‘, u‘E‘, u‘C‘, u‘A‘], freq=4)]

    接着我们来看看使用PrefixSpan类来挖掘频繁序列。为了和PrefixSpan算法原理总结中的分析比照,我们使用和原理篇一样的数据项集,一样的支持度阈值50%,同时将最长频繁序列程度设置为4,来训练数据。代码如下:

from  pyspark.mllib.fpm import PrefixSpan
data = [
   [[‘a‘],["a", "b", "c"], ["a","c"],["d"],["c", "f"]],
   [["a","d"], ["c"],["b", "c"], ["a", "e"]],
   [["e", "f"], ["a", "b"], ["d","f"],["c"],["b"]],
   [["e"], ["g"],["a", "f"],["c"],["b"],["c"]]
   ]
rdd = sc.parallelize(data, 2)
model = PrefixSpan.train(rdd, 0.5,4)

   我们接着来看看频繁序列的结果,代码如下: 

sorted(model.freqSequences().collect())

   输出即为所有满足要求的频繁序列,大家可以和原理篇里面分析时产生的频繁序列比较。代码输出如下: 

[FreqSequence(sequence=[[u‘a‘]], freq=4),
 FreqSequence(sequence=[[u‘a‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘b‘]], freq=4),
 FreqSequence(sequence=[[u‘a‘], [u‘b‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘b‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘b‘, u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘b‘, u‘c‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘c‘]], freq=4),
 FreqSequence(sequence=[[u‘a‘], [u‘c‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘c‘], [u‘b‘]], freq=3),
 FreqSequence(sequence=[[u‘a‘], [u‘c‘], [u‘c‘]], freq=3),
 FreqSequence(sequence=[[u‘a‘], [u‘d‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘d‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘a‘], [u‘f‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘]], freq=4),
 FreqSequence(sequence=[[u‘b‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘], [u‘c‘]], freq=3),
 FreqSequence(sequence=[[u‘b‘], [u‘d‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘], [u‘d‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘], [u‘f‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘a‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘a‘], [u‘d‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘a‘], [u‘d‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘a‘], [u‘f‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘b‘, u‘c‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘c‘]], freq=4),
 FreqSequence(sequence=[[u‘c‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘c‘], [u‘b‘]], freq=3),
 FreqSequence(sequence=[[u‘c‘], [u‘c‘]], freq=3),
 FreqSequence(sequence=[[u‘d‘]], freq=3),
 FreqSequence(sequence=[[u‘d‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘d‘], [u‘c‘]], freq=3),
 FreqSequence(sequence=[[u‘d‘], [u‘c‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘]], freq=3),
 FreqSequence(sequence=[[u‘e‘], [u‘a‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘a‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘a‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘a‘], [u‘c‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘b‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘c‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘f‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘f‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘f‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘e‘], [u‘f‘], [u‘c‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘f‘]], freq=3),
 FreqSequence(sequence=[[u‘f‘], [u‘b‘]], freq=2),
 FreqSequence(sequence=[[u‘f‘], [u‘b‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘f‘], [u‘c‘]], freq=2),
 FreqSequence(sequence=[[u‘f‘], [u‘c‘], [u‘b‘]], freq=2)]

  在训练出模型后,我们也可以调用save方法将模型存到磁盘,然后在需要的时候通过FPGrowthModel或PrefixSpanModel将模型读出来。

  以上就是用Spark学习FP Tree算法和PrefixSpan算法的所有内容,希望可以帮到大家。

时间: 2024-10-09 21:35:38

用Spark学习FP Tree算法和PrefixSpan算法的相关文章

Prim算法和Kruskal算法的正确性证明

今天学习了Prim算法和Kruskal算法,因为书中只给出了算法的实现,而没有给出关于算法正确性的证明,所以尝试着给出了自己的证明.刚才看了一下<算法>一书中的相关章节,使用了切分定理来证明这两个算法的正确性,更加简洁.优雅并且根本.相比之下,我的证明带着许多草莽气息,于此写成博客,只当是记录自己的思考 ------------------------------------------- 说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的

使用Apriori算法和FP-growth算法进行关联分析(Python版)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

使用Apriori算法和FP-growth算法进行关联分析

系列文章:<机器学习>学习笔记 最近看了<机器学习实战>中的第11章(使用Apriori算法进行关联分析)和第12章(使用FP-growth算法来高效发现频繁项集).正如章节标题所示,这两章讲了无监督机器学习方法中的关联分析问题.关联分析可以用于回答"哪些商品经常被同时购买?"之类的问题.书中举了一些关联分析的例子: 通过查看哪些商品经常在一起购买,可以帮助商店了解用户的购买行为.这种从数据海洋中抽取的知识可以用于商品定价.市场促销.存活管理等环节. 在美国国会

最小生成树(Prim算法和Kruskal算法)

1)最小生成树 给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一棵树,那么这棵树就叫生成树.如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Minimum Spanning Tree) 2)应用 比如让你为一个镇的九个村庄架设通信网络,每个村庄相当于一个顶点,权值是村与村之间可通达的直线距离,要求你必须用最小的成本完成这次任务:或者村庄之间建公路,连通N个村庄要N-1条路,如何让建路成本最低之类的问题. 1.Prim算法 ①该算法是构建最小生成树的算法之一.它是

最小生成树之Kruskal算法和Prim算法

依据图的深度优先遍历和广度优先遍历,能够用最少的边连接全部的顶点,并且不会形成回路. 这样的连接全部顶点并且路径唯一的树型结构称为生成树或扩展树.实际中.希望产生的生成树的全部边的权值和最小,称之为最小生成树. 常见的最小生成树算法有Kruskal算法和Prim算法. Kruskal算法每次选取权值最小的边.然后检查是否增加后形成回路,假设形成回路则须要放弃.终于构成最小生成树.n个顶点的图最小生成树过程例如以下: 边的权值升序排序. 选取全部未遍历的边中权值最小的边,推断增加后是否形成回路,若

Algorithm --&gt; Kruskal算法和Prim算法

最小生成树之Kruskal算法和Prim算法 根据图的深度优先遍历和广度优先遍历,可以用最少的边连接所有的顶点,而且不会形成回路.这种连接所有顶点并且路径唯一的树型结构称为生成树或扩展树.实际中,希望产生的生成树的所有边的权值和最小,称之为最小生成树.常见的最小生成树算法有Kruskal算法和Prim算法. Kruskal算法 每次选取权值最小的边.然后检查是否加入后形成回路,如果形成回路则需要放弃.最终构成最小生成树.n个顶点的图最小生成树步骤如下: 边的权值升序排序: 选取所有未遍历的边中权

SM2算法和RSA算法简介

SM2算法和RSA算法都是公钥密码算法,SM2算法是一种更先进安全的算法,在安全性能.速度性能等方面都优于RSA算法,在我国商用密码体系中被用来替换RSA算法.国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统.密钥管理系统.应用系统进升级改造,使用SM2算法. SM2算法和RSA算法简介 RSA公钥加密算法是美国计算机学家Ron Rivest.Adi Shamir和Leonard Adleman于1977年提出,是最早的公钥加密算法之一,在全球范围

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

Dijkstra算法和Floyed算法

写的比较好的三篇文章 Floyed算法 最短路径-Dijkstra算法和Floyed算法 最短路径之Dijkstra算法和Floyed算法 哈哈,他山之石,可以攻玉 自己有心得,慢慢补充