Apriori算法-頻繁項集-關聯規則


 

計算頻繁項集:

首先生成一個數據集

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


測試數據集dataset有了,第一步,我們要根據數據集dataset得到一個集合C1,集合C1中包含的元素為dataset的無重復的每個單元素,候選項集。
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)
返回的數據map計算得到一個元素為frozenset的集合。
為什么要轉成frozenset?

原因兩個:
 
 
 
         1.  
 
 
 
         這個集合是從dataset中抽取出所有無重復的數據集,是固定的,應該是不可變的類型。
 
 
 
         2.  
 
 
 
         frozenset可以作字典
可以看一下返回結果:

第二步,計算C1<key>每個元素key的支持度。
       支持度= count(key) / sizeof(C1)
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))  # 數據集長度
   
retList = []
    supportData = {}
   
for key in ssCnt:
        support = ssCnt[key] / numitems
       
if support >= minSupport:
            retList.insert(
0, key)
        supportData[key] = support
   
return retList, supportData
調用返回結果:

先把dataset轉成元素為集合的類型。
這里設置支持度為0.5。當keydataset中出現的集合個數超過一半即認為是頻繁項。
L1是根據計算C1中每個元素是否滿足支持度規則過濾得到的C1的子集。
L1的元素兩兩組合構成C2,再根據C2中每個元素是否滿足支持度規則過濾得到的C1的子集L2。依次類推,直到Lk是單元素集合。
添加如下代碼,可以得到一個完整的找頻繁項集的代碼:


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
def apriori(dataset, minsupport=0.5):
    C1 = createC1(dataset) 
# 候選項集
   
D = map(set, dataset)  # 數據集
   
L1, supportData = scanD(D, 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
   
return L, supportData

apriori是主函數,這里對Lk進行了合並,如果Lk的兩個元素(都是集合,假設分別是Lk1,Lk2)的[0:k-2]是一樣的,(k是什么?kLk1的長度加1)比方說:
example1:
{a},{c} k=2    
[0:k-2]分別是{}=={},需要進行合並。得到{a,c}
注意:[0:0]意思是從0開始取(含0),直到0(不含0),所以是{}
example2:
{a,c},{a,d}   k=3
[0:k-2]分別是{a}=={a},合並得到{a,c,d}
注意:[0:1]意思是從0開始取(含0),直到1(不含1),所以是{a}
應該能理解怎么合並的了。
 
為什么要合並?
上面解釋了怎么合並,以及合並的規則。我們拿到的數據是由C1生成的L1L1是單元素中符合支持度的構成的集合。所以我們只需要對L1進行組合,就能得到二元素集合C2,並根據支持度過濾得到其中符合支持度的二元素的頻繁項集L2。由L1得到C2,這就是為什么要合並的理由。
 
為什么用這種合並規則呢?
L1={[frozenset([1]), frozenset([3]),
        frozenset([2]), frozenset([5])]}
很明顯,我們可以組合得到
Ck[k=2]={[frozenset([1, 3]), frozenset([1, 2]), frozenset([1, 5]), frozenset([2, 3]), frozenset([3, 5]), frozenset([2, 5])]}
scanD(D, Ck, minsupport)執行該函數得到我們想要的
Lk[k=2]= {[frozenset([1, 3]), frozenset([2, 5]), frozenset([2, 3]), frozenset([3, 5])]}
接着看:
接下來我們就要對Lk[k=2]進行組合了。按照我們的規則:
[1,3]沒有與之可以合並的。
[2,5][2,3]可以合並。得到[2,3,5]
[3,5]沒有與之合並的。
所以Ck[k=3]={[frozenset([2, 3, 5])]}
假如我們不按照該規則來:
[1,3][2,5]=>[1,2,3,5],三元素集合這點規則是必須要遵守的。
[1,3][2,3]=>[1,2,3]出現[1,2]該子集不滿足支持度。
[1,3][3,5]=>[1,3,5]出現[1,5]該子集不滿足支持度。
[2,5][2,3]=>[2,3,5]
[2,5][3,5]=>[2,3,5]
[2,3][3,5]=>[2,3,5]出現三個重復的[2,3,5],還需要我們添加去重規則,相對比較麻煩。而且按照我們的規則,可以減少集合的數目,省去遍歷去重的過程,降低算法的時間復雜度。
根據規則生成的Ck,是建立在不違背最小支持度的基礎之上的,至於生成的Ck是否符合最小支持度,接下來要使用scanD算法來進行驗證,並丟掉不符合最小支持度的項集。
有一個問題:
k-2的操作,到底是怎么做到的,避免出現類似[1,2,3]這種含有[1,2]子集是之前已經被拋棄的集合。還是說,這里就是一個巧合?。
 
挖掘關聯規則:

1.  下面是關聯規則   默認最小置信度為0.7  

2.  主函數  

3.  def generateRules(L, supportData, minConf=0.7):  

4.      bigRuleList = []  

5.      for i in range(1, len(L)):  不處理單元素集合L[0]  

6.          for freqSet in L[i]:  

7.              H1 = [frozenset([item]) for item in freqSet]  

8.              if (i > 1):  當集合中元素的長度大於2的時候,嘗試對集合合並。  

9.                  比如:[2,3,5]=>{[2,3],5}  

10.                 ŒrulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)  

11.             else:  對於2元組,直接計算置信度  

12.                 calConf(freqSet, H1, supportData, bigRuleList, minConf)  

13.     return bigRuleList  

14.   

15.   

16. def calConf(freqSet, H, supportData, brl, minConf=0.7):  

17.     prunedH = []  

18.     for conseq in H:  

19.         conf = supportData[freqSet] / supportData[freqSet - conseq]  置信度  

20.         if conf >= minConf:  

21.             print freqSet - conseq, "--->", conseq, "conf", conf  

22.             brl.append((freqSet - conseq, conseq, conf))  

23.             prunedH.append(conseq)  

24.         if (len(freqSet) > 2):  

25.             conf = supportData[freqSet] / supportData[conseq]  置信度  

26.             if conf >= minConf:  

27.                 print conseq, "--->", freqSet - conseq, "conf", conf  

28.                 brl.append((conseq, freqSet - conseq, conf))  

29.                 prunedH.append(freqSet - conseq)  

30.     return prunedH  

31.   

32.   

33. def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):  

34.     m = len(H[0])  

35.     if (len(freqSet) > (m + 1)):  

36.         Hmp1 = aprioriGen(H, m + 1)  

37.         Hmp1 = calConf(freqSet, Hmp1, supportData, brl, minConf)  

38.         if (len(Hmp1) > 1):  

39.             rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)  

40.   

41.   

42. ruleList = generateRules(L, supportData)  

43. # print ruleList  

rulesFromConseq解釋一下:
在主函數generateRules中的Œ標記處,此時freqSet是三元組[2,3,5],嘗試對其元素進行合並。調用rulesFromConseq,執行aprioriGen(H, m + 1)得到Hmp1={[frozenset([2, 3]), frozenset([2, 5]),
               frozenset([3, 5])]}
然后調用calConf計算置信度。
 
這里對calConf補充了如下代碼:

1.          if (len(freqSet) > 2):  

2.              conf = supportData[freqSet] / supportData[conseq]  置信度  

3.              if conf >= minConf:  

4.                  print conseq, "--->", freqSet - conseq, "conf", conf  

5.                  brl.append((conseq, freqSet - conseq, conf))  

6.                  prunedH.append(freqSet - conseq)  

理由:原代碼,如果freqSet =[2,3,5] H={[frozenset([2, 3]), frozenset([2, 5]), frozenset([3, 5])]}
[2,3,5]去計算對[2][3][5]的置信度均不符合最小要求,返回[],無法繼續對[2,3][2,5][3,5]進行置信度驗證。
 
源代碼:https://files.cnblogs.com/files/simuhunluo/Apriori%E7%AE%97%E6%B3%95%E4%BB%A3%E7%A0%81.zip


免責聲明!

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



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