1. 程式人生 > >第11章:使用Apriori演算法進行關聯分析(計算頻繁項集)

第11章:使用Apriori演算法進行關聯分析(計算頻繁項集)

目的:找到資料集中事務的關係,如超市中經常一起出現的物品集合,想找到支援度超過0.8的所有項集

概念:

頻繁項集:指經常出現在一起的物品集合;

關聯規則:指兩個物品之間可能存在很強的關係,如一個人買了什麼之後很大可能會買另一種東西;

支援度:資料集中包含該項集的記錄所佔的比例;保留滿足最小支援度的項集即為頻繁項集;

可信度:針對諸如{尿布}-{葡萄酒}這樣的關聯規則產生的,定義為支援度({尿布,葡萄酒})/支援度({尿布})

Apriori原理:

想找到支援度超過0.8的所有項集,一般做法是生成所有可能的組合,對每種組合統計其出現的頻繁程度,當物品較多時,做法很慢。Apriori幫助減少可能感興趣的項集數,原理是如果某個項集是頻繁的,則它的所有子集也是頻繁,但是反過來,如果一個項集是非頻繁的,則它的所有超集也是非頻繁的。因此該演算法從最簡單的一個元素開始,計算一個元素的支援度,如果支援度小於最小支援度,則去除該元素;然後將兩個元素結合,計算兩個元素的支援度,仍然小於最小支援度則去除,以此類推找到所有可能的大於最小支援度的元素組合。

程式碼:


def apriori(dataSet,minSupport=0.5):
    #建立單個元素列表
    C1=createC1(dataSet)

    #map必須轉化為list才能使用
    D=list(map(set,dataSet))

    #去除支援度小於最小支援度的單個元素,返回大於支援度的單個元素列表以及所有元素的支援度
    L1,supportData=scanD(D,C1,minSupport)

    #L是一個列表存放單個元素,兩個元素...的組合,L[0]單個元素組合,L[1]兩個元素組合,以此類推
    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
    return L,supportData

def createC1(dataset):
    C1=[]   #大小為1的所有候選項的集合
    for transaction in dataset:
        for item in transaction:
            if not [item] in C1:
                C1.append([item])
    C1.sort()
    return list(map(frozenset,C1))  #frozenset是個型別,表示使用者不能改變它


def scanD(D,CK,minSupport):
    ssCnt={}
    for tid in D:
        for can in CK:
            if can.issubset(tid):
                if not can in ssCnt:
                    ssCnt[can]=1
                else:
                    ssCnt[can]+=1
    #pdb.set_trace()
    numItems=float(len(D))
    retList=[]
    supportData={}
    for key in ssCnt:
        support=ssCnt[key]/numItems
        if support>=minSupport:
            retList.insert(0,key)   #在首位置插入key,retList代表大於最小支援度的元素
        supportData[key]=support  #supportData代表每個元素的支援度
    return retList,supportData

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