數據關聯分析 association analysis (Aprior算法,python代碼)


1基本概念

購物籃事務(market basket transaction),如下表,表中每一行對應一個事務,包含唯一標識TID,和購買的商品集合。本文介紹一種成為關聯分析(association analysis)的方法,這種方法,可以從下表可以提取出,{尿布}—>牛奶.

clip_image002

兩個關鍵問題:1大型數據計算量很大。2發現的某種模式可能是虛假,偶然發生的。

2問題定義

把數據可以轉換為如下表的二元表示,非二元不在本文討論范圍

clip_image004

項集

clip_image006

項集的支持度計數:

clip_image008

關聯規則:

clip_image010

我們要發現,滿足最小支持度與最小置信度的規則。

l 頻繁項集(frequent itemset):發現滿足最小支持度閾值的所有項集,這些項集成為頻繁項集。

l 規則的產生:從上一步發現的頻繁項集中提取所有高置信度的規則,這些規則成為強規則(strong rule)

頻繁項集的產生

窮舉法:

利用格結構(lattice structure)產生所有候選項集(candidate itemset).

clip_image012

利用窮舉法,計算每個候選項集的支持度計數。但是該方法計算量太大。

clip_image014

先驗(apriori)原理:

如果一個項集是頻繁的,則的所有子集一定是頻繁的。若某項集是非頻繁的,則其所有的超級也一定是非頻繁的。

如下圖,若{c,d,e}是頻繁項集,則它的子集一定是頻繁項集。

clip_image016

項集{a,b}是非頻繁的,則其所有的超級也一定是非頻繁的,如下圖。

clip_image018

Aprior算法的頻繁項集產生

clip_image020

1. 確定每個1-項集的支持度計數,刪除不滿足最小支持度的1-項集。(步驟1,2)

2. 迭代:使用頻繁(k-1)項集,產生新的候選k項集(步驟5)

3. 為了對候選k項集計算支持度計數,再次掃描數據(6-10)

4. 刪去支持度小於最小支持度(minsup)的候選集

5. 當Fk=NULL,結束。

6. 候選集是所有頻繁i項集的交際。i=1,2…

clip_image022

clip_image024方法:產生clip_image026(頻繁k-項集)。(step5)

函數aprior-gen的候選產生過程,合並一對頻繁k-1項集,僅當他們前k-2個項都相同時,即

clip_image028

圖例:clip_image030

Python代碼:

def aprioriGen(Lk,k):#create ck(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:#比較i,j前k-1個項若相同,和合並它倆
                retList.append(Lk[i] | Lk[j])#加入新的k項集 | stanf for union
    return retList
支持度計數:算法(6-12)代碼

Python代碼:

def scanD(D,ck,minSupport):#dataset,a list of candidate set,最小支持率
    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
    
    numItem=float(len(D))
    retList=[]
    supportData={}
    for key in ssCnt:
        support=ssCnt[key]/numItem
        if support>=minSupport:
            retList.insert(0,key)
            supportData[key]=support
            
    return retList,supportData#返回頻繁k項集,相應支持度

頻繁項集的產生:

def apriori(dataSet,minSupport=0.5):
    C1=createC1(dataSet)
    D=map(set,dataSet)
    L1,supportData=scanD(D,C1,minSupport)#利用k項集生成頻繁k項集(即滿足最小支持率的k項集)
    L=[L1]#L保存所有頻繁項集
    
    k=2
    while(len(L[k-2])>0):#直到頻繁k-1項集為空
        Ck=aprioriGen(L[k-2],k)#利用頻繁k-1項集 生成k項集
        Lk,supK= scanD(D,Ck,minSupport)
        supportData.update(supK)#保存新的頻繁項集與其支持度
        L.append(Lk)#保存頻繁k項集
        k+=1
    return L,supportData#返回所有頻繁項集,與其相應的支持率

規則產生(mining rules)

定理:

clip_image002

例如下:若bcd ->a是低置信度的,則它的子代都是低置信度的。利用此定理可以避免不必要的計算,減少運算復雜度。

clip_image004[4]

算法流程如下:clip_image006[4]clip_image008[4]

 

python代碼:

def calcConf(freqSet,H,supportData,brl,minConf=0.7):
    prunedH=[]
    for conseq in H:#后件中的每個元素
        conf=supportData[freqSet]/supportData[freqSet-conseq]
        if conf>=minConf:
            print freqSet-conseq,'-->',conseq,'conf:',conf
            brl.append((freqSet-conseq,conseq,conf))#添加入規則集中
            prunedH.append(conseq)#添加入被修剪過的H中
        
    return prunedH

def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.7):
     
    m=len(H[0])#H是一系列后件長度相同的規則,所以取H0的長度即可
    if (len(freqSet)>m+1):
        Hmp1=aprioriGen(H,m+1)
        Hmp1=calcConf(freqSet,Hmp1,supportData,brl,minConf)
        if (len(Hmp1)>1):
            rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)
            
def generateRules(L,supportData,minConf=0.7):
    import pdb
    pdb.set_trace()
    bigRuleList=[]#存儲規則
    for i in range(1,len(L)):
        for freqSet in L[i]:
            H1=[frozenset([item]) for item in freqSet]
            if(i>1):
                rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf)
            else:
                calcConf(freqSet,H1,supportData,bigRuleList,minConf)
    return bigRuleList

 

 

 

整個prior算法的python代碼

算法函數:

# -*- coding: utf-8 -*-
"""
Created on Wed Dec 04 22:25:57 2013

@author: Administrator
"""

def loadDataSet():
    return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]

def createC1(dataSet):#產生單個item的集合
    C1=[]
    for transaction in dataSet:
        for item in transaction: 
            if not [item] in C1:
                C1.append([item])
    
    C1.sort()
    
    return map(frozenset,C1)#給C1.list每個元素執行函數
    
    
def scanD(D,ck,minSupport):#dataset,a list of candidate set,最小支持率
    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
    
    numItem=float(len(D))
    retList=[]
    supportData={}
    for key in ssCnt:
        support=ssCnt[key]/numItem
        if support>=minSupport:
            retList.insert(0,key)
            supportData[key]=support
            
    return retList,supportData#返回頻繁k項集,相應支持度
        

def aprioriGen(Lk,k):#create ck(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:#比較i,j前k-1個項若相同,和合並它倆
                retList.append(Lk[i] | Lk[j])#加入新的k項集 | stanf for union
    return retList
    
    
def apriori(dataSet,minSupport=0.5):
    C1=createC1(dataSet)
    D=map(set,dataSet)
    L1,supportData=scanD(D,C1,minSupport)#利用k項集生成頻繁k項集(即滿足最小支持率的k項集)
    L=[L1]#L保存所有頻繁項集
    
    k=2
    while(len(L[k-2])>0):#直到頻繁k-1項集為空
        Ck=aprioriGen(L[k-2],k)#利用頻繁k-1項集 生成k項集
        Lk,supK= scanD(D,Ck,minSupport)
        supportData.update(supK)#保存新的頻繁項集與其支持度
        L.append(Lk)#保存頻繁k項集
        k+=1
    return L,supportData#返回所有頻繁項集,與其相應的支持率
        
    
def calcConf(freqSet,H,supportData,brl,minConf=0.7):
    prunedH=[]
    for conseq in H:#后件中的每個元素
        conf=supportData[freqSet]/supportData[freqSet-conseq]
        if conf>=minConf:
            print freqSet-conseq,'-->',conseq,'conf:',conf
            brl.append((freqSet-conseq,conseq,conf))#添加入規則集中
            prunedH.append(conseq)#添加入被修剪過的H中
        
    return prunedH

def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.7):
     
    m=len(H[0])#H是一系列后件長度相同的規則,所以取H0的長度即可
    if (len(freqSet)>m+1):
        Hmp1=aprioriGen(H,m+1)
        Hmp1=calcConf(freqSet,Hmp1,supportData,brl,minConf)
        if (len(Hmp1)>1):
            rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)
            
def generateRules(L,supportData,minConf=0.7):
  
    bigRuleList=[]#存儲規則
    for i in range(1,len(L)):
        for freqSet in L[i]:
            H1=[frozenset([item]) for item in freqSet]
            if(i>1):
                rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf)
            else:
                calcConf(freqSet,H1,supportData,bigRuleList,minConf)
    return bigRuleList

 

測試代碼:

import apriori
dataSet=apriori.loadDataSet()

C1=apriori.createC1(dataSet)

D=map(set,dataSet)
L1,suppData0=apriori.scanD(D,C1,0.5)

L,suppData=apriori.apriori(dataSet)

print L
rules=apriori.generateRules(L,suppData,minConf=0.5)

 

 

參數文獻:

1數據挖掘導論

2machine learning in action


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM