基本概念

  关联分析是一种在大规模数据集中寻找有趣关系的非监督学习算法。这些关系可以有两种形式:频繁项集或者关联规则。频繁项集(frequent item sets)是经常出现在一块的物品的集合,关联规则(association rules)暗示两种物品之间可能存在很强的关系。

  下图是一个乒乓球店的交易记录,〇表示顾客购买了商品。其中{底板,胶皮,浇水}就是一个频繁项集;从中可以找到底板->胶皮这样的关联规则:

支持度

  怎样有效定义频繁和关联?其中最重要的两个概念是支持度和置信度。

  支持度(support)从字面上理解就是支持的程度,一个项集的支持度(support)被定义为数据集中包含该项集的记录所占的比例。上图中{底板}的支持度=(5/6) * 100%。

  这个概念其实经常在现实生活中出现,翻译成支持率似乎更好理解,典型的例子就是投票,比如英国脱欧的支持率为51.89%。

  用数学去解释就是,设W 中有s%的事务同时支持物品集A和B,s%称为{A,B}的支持度,即:

  support({A,B}) = num(A∪B) / W = P(A∩B)

  num(A∪B)表示含有物品集{A,B}的事务集的个数,不是数学中的并集。

置信度

  置信度(confidence)揭示了A出现时B是否一定出现,如果出现,则出现的概率是多大。如果A->B的置信度是100%,则说明A出现时B一定会出现(返回来不一定)。上图中底板共出现5次,其中4次同时购买了胶皮,底板->胶皮的置信度是80%。

  用公式表示是,物品A->B的置信度=物品{A,B}的支持度 / 物品{A}的支持度:

  Confidence(A->B) = support({A,B}) / support({A}) = P(B|A)

Apriori原理

   假设我们在经营一家商品种类并不多的杂货店,我们对那些经常在一起被购买的商品非常感兴趣。我们只有4种商品:商品0,商品1,商品2和商品3。那么所有可能被一起购买的商品组合都有哪些?这些商品组合可能只有一种商品,比如商品0,也可能包括两种、三种或者所有四种商品。我们并不关心某人买了两件商品0以及四件商品2的情况,我们只关心他购买了一种或多种商品。

  下图显示了物品之间所有可能的组合。为了让该图更容易懂,图中使用物品的编号0来取代物品0本身。另外,图中从上往下的第一个集合是Ф,表示空集或不包含任何物品的集合。物品集合之间的连线表明两个或者更多集合可以组合形成一个更大的集合。

  前面说过,我们的目标是找到经常在一起购买的物品集合。我们使用集合的支持度来度量其出现的频率。一个集合的支持度是指有多少比例的交易记录包含该集合。如何对一个给定的集合,比如{0,3},来计算其支持度?我们遍历毎条记录并检查该记录包含0和3,如果记录确实同时包含这两项,那么就增加总计数值。在扫描完所有数据之后,使用统计得到的总数除以总的交易记录数,就可以得到支持度。上述过程和结果只是针对单个集合{0,3}。要获得每种可能集合的支持度就需要多次重复上述过程。我们可以数一下上图中的集合数目,会发现即使对于仅有4种物品的集合,也需要遍历数据15次。而随着物品数目的增加遍历次数会急剧增长。对于包含— 物品的数据集共有2N-1种项集组合。事实上,出售10000或更多种物品的商店并不少见。即使只出售100种商品的商店也会有1.26×1030种可能的项集组合。对于现代的计算机而言,需要很长的时间才能完成运算。

  为了降低所需的计算时间,研究人员发现一种所谓的Apriori原理。Apriori原理可以帮我们减少可能感兴趣的项集。Apriori原理是说如果某个项集是频繁的,那么它的所有子集也是频繁的。上图给出的例子,这意味着如果{0,1}是频繁的,那么{0}、{1}也一定是频繁的。这个原理直观上并没有什么帮助,但是如果反过来看就有用了,也就是说如果一个项集是非频繁集,那么它的所有超集也是非频繁的,如下所示:

  上图中,已知阴影项集{2,3}是非频繁的。利用这个知识,我们就知道项集{0,2,3} ,{1,2,3}以及{0,1,2,3}也是非频繁的。这也就是说,一旦计算出了{2,3}的支持度,知道它是非频繁的之后,就不需要再计算{0,2,3}、{1,2,3}和{0,1,2,3}的支持度,因为我们知道这些集合不会满足我们的要求。使用该原理就可以避免项集数目的指数增长,从而在合理时间内计算出频繁项集。

Apriori算法过程

  关联分析的目标包括两项:发现频繁项集和发现关联规则。首先需要找到频繁项集,然后才能获得关联规则。

Apriori算法过程

  发现频繁项集的过程如上图所示:

  1. 由数据集生成候选项集C1(1表示每个候选项仅有一个数据项);再由C1通过支持度过滤,生成频繁项集L1(1表示每个频繁项仅有一个数据项)。
  2. 将L1的数据项两两拼接成C2。
  3. 从候选项集C2开始,通过支持度过滤生成L2。L2根据Apriori原理拼接成候选项集C3;C3通过支持度过滤生成L3……直到Lk中仅有一个或没有数据项为止。

  下面是一个超市的交易记录:

  Apriori算法发现频繁项集的过程如下:

 

以上转于:https://www.cnblogs.com/bigmonkey/p/7405555.html

FP-Grwoth 算法过程

Apriori算法虽然思路很简单,但是该算法有以下缺点:

(1)在每一步产生侯选项目集时循环产生的组合过多,没有排除不应该参与组合的元素;

(2)每次计算项集的支持度时,都对数据集中的全部记录进行了一遍扫描比较,

在数据集较大时,这样扫描下来会大大增加计算机的IO开销。这种代价会让计算机奔溃。
针对Apriori算法的性能瓶颈——需要产生大量候选集和需要重复扫描数据集,FP-growth算法应用而生。该算法只进行2次数据集扫描而且不使用候选集,直接压缩数据集成一个频繁模式树(FP树),最后通过这个FP树生成频繁项集。对于本题较大的数据集,FP-growth算法是个不错的选择。 

(1)按以下步骤构造FP-树

(a) 扫描事务数据库D一次。收集频繁项的集合F和它们的支持度。对F按支持度降序排序,结果为频繁项表L。
(b) 创建FP-树的根结点,以“null”标记它。对于D 中每个事务Trans,执行:选择 Trans 中的频繁项,并按L中的次序排序。设排序后的频繁项表为[p | P],其中,p 是第一个元素,而P 是剩余元素的表。调用insert_tree([p | P], T)。该过程执行情况如下。如果T有子女N使得N.item-name = p.item-name,则N 的计数增加1;否则创建一个新结点N将其计数设置为1,链接到它的父结点T,并且通过结点链结构将其链接到具有相同item-name的结点。如果P非空,递归地调用insert_tree(P, N)。
(2)FP-树的挖掘
通过调用FP_growth(FP_tree, null)实现。该过程实现如下:
FP_growth(Tree, α)
(1) if Tree 含单个路径P then
(2) for 路径 P 中结点的每个组合(记作β)
(3) 产生模式β ∪ α,其支持度support = β中结点的最小支持度;
(4) else for each ai在Tree的头部(按照支持度由低到高顺序进行扫描) {
(5) 产生一个模式β = ai ∪ α,其支持度support = ai .support;
(6) 构造β的条件模式基,然后构造β的条件FP-树Treeβ;
(7) if Treeβ ≠ ∅ then
(8) 调用 FP_growth (Treeβ, β);}
end
1.1.3 FP-Growth算法演示—构造FP-树
(1)事务数据库建立

原始事务数据库如下:

Tid

Items

1

I1,I2,I5

2

I2,I4

3

I2,I3

4

I1,I2,I4

5

I1,I3

6

I2,I3

7

I1,I3

8

I1,I2,I3,I5

9

I1,I2,I3

扫描事务数据库得到频繁1-项目集F。

I1

I2

I3

I4

I5

6

7

6

2

2

定义minsup=20%,即最小支持度为2,重新排列F。

I2

I1

I3

I4

I5

7

6

6

2

2

重新调整事务数据库。

Tid

Items

1

I2, I1,I5

2

I2,I4

3

I2,I3

4

I2, I1,I4

5

I1,I3

6

I2,I3

7

I1,I3

8

I2, I1,I3,I5

9

I2, I1,I3

(2)创建根结点和频繁项目表

(3)加入第一个事务(I2,I1,I5)

(4)加入第二个事务(I2,I4)

(5)加入第三个事务(I2,I3)

以此类推加入第5、6、7、8、9个事务。

(6)加入第九个事务(I2,I1,I3)

1.1.4 FP-Growth算法演示—FP-树挖掘

FP-树建好后,就可以进行频繁项集的挖掘,挖掘算法称为FpGrowth(Frequent Pattern Growth)算法,挖掘从表头header的最后一个项开始,以此类推。本文以I5、I3为例进行挖掘。

(1)挖掘I5:

对于I5,得到条件模式基:<(I2,I1:1)>、<I2,I1,I3:1>

构造条件FP-tree:

得到I5频繁项集:{{I2,I5:2},{I1,I5:2},{I2,I1,I5:2}}

I4、I1的挖掘与I5类似,条件FP-树都是单路径。

(1)挖掘I3:

I5的情况是比较简单的,因为I5对应的条件FP-树是单路径的,I3稍微复杂一点。I3的条件模式基是(I2 I1:2), (I2:2), (I1:2),生成的条件FP-树如下图:

I3的条件FP-树仍然是一个多路径树,首先把模式后缀I3和条件FP-树中的项头表中的每一项取并集,得到一组模式{I2 I3:4, I1 I3:4},但是这一组模式不是后缀为I3的所有模式。还需要递归调用FP-growth,模式后缀为{I1,I3},{I1,I3}的条件模式基为{I2:2},其生成的条件FP-树如下图所示。

在FP_growth中把I2和模式后缀{I1,I3}取并得到模式{I1 I2 I3:2}。

理论上还应该计算一下模式后缀为{I2,I3}的模式集,但是{I2,I3}的条件模式基为空,递归调用结束。最终模式后缀I3的支持度>2的所有模式为:{ I2 I3:4, I1 I3:4, I1 I2 I3:2}。

转于: https://blog.csdn.net/sunbow0/article/details/45602415

运行Spark fp-growth demo如下:

pom.xml中加载mllib依赖

<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_2.11</artifactId>
<version>2.3.0</version>
</dependency>

官网提供的代码如下:

package cn.xdf.userprofile.ML

import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.fpm.FPGrowth object FPGrowthDemo { def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder
.appName("FPGrowthDemo").master("local")
.config("spark.sql.warehouse.dir", "C:\\study\\sparktest")
.getOrCreate()
//val spark = getSparkSession("FPGrowthDemo") import spark.implicits._
val dataset = spark.createDataset(Seq(
"1 2 5",
"1 2 3 5",
"1 2 ")
).map(t => t.split(" ")).toDF("items") val fpgroth=new FPGrowth().setItemsCol("items").setMinSupport(0.5).setMinConfidence(0.6)
val model=fpgroth.fit(dataset)
// Display frequent itemsets.
model.freqItemsets.show() // Display generated association rules.
model.associationRules.show()
// transform examines the input items against all the association rules and summarize the
// consequents as prediction
model.transform(dataset).show()
// $example off$ spark.stop()
}
}

运行结果如下:

18/10/23 11:31:27 INFO CodeGenerator: Code generated in 255.413874 ms
+---------+----+
|    items|freq|
+---------+----+
|      [5]|   2|
|   [5, 1]|   2|
|[5, 1, 2]|   2|
|   [5, 2]|   2|
|      [1]|   3|
|   [1, 2]|   3|
|      [2]|   3|
+---------+----+
18/10/23 11:45:01 INFO CodeGenerator: Code generated in 566.235467 ms 
+----------+----------+------------------+
|antecedent|consequent|        confidence|
+----------+----------+------------------+
|    [1, 2]|       [5]|0.6666666666666666|
|    [5, 1]|       [2]|               1.0|
|       [2]|       [5]|0.6666666666666666|
|       [2]|       [1]|               1.0|
|       [5]|       [1]|               1.0|
|       [5]|       [2]|               1.0|
|       [1]|       [5]|0.6666666666666666|
|       [1]|       [2]|               1.0|
|    [5, 2]|       [1]|               1.0|
+----------+----------+------------------+ 

Spark下的FP-Growth和Apriori的更多相关文章

  1. 机器学习(十五)— Apriori算法、FP Growth算法

    1.Apriori算法 Apriori算法是常用的用于挖掘出数据关联规则的算法,它用来找出数据值中频繁出现的数据集合,找出这些集合的模式有助于我们做一些决策. Apriori算法采用了迭代的方法,先搜 ...

  2. FP - growth 发现频繁项集

    FP - growth是一种比Apriori更高效的发现频繁项集的方法.FP是frequent pattern的简称,即常在一块儿出现的元素项的集合的模型.通过将数据集存储在一个特定的FP树上,然后发 ...

  3. FP—Growth算法

    FP_growth算法是韩家炜老师在2000年提出的关联分析算法,该算法和Apriori算法最大的不同有两点: 第一,不产生候选集,第二,只需要两次遍历数据库,大大提高了效率,用31646条测试记录, ...

  4. Frequent Pattern 挖掘之二(FP Growth算法)(转)

    FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结 ...

  5. 关联规则算法之FP growth算法

    FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结 ...

  6. Frequent Pattern (FP Growth算法)

    FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达 到这样的效果,它采用了一种简洁的数据 ...

  7. Frequent Pattern 挖掘之二(FP Growth算法)

    Frequent Pattern 挖掘之二(FP Growth算法) FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断 ...

  8. Spark2.2+ES6.4.2(三十一):Spark下生成测试数据,并在Spark环境下使用BulkProcessor将测试数据入库到ES

    Spark下生成2000w测试数据(每条记录150列) 使用spark生成大量数据过程中遇到问题,如果sc.parallelize(fukeData, 64);的记录数特别大比如500w,1000w时 ...

  9. 【甘道夫】并行化频繁模式挖掘算法FP Growth及其在Mahout下的命令使用

    今天调研了并行化频繁模式挖掘算法PFP Growth及其在Mahout下的命令使用,简单记录下试验结果,供以后查阅: 环境:Jdk1.7 + Hadoop2.2.0单机伪集群 +  Mahout0.6 ...

随机推荐

  1. socket 简单了解

    网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.   建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API),对TCP/IP的 ...

  2. Codeforces 977D: Divide by three, multiply by two(暴力)

    题意 有nnn个无序的数,对这些数进行排列,要求ai=3×ai+1a_i=3\times a_{i+1}ai​=3×ai+1​或2×ai=ai+12\times a_i=a_{i+1}2×ai​=ai ...

  3. python-selctors实现文件上传

    服务端代码:程序目录server/server.py   上传文件目录:server/upload import os import time import socket import selecto ...

  4. java面试总躲不过的并发(一): 线程池ThreadPoolExecutor基础梳理

    本文核心:线程池ThreadPoolExecutor基础梳理 一.实现多线程的方式 1.继承Thread类,重写其run方法 2.实现Runnable接口,实现run方法 3.实现Callable接口 ...

  5. C++ 属性类

    又一次向目标迈进了... 这次是实现一个物体所拥有的属性类.没什么好说的,非常简单. 因为我是C++新手,不知道对这次的实现有没有什么更好的实现方式.因为这个类对以后的进展很重要,而且,要充分考虑易用 ...

  6. Lunar Lander 月球冒险

    发售年份 1979 平台 街机 开发商 雅达利(Atari) 类型 飞行模拟 https://www.youtube.com/watch?v=McAhSoAEbhM

  7. 用户id,组id和文件访问权限

    实际用户ID和实际组ID:标示了我们究竟是谁,这两个字段在登录时取自口令文件中的登录项 有效用户ID和有效组ID以及附属组ID:决定了我们的文件的访问权限(通常有效用户ID等于实际用户ID,有效组ID ...

  8. Thing in java 第四章,控制执行流程,练习题答案

    /** * Created by Sandy.Liu on 2018/7/19. * Thinking in java, version 4, chapter 4, practice 1 * Writ ...

  9. pl/sql oracle数据库中文数据显示异常或者不能使用中文查询的解决办法

    1首先我们需要找到pl/sql developer 目录 然后在该目录下 创建一个bat文件 在文件中定义 set NLS_LANG=AMERICAN_AMERICA.UTF8start PLSQLD ...

  10. Spring Boot引入Oracle Jar

    Oracle数据库的驱动依赖,maven仓库并不提供,需要手动添加 1. 下载jar文件 如ojdbc7.jar文件 将该文件放在D:\oracle\ojdbc7.jar路径下 2.然后在命令行输入 ...