美文网首页
关联分析(apriori & FP-tree)基于python

关联分析(apriori & FP-tree)基于python

作者: needle_princess | 来源:发表于2018-09-17 17:08 被阅读0次

    关联分析是为了探索不同集合共同出现的频率的一种方法,适用于分析名称变量,比如著名的啤酒尿布分析。通过分析消费者购物清单,发现啤酒和尿布经常出现在同一张清单上。

    apriori原理介绍

    apriori是一种常见的关联分析方法。它基于一个前提,就是频繁集的子集一定是频繁集。这句话的倒过来讲同样成立,非频繁集的母集一定也是非频繁集,我们将这个命题称之为频繁集定理。
    寻找频繁集涉及到两个频率,一个是集合在所有数据中出现的频率,称之为支持度。另一个是当集合A出现是,集合B也同时出现的频率,称之为置信度。

    举例: image.png

    可以想象,第一个集合是单个元素构成的,例如{a},{a}的支持度为4/5=0.8,当a存在时,b的置信度是2/4=0.5。第二层可以再{a,b}的基础上继续计算支持度和相应的置信度。如果用这种方式逐个匹配,会发现计算比较大。根据频繁集定理,我们可以设置一个最小支持度,当集合支持度小于最小支持度,该集合的所有母集也肯定都小于最小支持度,这部分数据可以直接省略。例如当我们把最小支持度设为0.7时,第一层的集合就剩下{a}。

    apriori python实现

    def loadDataSet():#新建数据集
        return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
    def createC1(dataSet):
        C1 = []
        for transaction in dataSet:
            for item in transaction:
                if not [item] in C1:
                    C1.append([item])
        C1.sort()
        return map(frozenset, C1)
    def scanD(D, Ck, minSupport):
        ssCnt = {}
        for tid in D:
            for can in Ck:
                if can.issubset(tid):
                    ssCnt[can] = ssCnt.get(can, 0) + 1
        #print(D)
        numItems = float(len(D))
        retList = []
        supportData = {}
        for key in ssCnt:
            support = ssCnt[key] / numItems
            if support >= minSupport:
                retList.insert(0, key)
            supportData[key] = support
        return retList, supportData
    
    def aprioriGen(Lk, k):
        retList = []
        lenLk = len(Lk)
        for i in range(lenLk):
            for j in range(i + 1, lenLk):
                # 前k-2项相同时,将两个集合合并
                L1 = list(Lk[i])[:k-2]; L2 = list(Lk[j])[:k-2]
                L1.sort(); L2.sort()
                if L1 == L2:
                    retList.append(Lk[i] | Lk[j])
        return retList
    def apriori(dataSet, minSupport=0.5):##支持度计算
        C1 = list(createC1(dataSet))
        D = list(map(set, dataSet))
        L1, supportData = scanD(D, C1, minSupport)
        L = [L1]
        k = 2
        while (len(L[k-2]) > 0):
            Ck = aprioriGen(L[k-2], k)
            Lk, supK = scanD(D, Ck, minSupport)
            supportData.update(supK)
            L.append(Lk)
            k += 1
        return L, supportData
    
    def generateRules(L, supportData, minConf=0.7):  
        bigRuleList = []  
        for i in range(1, len(L)):  # 不处理单元素集合L[0]  
            for freqSet in L[i]:  
                H1 = [frozenset([item]) for item in freqSet]  
                if (i > 1):  # 当集合中元素的长度大于2的时候,尝试对集合合并。  
    # 比如:[2,3,5]=>{[2,3],5}  
                    rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)  
                else:  # 对于2元组,直接计算置信度  
                    calConf(freqSet, H1, supportData, bigRuleList, minConf)  
        return bigRuleList  
    
    
    def calConf(freqSet, H, supportData, brl, minConf=0.7):  #置信度计算
        prunedH = []  
        for conseq in H:  
            conf = supportData[freqSet] / supportData[freqSet - conseq]  # 置信度  
            if conf >= minConf:  
                print (freqSet - conseq,'supp',supportData[freqSet - conseq] , "--->", conseq, "conf", conf ) 
                brl.append((freqSet - conseq, conseq, conf))  
                prunedH.append(conseq)  
    #         if (len(freqSet) > 2):  
    #             conf = supportData[freqSet] / supportData[conseq]  # 置信度  
    #         if conf >= minConf:  
    #             print (conseq, "--->", freqSet - conseq, "conf", conf )
    #             brl.append((conseq, freqSet - conseq, conf))  
    #             prunedH.append(freqSet - conseq)  
        return prunedH  
    
    
    
    def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):  
        m = len(H[0])  
        if (len(freqSet) > (m + 1)):  
            Hmp1 = aprioriGen(H, m + 1)  
            Hmp1 = calConf(freqSet, Hmp1, supportData, brl, minConf)  
            if (len(Hmp1) > 1):  
                rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)  
    

    将上述代码存储成apriori.py

    #引用并计算
    import apriori####将上面两个过程写入apriori,调用
    
    dataSet = apriori.loadDataSet()
    print(dataSet)
    C1 = apriori.createC1(dataSet)
    D = list(map(set, dataSet))
    print(type(D))
    L1, suppDat = apriori.scanD(D, C1, 0.5)
    print(L1)
    L, suppData = apriori.apriori(dataSet)
    print(L)
    L, suppData = apriori.apriori(dataSet, minSupport=0.5)
    print(L)
    ruleList = apriori.generateRules(L, suppData,  minConf=0.5) 
    
    
    
    

    FP-tree原理介绍

    apriori算法每次发现潜在的频繁集都需要重新扫描数据集来计算,速度堪忧。
    因此有人提出了FP-tree算法,这个算法优点明显,只需要对数据集扫描两次就可以完成寻找频繁集的任务。
    第一次扫描,对所有的单元素集合删除支持度过小的集合且建立频数指针,如a:1。过滤并对数据集进行排序。
    第二次扫描,建立FP树。这颗树是怎么建的呢,从头开始读入数据,将数据添加到已有路径上,如果路径不存在则新建路径,同时指针中频数变化。这样问题就集中在对路径和指针的保存上。

    FP-tree python实现

    网上这部分代码很多,这里就略过了
    

    参考资料:机器学习实战

    相关文章

      网友评论

          本文标题:关联分析(apriori & FP-tree)基于python

          本文链接:https://www.haomeiwen.com/subject/ysolnftx.html