机器学习实战(9) 使用Apriori算法进行关联分析

使用Apriori算法来发现频繁集

支持度:某一项集的记录在数据集所占的比例
可信度:某一项集包含的细分项集的比例
如何找到支持度大于0.8的所有项集?
首先自建一个简单的数据集,构建两个辅助函数,createc1函数用来构建不变集合,scand函数扫描数据集,计算出现频数和支持度。

def loaddata():
    return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
def createc1(dataset):
    c1 = []
    for tran in dataset:
        for item in tran:
            if not [item] in c1:
                c1.append([item])
    c1.sort()
    #print(c1)
    return list(map(frozenset,c1))#返回frozenset的列表
def scand(D,Ck,sup):
    cnt={}
    for tid in D:
        for can in Ck:
            if can.issubset(tid):#issubset()判断can是否是tid的子集
                if not can in cnt: cnt[can]=1
                else: cnt[can] += 1
    numitems = float(len(D))
    retlist = []
    supdata = {}
    for key,value in cnt.items():
        support = value/numitems
        if support>=sup:
            retlist.insert(0,key)
        supdata[key]=support
    return retlist,supdata

接下来组建完整的Apriori算法,这里包含主函数apriori和辅助函数genc,genc输入Ck-1和k,生成集合的组合Ck,这里采用的一个比较神奇的方式,比较集合的前k-2个元素,如果相等,那么就将这两个集合求并集。这里我们举个例子来看下假如Ck-1集合的元素为{0,1},{0,2},{1,2},我们要创建三元素项集,这里k=3,取前k-2个元素也就是只取第一个元素0是相同的,那么我们对前俩个取并集,获得{0,1,2},这样就不需要遍历列表寻找非重复值。

def genc(Lk,k):#create Ck Lk=Lk-1
    retlist = []
    lenlk = len(Lk)
    for i in range(lenlk):
        for j in range(i+1,lenlk):
            L1=list(Lk[i])[:k-2]# start from k=2 L1=[] k=3 L1= [one element]
            L2=list(Lk[j])[:k-2]#  if the first just(k-2) is same, then | 
            L1.sort()
            L2.sort()
            if L1==L2:
                retlist.append(Lk[i] | Lk[j])
    return retlist
def apriori(data,minsup=0.5):
    C1 = createc1(data)
    D = list(map(set,data))
    L1,supdata = scand(D,C1,minsup)
    L = [L1]# a list that L[0] = L1
    k=2
    while (len(L[k-2])>0):#while Ck=[] break
        Ck = genc(L[k-2],k)#L is list of Lk
        print(Ck)
        Lk,supK = scand(D,Ck,minsup)
        supdata.update(supK)# put dict supK into supdata
        L.append(Lk)
        print(L)
        k +=1
        print(k)
    return L,supdata

关联规则生成

关联规则生成函数
从一个频繁项开始,首先创建规则右部只有一个元素的规则列表进行测试,接下来合并所有剩余规则来创建一个新的规则列表,规则右部包含两个元素。
这里基本重点代码处都写了注释,就不在一一列举了,按照例子来理解会更容易些,genru生成规则函数在i大于1时会调用ruconseq函数,i等于调用calcconf函数,而i的值关系到L[i]中的元素个数,L[1]的元素个数为2

def genru(L,supdata,minconf=0.7):
    rulist = []
    for i in range(1,len(L)):
        for freqset in L[i]:# for exam:freqset=frozenset({2, 5})
            H1 = [frozenset([item]) for item in freqset]
            print(H1)
            if (i>1):# more than two element
                ruconseq(freqset,H1,supdata,rulist,minconf)
            else:
                calcconf(freqset,H1,supdata,rulist,minconf)#freqset=frozenset({2, 3, 5})
    return rulist
def calcconf(freqset,H,supdata,br1,minconf=0.7):#for exam:freqset=frozenset({2, 5}) H=[frozenset({2}),frozenset({5})]
    pru=[]
    for conseq in H:
        conf = supdata[freqset]/supdata[freqset-conseq]#frozenset({2, 5})/frozenset({2, 5})-H[0] or frozenset({2, 5})-H[1]
        if conf >= minconf:
            print(freqset-conseq,'--->',conseq,'conf',conf)#frozenset({2, 5})-frozenset({2})--->frozenset({2})
            br1.append((freqset-conseq,conseq,conf))# record the revelance
            pru.append(conseq)
    return pru# for judge to stop cycle
def ruconseq(freqset,H,supdata,br1,minconf=0.7):
    m = len(H[0])#H = [frozenset({2}),frozenset({3}),frozenset({5})]
    if len(freqset) > (m+1):
        hmp1 = genc(H,m+1)
        hmp1 = calcconf(freqset,hmp1,supdata,br1,minconf)
        if len(hmp1) > 1:#cycle when hmp1 is [] break 
            ruconseq(freqset,hmp1,supdata,br1,minconf)

未完待续…

猜你喜欢

转载自blog.csdn.net/weixin_40548136/article/details/86769516