zoukankan      html  css  js  c++  java
  • 机器学习实战第11章——使用 Apriori 算法进行关联分析

    从大规模数据集中寻找物品间的隐含关系被称作关联分析(association analysis)或者关联规则学习(association rule learning)。
     
    优点:简单
    缺点:对大数据集比较慢
    使用数据类型:数值型或者标称型
     
    一、相关定义:
    频繁项集:经常出现在一起的物品集合
    关联规则:两种物品之间存在很强的关系,表示为P->H
    support支持度:该项集在所有数据集中出现的次数所占的比例,Support(P,H) = NUM(P,H) / N
    confidence置信度:Confidence(P->H) = support({P,H}) / support({P}) = P(H|P)
     
    二、使用Apriori算法发现频繁项
    原理:如果某个项集是频繁的,那么它的子集也是频繁的,也就是说如果一个项集是非频繁的,那么它的超集也是非频繁的。
    输入:数据集D,支持度阈值s
    输出:最大频繁k项集
    1. k=1, 扫描整个数据集,得到所有出现过的数据,作为初始候选频繁1项集candiItem1
    2. 计算频繁k项集
        a)  计算候选频繁k项集的支持度
        b)去掉所有支持度小于阈值s的项集,得到频繁k项集。
        c)如果频繁k项集为空,则直接返回频繁k-1项集,算法结束。如果得到的频繁项集只有一项,直接返回频繁k项集,算法结束
        d)  基于频繁k项集,连接生成候选频繁k+1项集
    3. 令k=k+1,进入步骤2
    实现代码:
    def loadDataSet():
        return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
     
     
    def createC1(DataSet):
        """
        创建初始候选频繁项集c1
        :param DataSet:
        :return:
        """
        C1 = []
        for lineSet in DataSet:
            for item in lineSet:
                if not [item] in C1:
                    C1.append([item])
        C1.sort()
        return list(map(frozenset,C1))  #use forzen set so we can use it to as a key in dict
     
     
    def getLk(DataSet, Ck, minSupport):
        """
        返回ck的频繁项集,和支持度
        :param C:
        :return:
        """
        Lk = [];    #频繁项集
        Cksupport = {};   #CK的支持度
        Lksupport = {}; #LK的支持度
        numItem = float(len(DataSet))
        for C in Ck:
            for D in DataSet:
                if set(C).issubset(set(D)):
                    if C not in Cksupport: Cksupport[C] = 1
                    else: Cksupport[C] += 1
     
        for key in Cksupport:
            sup = Cksupport[key] / numItem
            if sup >= minSupport:
                Lk.append(key)
                Lksupport[key] = sup
        return Lk, Lksupport
     
     
    def aprioriGen(Lk):
        """
        根据频繁项集LK生成Ck+1
        :param Lk:
        :return:
        """
        Ck = []
        for i in range(len(Lk)-1):
            for j in range(i + 1, len(Lk)):
                c = list(set(Lk[i]).union(set(Lk[j])))
                if c not in Ck:
                    Ck.append(c)
        return list(map(frozenset, Ck))
     
     
    def aprior(DataSet, minSupport=0.5):
         """
        生成频繁项集
        :param DataSet:原始数据集
        :return:
            L:满足最小支持度的频繁项集
            supportData:支持度数据集
        """
        k = 1
        C1 = createC1(DataSet)
        L1, supportData = getLk(DataSet, C1, minSupport)
        L = [L1]
        C = [C1]
        while(len(L[-1]) > 1):
            k += 1
            C.append(aprioriGen(L[-1]))
            Lk, LkSupport = getLk(DataSet, C[k-1], minSupport)
            L.append(Lk)
            supportData.update(LkSupport)
        # if len(L[-1]) == 1 or len(L) <= 1:
        #     for item in L[-1]:
        #         supportData.update({item : LSupport[item]})
        #     return L[-1], LSupport
        # else :
        #     for item in L[-2]:
        #         supportData.update({item : LSupport[item]})
        #     return L[-2], LSupport
        return L, supportData
     
    if __name__ == '__main__':
        DataSet = loadDataSet()
        L, LSupport = aprior(DataSet, 0.7)
        print(L, LSupport)  
    结果:
     
    三、从频繁项中挖掘关联规则
    一条规则P->H的置信度为support(P,H)/support(P)
    输入:最大频繁项集L,对应的支持度数据集supportData,最低置信度minConf
    输出:满足最低置信度的规则bigRuleList
    对每个频繁项集Li:
        如果元素个数大于等于2:
            生成关联规则(获取单个元素的H1, P=Li-Hk)
            计算规则置信度,将置信度大于minConf的规则存入bigRuleList
            while:H的长度小于len(Li)-1:
            根据Hk,生成关联规则(获取H(k+1), P=Li-H(k+1))
            计算规则置信度,将置信度大于minConf的规则存入bigRuleList
    返回bigRuleList
     
    实现代码:
    def generateRules(L, supportData, minConf=0.7):
        """
        生成满足最小可信度的关联规则
        :param L: 最大频繁项集
        :param supportData: 支持度数据集
        :param minConf: 最低可信度
        :return: 满足最小可信度的关联规则
        """
        bigRuleList = []
        for i in range(len(L)):
            for freqSet in L[i]:
                if len(freqSet) >= 2:
                    H1 = [frozenset([item]) for item in freqSet]
                    prunedH = calConf(freqSet, supportData, minConf, H1, bigRuleList)
                    while len(prunedH) < len(H1) - 1:
                        Hk = aprioriGen(prunedH)   #CREATE H(K+1)
                        prunedH = calConf(freqSet, supportData, minConf, Hk, bigRuleList)
     
     
     
    def calConf(Lk, supportData, minCof, H, bigRuleList):
        """
        计算规则的可信度,返回满足最小可信度的H
        :param Lk:  频繁项集
        :param supportData: 支持度
        :param minCof:  最小可信度
        :param H:  规则的后件集合
        :param bigRuleList: 满足最小可信度的生成规则
        :return: prunedH    满足最小可信度的后件
        """
        prunedH = []
        confData = {}
        for conseq in H:
            conf = supportData[Lk] / supportData[frozenset(Lk)-frozenset(conseq)]
            if conf >= minCof:
                print(Lk-conseq, '-->', conseq, 'conf:', conf)
                bigRuleList.append((Lk - conseq, H, conf))
                prunedH.append(conseq)
        return prunedH
    if __name__ == '__main__':
        DataSet = loadDataSet()
        L, LSupport = aprior(DataSet, 0.7)
        print(L, LSupport)
        generateRules(L, LSupport, 0.5)
     

      

  • 相关阅读:
    秘密挤奶机(最大流,二分)
    伊基的故事 I
    多源汇最大流(最大流)
    无向树是二分图
    上下界可行流
    圆桌问题(最大流,二分图,网络流24题)
    双栈排序
    观光奶牛
    拜访奶牛
    愤怒的牛&数列分段II
  • 原文地址:https://www.cnblogs.com/weiququ/p/10003305.html
Copyright © 2011-2022 走看看