实 验 目 的:
1、熟悉Apriori算法和FP算法的具体实现过程。
2、熟悉频繁项集挖掘方法,并体会FP算法对于Apriori算法的效率提升。
3、加强对Apriori 算法与FP-growth算法的理解;
4、锻炼分析问题、解决问题并动手实践的能力。
实 验 内 容 及 过 程:
1、任选数据集,实现FP-growth 算法;
2、对比Apriori算法与FP-growth在相同数据集上的性能。
FP树:FP-growth算法将数据存储在一种称为FP树的紧凑数据结构中。FP代表频繁模式。一棵FP树看上去和其他的树类似,但是它通过链接来连接相似的元素,被连接的元素可以看作一个链表。
同搜索树不同,一个元素可以在FP树中出现多次,FP树会存储项集出现的频率,每个项集会以路径形式存在树中。存在相似元素的集合会共享树的一部分。树节点给出集合中单个元素及其在序列中出现的次数,路径会给出该序列出现的次数。相似项之间的链接即为节点连接,用于快速发现相似项的位置。链接在图中用虚曲线表示,它链接了相同的元素。
下面是构成这个FP树所用到的数据:
在上面的那棵树中,项集中的元素是某个节点到根节点之间路径上所有元素的集合,该项集出现的频率是第一个节点旁边代表的数字。比如集合{z}一共出现了5次,集合{r,z}一共出现了一次,这和表中的数据结论是相吻合的。至于树中没有出现的元素,是因为我们同样对这棵树设置了最小支持度,小于该值的项集不会出现。这棵树设置的最小支持度为3,所以其他的元素并没有出现在这棵树上。
FP-growth算法的工作流程如下:首先构成FP树,然后利用它来挖掘频繁项集。为了构建FP树,需要对原始数据扫描两遍。第一遍对所有元素项出现的次数进行统计,把那些不符合支持度的元素去掉。数据库的第一遍扫描用于统计出现的频率,第二次扫描只考虑那些频繁元素。
1、构建FP树:因为最终结果是要构建一棵FP树,为成功构建该树,需要一个容器来保存。
①创建FP树的数据结构:由于树中需要保存大量信息,为了方便之后的计算,我们将树节点存储到一个类中。
②构建FP树除了构建FP树所需的数据结构,还需要一个头指针来指向给定类型的第一个实例。利用头指针,可以快速访问树中给定类型的所有元素,下面是一个头指针表的示意图:
第一次遍历数据集会获得每个元素项出现的频率。接下来去掉不满足最小支持度的元素项。再下一步构建FP树。在构建时,读入每个项集并将其添加到已经存在的路径中,如果路径不存在,则创建一条新路径。
每个事务是一个无序集合,假设有集合{z,y}和{y,z},那么在FP树中,相同项只会表示一次。为了解决这个问题,将集合添加到树之前,需要对每个集合进行排序。排序基于元素项的出现频率来进行。上面的数据经过去除非频繁项集和排序后得到以下结果:
在对集合进行过滤排序之后,就可以构建FP树了。从空集开始,向其不断添加频繁项集。过滤排序后的事务依次添加到树中,如果树中已存在现有的元素,则增加现有元素的值。如果元素不存在,则向树中添加一个分支。对前面数据中前两条进行添加的过程如下:
构建树的详细代码如下:
树构建的过程中遍历两遍数据集,第一次遍历数据集获取每个元素出现的次数,并去除不符合要求的元素。第二次遍历只对频繁项集,将每条数据中的频繁项集取出,之后对其排序,最后添加到树中。
排序算法根据出现次数从大到小排序
第一次写的时候发现排序结果和树中的不一样,排查后发现是对出现次数相同的元素排序规则不一样。不过这个并不影响最终结果,如果想改成书中那样,只需要在排序中key的选择写成key=lambda x:(x[1],x[0]),先对次数进行排序,同次数的再根据元素ascII码排序。
之后就是要将处理好的集合添加到树中,具体代码如下:(图1)
图1
这样整个FP树就创建完毕了,接下来导入数据进行测试,由于数据集的格式和其他的都不一样,这里先创建数据集的处理函数
2、从FP树中挖掘频繁项集
有了FP树之后,就可以抽取频繁项集了。这里的思路和Apriori算法大体一致,首先从单元素集合开始,然后在此基础上逐步构建更大的集合。这里利用到了FP树,就不需要原始数据集了。
从FP树中抽取频繁项集的三个基本步骤如下:
①从FP树中获取条件模式基
②利用条件模式基,构建一个条件FP树
③迭代重复前两步,直到树包含一个元素项为止
具体代码如下:(图2)
3、创建条件FP树
对于每一个频繁项,都要创建一棵条件FP树。可以使用刚才构建的条件模式基作为输入数据,并通过相同的建树代码来构建这些树。然后递归的发现频繁项、发现条件模式基,以及发现另外的条件树。该过程不断重复,直到条件树中没有元素为止,就可以停止了。具体的实现代码如下:(图3)
对上面的数据进行测试,得到频繁项集如下:
[{'r'}, {'y +
'}, {'x', 'y'}, {'x', 'y', 'z'}, {'y', 'z'}, {'t'}, {'x', 't'}, {'x', 'y', 't'}, {'x', 'z', 'y', 't'}, {'x', 'z', 't'}, {'y', 't'}, {'z', 'y', 't'}, {'z', 't'}, {'s'}, {'x', 's'}, {'x'}, {'x', 'z'}, {'z'}]
实 验 心 得:
对比实验三,我们可以发现apriori算法多次扫描交换数据库,每次利⽤候选频繁集产⽣频繁集;⽽FP-growth则利⽤树形结构,⽆需产⽣候选频繁集⽽是直接得到频繁集,⼤⼤减少扫描交易数据库的次数,从⽽提⾼了算法的效率。
但是apriori的算法扩展性较好,可以⽤于并⾏计算等领域。使⽤Apriori算法进⾏关联分析。FP-growth算法来⾼效发现频繁项集。