机器学习——Apriori算法与关联分析

Apriori算法与关联分析

 

1.原理

  • 关联分析:在大数据的集合里寻找一些关系。关系有两种形式:频繁项(经常出现在一起的物品的集合)和关联规则(两种物品可能存在的强关系)。判断关系的两个标准是支持度和可信度。支持度定义为数据集中包含该项的记录所占的比例。可信度是关于关联规则的标准,如可信度 = 支 持 度 A , B 支 持 度 A =\frac{支持度{A,B}}{支持度{A}} =AA,B
  • 使用贪心算法列举所有物品的组合的运算量过于庞大,Apriori算法可以更快的找到合适的集合。Apriori算法的原理是:如果某个项集是频繁的,那么它所有的子集也是频繁的。相应地,如果一个项集是非频繁的,那么它所有的超集也是非频繁的。根据以上的理论,可以在合理时间内找出频繁项集。

 

2.代码

(1)Apriori算法

  • Apriori算法是找到频繁项集的一种方法。首先生成单个物品的列表,根据交易记录判断哪些项集满足最小支持度,对剩下的集合进行组合生成两个元素的项集,再扫描交易记录,等等重复进行直到所有项集被去除。

    生成候选项集的伪代码:
      	对数据集中每条交易记录:
      		对每个候选项集:
      			该项集是否是该条交易记录的子集,是则增加计数
      	对每个候选项集:
      		如果其支持度不低于最小值,则保留
      	返回频繁项集列表
    
# 生成候选集C1(交易记录中存在的所有物品的集合)
def createC1(dataset):
    C1 = []
    for transacation in dataset:
        for item in transacation:
            if not [item] in C1:
                C1.append([item])
    C1.sort()
    return list(map(frozenset, C1))  # 得到不可变且无重复的候选集

# 判断是否满足最小支持度,生成合适的候选集L1与其支持度
def scanD(D, Ck, minSupport):
    ssCnt = {}
    for trans in D:
        for can in Ck:
            if can.issubset(trans):  # 若原候选集的元素是交易记录的子集
                if can not in ssCnt:  # 计算候选集的元素在交易记录中出现的次数
                    ssCnt[can] = 1
                else:
                    ssCnt[can] += 1
    item_num = float(len(D))  # 交易记录的数量
    retList = []
    supportData = {}
    for key in ssCnt:
        support = ssCnt[key] / item_num  # 每个键的支持度
        if support >= minSupport:  # 保留大于最低支持度的键
            retList.insert(0, key)
        supportData[key] = support
    return retList, supportData

if __name__ == "__main__":
    dataset = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
    C1 = createC1(dataset)
    D = list(map(set,dataset))
    L1 ,support= scanD(D,C1,0.5)
    print(L1)

 

  • 再过滤集合,得到最后的候选集合

      伪代码:
      	当集合中项的个数大于0时:
      		构建由k项组成的候选项集的列表
      		检查数据,确定每个项集是频繁的
      		保留频繁项集,构建由k+1项组成的候选集的列表
    
# 组合元素
def aprioriGen(Lk, k):
    retList = []
    lenLk = len(Lk)
    for i in range(lenLk):  
        for j in range(i + 1, lenLk):  # 两两比较Lk元素以减少重复次数
            """元素本身长度为1时,直接两两组合,不会重复(list(Lk[i])[:k - 2]得到空集,即为相同集合);
            当元素本身长度大于1时,两两组合容易形成重复的组合,所以通过比较前k-2个值,相同的形成集合,这样不会造成重复
            此外,前k-2个值不同的元素的组合会直接被排除,因为其组合必定有一个子集非频繁,例如{12}与{23}的组合{123}会被排除,
            因为其子集{13}不在原列表内,说明{13}不频繁,从而{123}不频繁"""
            L1 = list(Lk[i])[:k - 2]
            L2 = list(Lk[j])[:k - 2]
            L1.sort()
            L2.sort()
            if L1 == L2:  # 排序后若前 k-2个元素都相等,则合并为一个大小为k的集合
                retList.append(Lk[i] | Lk[j])  # “|”:集合合集
    return retList

# 生成最后的候选集及其支持度
def apriori(dataset, minSupport=0.5):
    C1 = 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)  # 将上一个加入到L的列表元素进行组合,得到不重复的组合的列表
        Lk, suppk = scanD(D, Ck, minSupport)  # 剔除上面列表的不满足支持度的组合
        supportData.update(suppk)  # 增加上面的组合列表的支持度
        L.append(Lk)   #增加组合列表
        k += 1
    return L, supportData

if __name__ == "__main__":
    dataset = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
    L, support = apriori(dataset, minSupport=0.7)
    print(L)

 

(2)关联分析

  • 对于关联规则,通过可信度进行量化。一条关联规则 P → H P → H PH的可信度定义为 s u p p o r t ( P ∪ H ) / s u p p o r t ( P ) support(P∪H)/support(P) support(PH)/support(P)。同样地,如果某条规则不满足最低可信度要求,那么该规则的所有子集也不满足最低可信度的要求。根据该性质,我们可以减少进行测试的规则数目。
# 生成最终的关联规则
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]  # 对每个频繁项集生成只包含单元素集合的列表
            print('H1:', H1, 'freqset', freqSet, 'lenf', len(freqSet))
            if i > 1:  # 超过两个元素则需要两两组合后再得到关联规则
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
            else:  # 若上面的列表只包含两个元素,直接得到关联规则
                calConf(freqSet, H1, supportData, bigRuleList, minConf)
    return bigRuleList

# 返回所有满足最低可信度的元素与关联规则
def calConf(freqSet, H, supportData, br1, minConf=0.7):
    pruneH = []
    for conseq in H:  # 计算所有元素的可信度
        conf = supportData[freqSet] / supportData[freqSet - conseq]
        if conf >= minConf:
            print(freqSet - conseq, '-->', conseq, 'conf:', conf)
            br1.append((freqSet - conseq, conseq, conf))  # 添加相应关联规则
            pruneH.append(conseq)
    return pruneH, br1

# 生成组合元素的关联规则
def rulesFromConseq(freSet, H, supportData, br1, minConf=0.7):
    m = len(H[0])
    """m为H中元素的长度,由于需要找到将H中元素进行组合后的关联规则,所以要对H中的元素进行组合,
       这样使得组合后元素的长度为m+1。如果freSet的长度<= m+1,则无意义。
       如freSet=frozenset({2,3,5}),H=[frozenset({2,3}),frozenset({3,5},frozenset({2,5})]
       len(freSet)=3,m=len(H[0])=2,如果再递归,则下一个H为frozenset({2,3,5}),与freSet相同
       找它们的关联规则毫无意义,因此需要大于m+1"""
    if len(freSet) > m + 1:  # freSet的长度需要满足条件
        Hmp1 = aprioriGen(H, m + 1)  # 返回H的元素两两组合的列表
        Hmp1 = calConf(freSet, Hmp1, supportData, br1, minConf)  # 得到上述列表元素的关联规则
        if len(Hmp1) > 1:  # 如果组合后不是一个元素(还可以继续组合),继续组合
            rulesFromConseq(freSet, Hmp1, supportData, br1, minConf)

if __name__ == "__main__":
    dataset = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
    Lk, support = apriori(dataset, minSupport=0.5)
    rules = generateRules(Lk, support, minConf=0.5)
    print(rules)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值