You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.5 KiB

8.3 动手实现Apriori

想要从数据中挖掘出关联规则,就需要先能够寻找频繁项集,所以首先我们可以实现一些用于寻找频繁项集的函数。

频繁项集来源于项集,所以首先需要构建只有一个元素的项集,再构建只有两个元素的项集,...,一直到有 K 个元素的项集。因此首先需要构建只有一个元素的项集,构建的函数实现如下:

# 构建只有一个元素的项集, 假设dataSet为[[1, 2], [0, 1]. [3, 4]]
# 那么该项集为frozenset({0}), frozenset({1}), frozenset({2}),frozenset({3}), frozenset({4})
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)

有了从无到有之后,接下来需要从 1 到 K。不过需要注意的是这个时候需要排除掉支持度小于最小支持度的项集。代码实现如下


# 从只有k个元素的项集生成有k+1个元素的频繁项集排除掉支持度小于最小支持度的项集
# D为数据集ck为createC1的输出minsupport为最小支持度
def scanD(D, ck, minsupport):
    ssCnt = {}
    for tid in D:
        for can in ck:
            if can.issubset(tid):
                if not ssCnt.has_key(can): 
                    ssCnt[can]=1
                else:
                    ssCnt[can] +=1
    numItems = float(len(D))
    reList = []
    supportData = {}
    for key in ssCnt:
        support = ssCnt[key]/numItems
        if support >= minsupoort:
            reList.insert(0, key)
        supportData[key] = support
    #reList为有k+1个元素的频繁项集supportData为频繁项集对应的支持度
    return reList, supportData

这就完了吗?还没有,我们还需要一个能够实现构建含有 K 个元素的频繁项集的函数。实现代码如下:

#构建含有k个元素的频繁项集
#如输入为{0},{1},{2}会生成{0,1},{0, 2},{1,2}
def aprioriGen(Lk, k):
    retList = []
    lenLk = len(LK)
    for i in range(lenLk):
        for j in range(i+1lenKk):
            L1 = list(Lk[i])[k:-2]
            L2 = list(Lk[j])[:k-2]
            if L1 == L2:
                relist.append(Lk[i] | Lk[j])
    return reList

有了以上的函数之后,我们就可以根据生成候选频繁项集的流程,使用这些函数来实现这个功能了。代码如下:

#生成候选的频繁项集列表,以及候选频繁项集的支持度,因为在算可信度时要用到
def apriori(dataSet, minsupport=0.5):
    C1 = creatC1(dataSet)
    D = map(set, dataSet)
    L1, supportData = scanD(dataSet, 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
    # L为候选频繁项集列表supportData为候选频繁项集的支持度
    return L, supportData

有了候选频繁项集和它的支持度之后,就可以开始着手挖掘关联规则了。在挖掘关联规则时,需要排除可信度比较小的关联规则,所以首先需要实现计算关联规则的可信度的功能。代码实现如下:

# 计算关联规则的可信度,并排除可信度小于最小可信度的关联规则
# freqSet为频繁项集H为规则右边可能出现的元素的集合supportData为频繁项集的支持度brl为存放关联规则的列表minConf为最小可信度
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

接下来就需要实现从频繁项集中生成关联规则的功能了,若已经忘记了算法流程,可以翻看一下上一节的内容,实现如下:

# 从频繁项集中生成关联规则
# freqSet为频繁项集H为规则右边可能出现的元素的集合supportData为频繁项集的支持度brl为存放关联规则的列表minConf为最小可信度
def ruleFromConseq(freqSet, H, supportData, brl, minConf = 0.7):
    m = len(H[0])
    if len(freqSet) > m+1:
        Hmp1 = aprioriGen(H, m+1)
        Hmp1 = calcConf(freqSet, Hmp1, supporData, brl, minConf)
        if len(Hmp1) > 1:
            ruleFromConseq(freqSet, Hmp1, supportData, brl, minConf)

由于使用apriori函数后得到的是一个候选频繁项集的列表,所以需要遍历整个候选频繁项集的列表来挖掘关联规则,所以代码实现如下:

# 从频繁项集中挖掘关联规则
# L为频繁项集 supportData为频繁项集的支持度minConf为最小可信度
def generateRules(L, supportData, minConf = 0.7):
    digRuleList = []
    for i in range(1, len(L)):
        # freqSet为含有i个元素的频繁项集
        for freqSet in L[i]:
            H1 = [frozenset([item]) for item in freqSet]
            if i > 1:
                # H1为关联规则右边的元素的集合
                rulesFromConseq(freqSet, H1, supportData, digRuleList, minConf)
            else:
                calcConf(freqSet, H1, supportData, digRuleList, minConf)
    return digRuleList

# 挖掘关联规则部分 End

到这里,我们已经实现了Apriori算法和关联规则挖掘算法。接下来,将介绍如何使用刚刚实现的算法来挖掘毒蘑菇的共性特征。