当前位置: 代码迷 >> 综合 >> 频繁模式挖掘-FP-Growth
  详细解决方案

频繁模式挖掘-FP-Growth

热度:85   发布时间:2024-01-09 13:47:09.0

目录

算法简介

算法逻辑

案例

Spark程序实现例子(Java语言)


 

算法简介

FP-Growth是频繁模式挖掘的一种算法,由韩家炜等在2000年提出,算法通过建立一棵频繁项集树来实现频繁项集的搜索,同时能实现事务的压缩,相比Apriori能减少数据的扫描次数。

算法逻辑

1、扫描数据,统计项目(item)在数据集中出现的频数,例如苹果出现(被购买)了4次、牛奶出现(被购买)了5次等

2、再次扫描数据,构建频繁树(FP-Tree),并生成头表。将每条事物中的项目按照步骤1中的频数由高到底排列后,依次放到树中,并用头表记录每个项目在树中的位置

3、依据头表和支持度,在频繁树种搜索频繁项集

案例

数据:

交易ID(TID) item(项)
1 苹果,牛奶,香蕉
2 苹果,烤串
3 牛奶,香蕉,啤酒
4 牛奶,啤酒
5 香蕉,啤酒,尿布
6 香蕉
7 苹果,牛奶,香蕉,啤酒,尿布,烤串
8 香蕉
9 牛奶
10 啤酒

1、扫描数据,统计项目的频数,按照频数由大到小排序结果如下:

item(项) 频数
香蕉 6
牛奶 5
啤酒 5
苹果 3
烤串 2
尿布 2

2、再次扫描数据,构建频繁树(FP-Tree),并生成头表。构建FP-Tree时首先建立根节点root(或者叫NULL),根节点不保存数据

TID=1:苹果,牛奶,香蕉

根据频数对事务中的项目进行排序,得到:香蕉,牛奶,苹果

根据排序后的事务创建FP-Tree:根据频数倒序生成,香蕉紧跟在root节点后面,然后是牛奶在香蕉后面,苹果在牛奶后面,并在节点上记录项目的频数,生成头表指向各节点,如下图:

TID=2:苹果,烤串

根据频数对事务种项目进行排序,得到:苹果,烤串

插入到FP-Tree中,因root节点只有一个香蕉节点,没有苹果节点,因此root下面新增一个苹果节点;苹果节点之间增加指针,增加烤串指针

TID=3:牛奶,香蕉,啤酒

根据频数对事务种项目进行排序,得到:香蕉,牛奶,啤酒

插入到FP-Tree中,相同节点上的频数相加,如下图黑色文字部分

TID=4:牛奶,啤酒

根据频数对事务种项目进行排序,得到:牛奶,啤酒

插入到FP-Tree中,从root节点下面新增“牛奶”节点,建立啤酒之间的指针,如下图黑色文字部分

 

TID=5:香蕉,啤酒,尿布

根据频数对事务种项目进行排序,得到:香蕉,啤酒,尿布

插入到FP-Tree中,如下图黑色文字部分

TID=6:香蕉

插入到FP-Tree中,香蕉节点的频数由3增加到4,如下图黑色文字部分

TID=7:苹果,牛奶,香蕉,啤酒,尿布,烤串

根据频数对事务种项目进行排序,得到:香蕉,牛奶,啤酒,苹果,烤串,尿布

插入到FP-Tree中,如下图黑色文字部分

 

TID=8:香蕉

插入到FP-Tree中,如下图黑色文字部分

 

TID=9:牛奶

插入到FP-Tree中,如下图黑色文字部分

TID=10:啤酒

插入到FP-Tree中,如下图黑色文字部分。完整的FP-Tree如下图,从root开始生长的一棵频繁树,除root节点外,每个节点存储一个item(项目),以及item(项目)在事务数据中的频数,以及指向相同项目其他节点的指针;还有一张存储节点指针的头表。

3、挖掘频繁模式

从头表底部开始,由下到上挖掘频繁模式,最底部是尿布,在频繁树中,有两条路径:(香蕉6-牛奶3-啤酒2-苹果1-烤串1-尿布1)、(香蕉6-啤酒1-尿布1);

假如最小支持度设为2,即项目或项目组合大于等于2才算是频繁项,则以上两条路径被裁剪为(香蕉6-啤酒2-尿布1)、(香蕉6-啤酒1-尿布1)。苹果、烤串和尿布组合的数量只有1 ,不满足最小支持度,因此被裁剪掉;建立如下子树:

根据子树,得到频繁项集:以“尿布”结尾的频繁项集有:(尿布)(尿布,啤酒)(尿布,香蕉)(尿布,啤酒,香蕉)

然后根据指针的头表,继续向上挖掘以“烤串”、“苹果”,“啤酒”,“牛奶”,“香蕉”结尾的频繁项集
 

 

Spark程序实现例子(Java语言)

Spark中实现了FP-Growth算法,官方例子点这里,下面是代码


public class JavaFPGrowthExample {public static void main(String[] args) {//创建SparkSessionSparkSession spark = SparkSession.builder().appName("JavaFPGrowthExample").master("local").getOrCreate();// 创建List数据List<Row> data = Arrays.asList(RowFactory.create(Arrays.asList("1 2 5".split(" "))),RowFactory.create(Arrays.asList("1 2 3 5".split(" "))),RowFactory.create(Arrays.asList("1 2".split(" "))));StructType schema = new StructType(new StructField[]{ new StructField("items", new ArrayType(DataTypes.StringType, true), false, Metadata.empty())});// 创建DataFrameDataset<Row> itemsDF = spark.createDataFrame(data, schema);// 显示原始数据System.out.println("原始数据在同一列里面,这是Spark的规则,数据框如下:");itemsDF.show(false);// 创建FPGrowth实例FPGrowthModel model = new FPGrowth().setItemsCol("items") // 设置输入列,交易数据需要进行拆分后,将项目(item)数据放在同一列中,这是Spark的要求.setMinSupport(0.5) // 设置最小支撑度.setMinConfidence(0.6) // 设置最小置信度.fit(itemsDF);  // 拟合数据,返回一个FPGrowthModel// 展示频繁项System.out.println("频繁项集如下,第一列是项集组合,第二列是频数:");model.freqItemsets().show();// 生成关联规则System.out.println("关联规则如下,第一列是前项,第二列是后项,第三列是置信度");model.associationRules().show();//System.out.println("得到模型后,可以调用模型的transform方法,对数据集进行预测,得到规则。第一列是项集,第二列是推出的结果");model.transform(itemsDF).show();System.out.println("例如:1、2组合能够推出5");// $example off$spark.stop();}
}

执行代码后得到以下结果

 

原始数据在同一列里面,这是Spark的规则,数据框如下:
+------------+
|items       |
+------------+
|[1, 2, 5]   |
|[1, 2, 3, 5]|
|[1, 2]      |
+------------+2021-03-02 17:16:57 WARN [org.apache.spark.mllib.fpm.FPGrowth] - Input data is not cached.
频繁项集如下,第一列是项集组合,第二列是频数:
+---------+----+
|    items|freq|
+---------+----+
|      [5]|   2|
|   [5, 1]|   2|
|[5, 1, 2]|   2|
|   [5, 2]|   2|
|      [1]|   3|
|   [1, 2]|   3|
|      [2]|   3|
+---------+----+关联规则如下,第一列是前项,第二列是后项,第三列是置信度
+----------+----------+------------------+
|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|
+----------+----------+------------------+得到模型后,可以调用模型的transform方法,对数据集进行预测,得到规则。第一列是项集,第二列是推出的结果
+------------+----------+
|       items|prediction|
+------------+----------+
|   [1, 2, 5]|        []|
|[1, 2, 3, 5]|        []|
|      [1, 2]|       [5]|
+------------+----------+例如:1、2组合能够推出5