llhthinker-Apriori算法介绍(Python实现)

一、Apriori算法简介

Apriori算法是经典的挖掘频繁项集和关联规则的数据挖掘算法。A priori在拉丁语中指"来自以前"。当定义问题时,通常会使用先验知识或者假设,这被称作"一个先验"(a priori)。Apriori算法的名字正是基于这样的事实:算法使用频繁项集性质的先验性质,即频繁项集的所有非空子集也一定是频繁的(这也是Apriori依据的公理)。Apriori算法使用一种称为逐层搜索的迭代方法,其中k项集用于探索(k+1)项集。首先,通过扫描数据库,累计每个项的计数,并收集满足最小支持度的项,找出频繁1项集的集合。该集合记为L1。然后,使用L1找出频繁2项集的集合L2,使用L2找出L3,如此下去,直到不能再找到频繁k项集。每找出一个Lk需要一次数据库的完整扫描。Apriori算法使用频繁项集的先验性质来压缩搜索空间。
公理:
Apriori定律1:如果一个集合是频繁项集,则它的所有子集都是频繁项集。
Apriori定律2:如果一个集合不是频繁项集,则它的所有超集都不是频繁项集。

二、基本概念

项与项集:设itemset={item1, item_2, …, item_m}是所有项的集合,其中,item_k(k=1,2,…,m)称为项。项的集合称为项集(itemset),包含k个项的项集称为k项集(k-itemset)。(项可以理解为一个商品;项集可以理解成整个超市所有的商品,即所有可能出现在购物篮中的商品)

事务与事务集:一个事务T是一个项集,它是itemset的一个子集,每个事务均与一个唯一标识符Tid相联系。不同的事务一起组成了事务集D,它构成了关联规则发现的事务数据库。(比如一个购物篮中的所有商品)

关联规则:关联规则是形如A=>B的蕴涵式,其中A、B均为itemset的子集且均不为空集,而A交B为空。(比如当购物篮中出现了啤酒,就应当推荐尿布,这就是一个关联规则)

支持度(support)

Prosac算法python代码_Prosac算法python代码


可以理解成:AB同时出现在一个事务的概率,用频率代替就是同时含有AB的事务数占总事务的数的比例。体现的是一种广泛性,比如在10000次购买记录中,冷门商品A和冷门商品B恰好都只被购买一次且是被同时购买,那它们的置信度就是100%。但显然这只是一个偶然行为,不能充分说明(A=>B)或者(B=>A)是强关联的规则,因此需要考虑它们的支持度,结果发现只有万分之一,在做挖掘的时候就应当抛弃掉。

置信度(confidence)

Prosac算法python代码_关联规则_02


就是条件概率,在A出现的条件下,B出现的概率,也就是P(AB)/P(A)

项集的出现频度(support count):包含项集的事务数,简称为项集的频度、支持度计数或计数。感觉称作支持度计数更加合理,体现与支持度的关系,也可以知道支持度计数=支持度*事务总数。

频繁项集(frequent itemset):如果项集I的相对支持度满足事先定义好的最小支持度阈值(即I的出现频度大于相应的最小出现频度(支持度计数)阈值),则I是频繁项集。

简单来讲就是满足最小支持度和最小置信度的项集。

强关联规则:满足最小支持度和最小置信度的关联规则,即待挖掘的关联规则。

三、实现步骤

1、找出所有频繁项集
2、从频繁项集中挖掘关联规则
注意:因为挖掘的是关联规则,体现的是同时出现的概率,所以(A,B)和(B,A)是一个项集。
相关定义:
1、连接步骤:Apriori算法假定项集中的项按照字典序排序。如果Lk-1中某两个的元素(项集)itemset1和itemset2的前(k-2)个项是相同的,则称itemset1和itemset2是可连接的。所以itemset1与itemset2连接产生的结果项集是{itemset1[1], itemset1[2], …, itemset1[k-1], itemset2[k-1]}。连接步骤包含在下文代码中的create_Ck函数中。
解释:对于(k-1)-项集,前(k-2)项相同,也就说明了是可以做连接操作,并且可以连接生成K-项集的(两个(K-1)-项集一边出一个不同的项,凑出K-2+1+1个项)。至于为什么要排序,是因为排序后的项集,如果有(K-2)项相同,那么他的顺序肯定是固定的,两个(K-1)项做前(K-2)项切片后肯定是相同的。这一步实际上就是生成K-项集(不是候选)的过程。
2、剪枝策略:由于存在先验性质:任何非频繁的(k-1)项集都不是频繁k项集的子集。因此,如果一个候选k项集Ck的(k-1)项子集不在Lk-1中,则该候选也不可能是频繁的,从而可以从Ck中删除,获得压缩后的Ck。下文代码中的is_apriori函数用于判断是否满足先验性质,create_Ck函数中包含剪枝步骤,即若不满足先验性质,剪枝。
解释:利用先验性质,删除(剪枝)不可能继续连接形成频繁K-项集的(K-1)-项集,压缩搜索空间,在实际使用中,因为大多数数据是稀疏的,所以效果非常好。这一步实际上是生成候选K-项集的过程。
3、删除策略:基于压缩后的Ck,扫描所有事务,对Ck中的每个项进行计数,然后删除不满足最小支持度的项,从而获得频繁k项集。删除策略包含在下文代码中的generate_Lk_by_Ck函数中。
解释:删除过程也是生成频繁K-项集的过程。
实际上1、2、3步骤,就是:生成K-项集=>生成候选K-项集=>生成频繁K-项集

步骤:
1、每个项都是候选1项集的集合C1的成员。算法扫描所有的事务,获得每个项,生成C1(见下文代码中的create_C1函数)。然后对每个项进行计数。然后根据最小支持度从C1中删除不满足的项,从而获得频繁1项集L1。
2、对L1的自身连接生成的集合执行剪枝策略产生候选2项集的集合C2,然后,扫描所有事务,对C2中每个项进行计数。同样的,根据最小支持度从C2中删除不满足的项,从而获得频繁2项集L2。
3、对L2的自身连接生成的集合执行剪枝策略产生候选3项集的集合C3,然后,扫描所有事务,对C3每个项进行计数。同样的,根据最小支持度从C3中删除不满足的项,从而获得频繁3项集L3。
4、以此类推,对Lk-1的自身连接生成的集合执行剪枝策略产生候选k项集Ck,然后,扫描所有事务,对Ck中的每个项进行计数。然后根据最小支持度从Ck中删除不满足的项,从而获得频繁k项集。

图解:

Prosac算法python代码_关联规则_03