基于python 的Apriori算法

来源:互联网 发布:怎么提升自己 知乎 编辑:程序博客网 时间:2024/05/21 17:53

 Apriori algorithm是关联规则里一项基本算法。是由Rakesh Agrawal和Ramakrishnan Srikant两位博士在1994年提出的关联规则挖掘算法。关联规则的目的就是在一个数据集中找出项与项之间的关系,也被称为购物蓝分析 (Market Basket analysis),因为“购物蓝分析”很贴切的表达了适用该算法情景中的一个子集。
 该算法的具体思想可以参考这个网址了解:
 Apriori算法详解
 接下来,我向分享如何用代码实现Apriori算法,步骤如下:
 1.创建apriori类
 

class Apriori:    def __init__(self,min_sup=0.2,dataDic={}):        self.data = dataDic  ##构建数据记录词典,形如{'T800': ['I1', 'I2', 'I3', 'I5'],...}        self.size = len(dataDic) #统计数据记录的个数        self.min_sup = min_sup  ##最小支持度的阈值        self.min_sup_val = min_sup * self.size ##最小支持度计数

2.过滤掉小于最小支持度阈值的物品

 def find_frequent_1_itemsets(self):        FreqDic = {} #{itemset1:freq1,itemsets2:freq2},用于统计物品的支持度计数        for event in self.data:  ##event为每一条记录,如T800            for item in self.data[event]: ##item就是I1,I2,I3,I4,I5                if item in FreqDic:                    FreqDic[item] += 1                else:                    FreqDic[item] = 1        L1 = []        for itemset in FreqDic:            if FreqDic[itemset] >= self.min_sup_val: ##过滤掉小于最小支持度阈值的物品                L1.append([itemset])        return L1

3.过滤掉非频繁项集

  def has_infrequent_subset(self,c,L_last,k):        ## c为当前集合,L_last为上一个频繁项集的集合,k为当前频繁项集内的元素个数,        ## 该函数用于检查当前集合的子集是否 都为频繁项集        subsets = list(itertools.combinations(c,k-1)) #itertools是排列组合模块,目的就c分解,如[1,2,3]将分成[(1,2),(1,3),(2,3)]        for each in subsets:            each = list(each) #将元组转化为列表            if each not in L_last:  ##子集是否 都为频繁项集                return True        return False

补充说明:
itertools是排列组合模块,例如 list(itertools.combinations([1,2,3],2))就能分解成[(1,2),(1,3),(2,3)]
具体使用可以参考:http://www.jb51.net/article/34921.htm

4.合并形成新的频繁项集

  def apriori_gen(self,L_last): #L_last means frequent(k-1) itemsets        k = len(L_last[0]) + 1        Ck = []        ##        for itemset1 in L_last:            for itemset2 in L_last:                #join step                flag = 0                for i in range(k-2):                    print k-2                    if itemset1[i] != itemset2[i]:                        flag = 1 ##若前k-2项中如果有一个项是不相等,新合并的集合是不可能是频繁项集                        break;                if flag == 1:continue                if itemset1[k-2] < itemset2[k-2]:                    c = itemset1 + [itemset2[k-2]]                else:                    continue                #pruning setp                if self.has_infrequen`t`_subset(c,L_last,k):##判断子集是否为频繁项集                    continue                else:                    Ck.append(c)        return Ck

5.关联分析迭代形成频繁项集

 def do(self):        L_last = self.find_frequent_1_itemsets() ##过滤掉小于最小支持度阈值的物品        L = L_last        i = 0        while L_last != []:            Ck = self.apriori_gen(L_last) ##合并形成新的频繁项集            FreqDic = {}            for event in self.data:                #get all suported subsets                for c in Ck: ##统计新形成的频繁项集的个数                    if set(c) <= set(self.data[event]):#判断新合成的频繁项目是否为数据记录的子集                        if tuple(c) in FreqDic:                            FreqDic[tuple(c)]+=1                        else:                            FreqDic[tuple(c)]=1            print FreqDic            Lk = []            for c in FreqDic:                print c                print '------'                if FreqDic[c] > self.min_sup_val:##判断新形成的频繁项集是否大于最小支持度的阈值                    Lk.append(list(c))            L_last = Lk            L += Lk        return L  ## L就是新形成的频繁项集的集合

测试样例
Data = {'T100':['I1','I2','I5'],
'T200':['I2','I4'],
'T300':['I2','I3'],
'T400':['I1','I2','I4'],
'T500':['I1','I3'],
'T600':['I2','I3'],
'T700':['I1','I3'],
'T800':['I1','I2','I3','I5'],
'T900':['I1','I2','I3']}

完整代码:

#! -*- coding:utf-8 -*-import itertoolsclass Apriori:    def __init__(self,min_sup=0.2,dataDic={}):        self.data = dataDic  ##构建数据记录词典,形如{'T800': ['I1', 'I2', 'I3', 'I5'],...}        self.size = len(dataDic) #统计数据记录的个数        self.min_sup = min_sup  ##最小支持度的阈值        self.min_sup_val = min_sup * self.size ##最小支持度计数    def find_frequent_1_itemsets(self):        FreqDic = {} #{itemset1:freq1,itemsets2:freq2},用于统计物品的支持度计数        for event in self.data:  ##event为每一条记录,如T800            for item in self.data[event]: ##item就是I1,I2,I3,I4,I5                if item in FreqDic:                    FreqDic[item] += 1                else:                    FreqDic[item] = 1        L1 = []        for itemset in FreqDic:            if FreqDic[itemset] >= self.min_sup_val: ##过滤掉小于最小支持度阈值的物品                L1.append([itemset])        return L1    def has_infrequent_subset(self,c,L_last,k):        ## c为当前集合,L_last为上一个频繁项集的集合,k为当前频繁项集内的元素个数,        ## 该函数用于检查当前集合的子集是否 都为频繁项集        subsets = list(itertools.combinations(c,k-1)) #itertools是排列组合模块,目的就c分解,如[1,2,3]将分成[(1,2),(1,3),(2,3)]        for each in subsets:            each = list(each) #将元组转化为列表            if each not in L_last:  ##子集是否 都为频繁项集                return True        return False    def apriori_gen(self,L_last): #L_last means frequent(k-1) itemsets        k = len(L_last[0]) + 1        Ck = []        ##        for itemset1 in L_last:            for itemset2 in L_last:                #join step                flag = 0                for i in range(k-2):                    print k-2                    if itemset1[i] != itemset2[i]:                        flag = 1 ##若前k-2项中如果有一个项是不相等,新合并的集合是不可能是频繁项集                        break;                if flag == 1:continue                if itemset1[k-2] < itemset2[k-2]:                    c = itemset1 + [itemset2[k-2]]                else:                    continue                #pruning setp                if self.has_infrequent_subset(c,L_last,k):##判断子集是否为频繁项集                    continue                else:                    Ck.append(c)        return Ck    def do(self):        L_last = self.find_frequent_1_itemsets() ##过滤掉小于最小支持度阈值的物品        L = L_last        i = 0        while L_last != []:            Ck = self.apriori_gen(L_last) ##合并形成新的频繁项集            FreqDic = {}            for event in self.data:                #get all suported subsets                for c in Ck: ##统计新形成的频繁项集的个数                    if set(c) <= set(self.data[event]):#判断新合成的频繁项目是否为数据记录的子集                        if tuple(c) in FreqDic:                            FreqDic[tuple(c)]+=1                        else:                            FreqDic[tuple(c)]=1            print FreqDic            Lk = []            for c in FreqDic:                print c                print '------'                if FreqDic[c] > self.min_sup_val:##判断新形成的频繁项集是否大于最小支持度的阈值                    Lk.append(list(c))            L_last = Lk            L += Lk        return L  ## L就是新形成的频繁项集的集合#******Test******Data = {'T100':['I1','I2','I5'],        'T200':['I2','I4'],        'T300':['I2','I3'],        'T400':['I1','I2','I4'],        'T500':['I1','I3'],        'T600':['I2','I3'],        'T700':['I1','I3'],        'T800':['I1','I2','I3','I5'],        'T900':['I1','I2','I3']}a=Apriori(dataDic=Data)# print a.do()a.do()
0 0