Apriori算法:

扫描一遍数据库,得到一阶频繁项

用一阶频繁项构造二阶候选项

扫描数据库对二阶候选项进行计数,删除其中的非频繁项,得到二阶频繁项

然后构造三阶候选项,以此类推,直到无法构造更高阶的候选项,或到达频繁项集的最大长度限制。


Apriori.py

# 构建初始候选项集
def createC1(dataSet):
    C1 = []
    for transaction in dataSet:
        for item in transaction:
            if [item] not in C1:
                C1.append([item])
    C1.sort()
    return list(map(frozenset, C1))

# 计算并筛选Ck中的项集在数据集合D中的支持度
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

    # 计算满足最小支持度的项集的集合和所有项集支持度信息的字典
    numItems = len(D)
    retList = []
    supportData = {}
    for key in ssCnt:
        # 每个项集的支持度
        support = float(ssCnt[key]) / numItems

        # 将满足最小支持度的项集 加入retList
        if support >= minSupport:
            retList.append(key)

        # 汇总支持度数据
        supportData[key] = support

    return retList, supportData

# 由初始候选项集的集合Lk生成新的候选项集 k表示生成的新项集中所含有的元素个数
def aprioriGen(Lk, k):
    retList = []
    lenLk = len(Lk)
    for i in range(lenLk):
        for j in range(i + 1, lenLk):
            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

# Aprior算法
def apriori(dataSet, minSupport=0.5):
    # 构建初始候选项集C1
    C1 = createC1(dataSet)

    D = list(map(set, dataSet))

    # 构建初始的频繁项集 即所有项集只有一个元素
    L, suppData = scanD(D, C1, minSupport)

    L = [L]
    k = 2

    # 最初的L中的每个项集含有一个元素 新生成的项集每个项集应该依次多一个元素
    while (len(L) > k - 2):
        Ck = aprioriGen(L[k - 2], k)
        Lk, supK = scanD(D, Ck, minSupport)

        # 将新的项集的支持度数据加入原来的总支持度字典中
        suppData.update(supK)

        # 将符合最小支持度要求的项集加入L
        if len(Lk) > 0:
            L.append(Lk)

        # 新生成的项集中的元素个数应不断增加
        k += 1

    # 返回所有满足条件的频繁项集的列表,和所有候选项集的支持度信息
    return L, suppData


# 规则生成与评价
def calcConf(freqSet, H, supportData, brl, minConf=0.7):
    prunedH = []
    for conseq in H:
        conf = supportData[freqSet] / supportData[freqSet - conseq]
        if conf >= minConf:
            brl.append((freqSet - conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH

# 对频繁项集中元素超过2的项集进行合并
def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    m = len(H[0])
    # 查看频繁项集是否大到移除大小为m的子集
    if len(freqSet) > m + 1:
        # 生产大小大一的子集
        Hmp = aprioriGen(H, m + 1)

        # 如果不止一条规则满足要求 进一步递归合并
        Hmp = calcConf(freqSet, Hmp, supportData, brl, minConf)
        if len(Hmp) > 1:
            rulesFromConseq(freqSet, Hmp, supportData, brl, minConf)

# 根据频繁项集L和所有项集的支持度supportData和最小可信度来生成规则
def generateRules(L, supportData, minConf=0.7):
    bigRuleList = []
    for i in range(1, len(L)):
        for freqSet in L[i]:
            H = [frozenset([item]) for item in freqSet]

            # 如果频繁项集中的元素个数大于2 需要进一步合并
            if i > 1:
                rulesFromConseq(freqSet, H, supportData, bigRuleList, minConf)
            else:
                calcConf(freqSet, H, supportData, bigRuleList, minConf)

    return bigRuleList


def main():
    # 创建数据集
    def loadDataSet():
        return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]

    myData = loadDataSet()

    L, suppData = apriori(myData, 0.5)

    print('频繁项集:', L)

    print('所有候选项集的支持度信息:')
    for data in suppData:
        print(data, ' : ', suppData[data])

    rules = generateRules(L, suppData, 0.5)

    print('生成规则:')
    for rule in rules:
        print(rule[0], ' --> ', rule[1], ' : ', rule[2])

if __name__ == '__main__':
    exit(main())

输出结果:


频繁项集: [[frozenset({1}), frozenset({3}), frozenset({2}), frozenset({5})], [frozenset({1, 3}), frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5})], [frozenset({2, 3, 5})]]
所有候选项集的支持度信息:
frozenset({1})  :  0.5
frozenset({3})  :  0.75
frozenset({4})  :  0.25
frozenset({2})  :  0.75
frozenset({5})  :  0.75
frozenset({1, 3})  :  0.5
frozenset({2, 3})  :  0.5
frozenset({3, 5})  :  0.5
frozenset({2, 5})  :  0.75
frozenset({1, 2})  :  0.25
frozenset({1, 5})  :  0.25
frozenset({2, 3, 5})  :  0.5
生成规则:
frozenset({3})  -->  frozenset({1})  :  0.6666666666666666
frozenset({1})  -->  frozenset({3})  :  1.0
frozenset({3})  -->  frozenset({2})  :  0.6666666666666666
frozenset({2})  -->  frozenset({3})  :  0.6666666666666666
frozenset({5})  -->  frozenset({3})  :  0.6666666666666666
frozenset({3})  -->  frozenset({5})  :  0.6666666666666666
frozenset({5})  -->  frozenset({2})  :  1.0
frozenset({2})  -->  frozenset({5})  :  1.0
frozenset({5})  -->  frozenset({2, 3})  :  0.6666666666666666
frozenset({3})  -->  frozenset({2, 5})  :  0.6666666666666666
frozenset({2})  -->  frozenset({3, 5})  :  0.6666666666666666