基於python 的Apriori演算法,pythonApriori演算法
Apriori algorithm是關聯規則裡一項基本演算法。是由Rakesh Agrawal和Ramakrishnan Srikant兩位博士在1994年提出的關聯規則挖掘演算法。關聯規則的目的就是在一個資料集中找出項與項之間的關係,也被稱為購物藍分析 (Market Basket analysis),因為“購物藍分析”很貼切的表達了適用該演算法情景中的一個子集。
該演算法的具體思想可以參考這個網址瞭解:
Apriori演算法詳解
接下來,我向分享如何用代碼實現Apriori演算法,步驟如下:
1.建立apriori類
class Apriori: def __init__(self,min_sup=0.2,dataDic={}): self.data = dataDic ##構建資料記錄詞典,形如{'T800': ['I1', 'I2', 'I3', 'I5'],...} self.size = len(dataDic) #統計資料記錄的個數 self.min_sup = min_sup ##最小支援度的閾值 self.min_sup_val = min_sup * self.size ##最小支援度計數
2.過濾掉小於最小支援度閾值的物品
def find_frequent_1_itemsets(self): FreqDic = {} #{itemset1:freq1,itemsets2:freq2},用於統計物品的支援度計數 for event in self.data: ##event為每一條記錄,如T800 for item in self.data[event]: ##item就是I1,I2,I3,I4,I5 if item in FreqDic: FreqDic[item] += 1 else: FreqDic[item] = 1 L1 = [] for itemset in FreqDic: if FreqDic[itemset] >= self.min_sup_val: ##過濾掉小於最小支援度閾值的物品 L1.append([itemset]) return L1
3.過濾掉非頻繁項集
def has_infrequent_subset(self,c,L_last,k): ## c為當前集合,L_last為上一個頻繁項集的集合,k為當前頻繁項集內的元素個數, ## 該函數用於檢查當前集合的子集是否 都為頻繁項集 subsets = list(itertools.combinations(c,k-1)) #itertools是排列組合模組,目的就c分解,如[1,2,3]將分成[(1,2),(1,3),(2,3)] for each in subsets: each = list(each) #將元組轉化為列表 if each not in L_last: ##子集是否 都為頻繁項集 return True return False
補充說明:
itertools是排列組合模組,例如 list(itertools.combinations([1,2,3],2))就能分解成[(1,2),(1,3),(2,3)]
具體使用可以參考:http://www.jb51.net/article/34921.htm
4.合并形成新的頻繁項集
def apriori_gen(self,L_last): #L_last means frequent(k-1) itemsets k = len(L_last[0]) + 1 Ck = [] ## for itemset1 in L_last: for itemset2 in L_last: #join step flag = 0 for i in range(k-2): print k-2 if itemset1[i] != itemset2[i]: flag = 1 ##若前k-2項中如果有一個項是不相等,新合并的集合是不可能是頻繁項集 break; if flag == 1:continue if itemset1[k-2] < itemset2[k-2]: c = itemset1 + [itemset2[k-2]] else: continue #pruning setp if self.has_infrequen`t`_subset(c,L_last,k):##判斷子集是否為頻繁項集 continue else: Ck.append(c) return Ck
5.關聯分析迭代形成頻繁項集
def do(self): L_last = self.find_frequent_1_itemsets() ##過濾掉小於最小支援度閾值的物品 L = L_last i = 0 while L_last != []: Ck = self.apriori_gen(L_last) ##合并形成新的頻繁項集 FreqDic = {} for event in self.data: #get all suported subsets for c in Ck: ##統計新形成的頻繁項集的個數 if set(c) <= set(self.data[event]):#判斷新合成的頻繁項目是否為資料記錄的子集 if tuple(c) in FreqDic: FreqDic[tuple(c)]+=1 else: FreqDic[tuple(c)]=1 print FreqDic Lk = [] for c in FreqDic: print c print '------' if FreqDic[c] > self.min_sup_val:##判斷新形成的頻繁項集是否大於最小支援度的閾值 Lk.append(list(c)) L_last = Lk L += Lk return L ## L就是新形成的頻繁項集的集合
測試範例
Data = {'T100':['I1','I2','I5'],
'T200':['I2','I4'],
'T300':['I2','I3'],
'T400':['I1','I2','I4'],
'T500':['I1','I3'],
'T600':['I2','I3'],
'T700':['I1','I3'],
'T800':['I1','I2','I3','I5'],
'T900':['I1','I2','I3']}
完整代碼:
#! -*- coding:utf-8 -*-import itertoolsclass Apriori: def __init__(self,min_sup=0.2,dataDic={}): self.data = dataDic ##構建資料記錄詞典,形如{'T800': ['I1', 'I2', 'I3', 'I5'],...} self.size = len(dataDic) #統計資料記錄的個數 self.min_sup = min_sup ##最小支援度的閾值 self.min_sup_val = min_sup * self.size ##最小支援度計數 def find_frequent_1_itemsets(self): FreqDic = {} #{itemset1:freq1,itemsets2:freq2},用於統計物品的支援度計數 for event in self.data: ##event為每一條記錄,如T800 for item in self.data[event]: ##item就是I1,I2,I3,I4,I5 if item in FreqDic: FreqDic[item] += 1 else: FreqDic[item] = 1 L1 = [] for itemset in FreqDic: if FreqDic[itemset] >= self.min_sup_val: ##過濾掉小於最小支援度閾值的物品 L1.append([itemset]) return L1 def has_infrequent_subset(self,c,L_last,k): ## c為當前集合,L_last為上一個頻繁項集的集合,k為當前頻繁項集內的元素個數, ## 該函數用於檢查當前集合的子集是否 都為頻繁項集 subsets = list(itertools.combinations(c,k-1)) #itertools是排列組合模組,目的就c分解,如[1,2,3]將分成[(1,2),(1,3),(2,3)] for each in subsets: each = list(each) #將元組轉化為列表 if each not in L_last: ##子集是否 都為頻繁項集 return True return False def apriori_gen(self,L_last): #L_last means frequent(k-1) itemsets k = len(L_last[0]) + 1 Ck = [] ## for itemset1 in L_last: for itemset2 in L_last: #join step flag = 0 for i in range(k-2): print k-2 if itemset1[i] != itemset2[i]: flag = 1 ##若前k-2項中如果有一個項是不相等,新合并的集合是不可能是頻繁項集 break; if flag == 1:continue if itemset1[k-2] < itemset2[k-2]: c = itemset1 + [itemset2[k-2]] else: continue #pruning setp if self.has_infrequent_subset(c,L_last,k):##判斷子集是否為頻繁項集 continue else: Ck.append(c) return Ck def do(self): L_last = self.find_frequent_1_itemsets() ##過濾掉小於最小支援度閾值的物品 L = L_last i = 0 while L_last != []: Ck = self.apriori_gen(L_last) ##合并形成新的頻繁項集 FreqDic = {} for event in self.data: #get all suported subsets for c in Ck: ##統計新形成的頻繁項集的個數 if set(c) <= set(self.data[event]):#判斷新合成的頻繁項目是否為資料記錄的子集 if tuple(c) in FreqDic: FreqDic[tuple(c)]+=1 else: FreqDic[tuple(c)]=1 print FreqDic Lk = [] for c in FreqDic: print c print '------' if FreqDic[c] > self.min_sup_val:##判斷新形成的頻繁項集是否大於最小支援度的閾值 Lk.append(list(c)) L_last = Lk L += Lk return L ## L就是新形成的頻繁項集的集合#******Test******Data = {'T100':['I1','I2','I5'], 'T200':['I2','I4'], 'T300':['I2','I3'], 'T400':['I1','I2','I4'], 'T500':['I1','I3'], 'T600':['I2','I3'], 'T700':['I1','I3'], 'T800':['I1','I2','I3','I5'], 'T900':['I1','I2','I3']}a=Apriori(dataDic=Data)# print a.do()a.do()
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。