#-*- coding: utf-8 -*-
def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
#構建集合C1,C1是大小爲1的所有候選項集的集合
def createC1(dataSet):
C1 = [] #創建一個空列表,用來存儲所有不重複的項值
#遍歷數據集中的所有交易記錄,transaction依次爲數據集中的每條交易記錄,即每個項集,
# 如依次爲[1,3,4],[2,3,5],[1,2,3,5],[2,5]
for transaction in dataSet:
for item in transaction: #遍歷記錄中的每一個項,item是每條交易記錄中的物品,如項集[1,3,4]中的1,3,4
if not [item] in C1:#如果某個物品項沒有在C1中出現,則將其添加到C1中
#不是簡單地添加每個物品項,而是添加只包含該物品項的一個列表,
# 目的是爲每個物品構建一個集合,因爲後面要進行集合操作
C1.append([item])
C1.sort() #對大列表進行排序
#將列表中的每個單元素列表映射到frozenset(),最後返回frozenset的列表
#frozenset是指被冰凍的集合,就是它們是不可改變的,這裏必須使用frozenset而不是set類型,因爲之後
#必須要將這些集合作爲字典鍵值使用,使用frozenset可以實現,而set卻做不到
return map(frozenset, C1)
#數據集Ck,包含候選集合的列表D,感興趣項集的最小支持度minSupport
def scanD(D,Ck,minSupport):
ssCnt = {}
for tid in D:#遍歷數據集中的所有交易記錄
for can in Ck: #遍歷C1中的所有候選集
if can.issubset(tid): #如果C1中的集合是記錄的一部分,那麼增加字典中對應的計數值
if not ssCnt.has_key(can): ssCnt[can] = 1
else: ssCnt[can] += 1
numItems = float(len(D)) #numItems是數據集中交易記錄的條數
retList = []
supportData = {}
for key in ssCnt:
support = ssCnt[key] / numItems #計算支持度
if support >= minSupport:
retList.insert(0,key) #retList列表中包含了滿足最小支持度要求的集合,insert(0,key)表示在列表的首部插入新的集合
supportData[key] = support #以字典的形式將滿足最小支持度要求的集合和其支持度存儲在supportData
return retList, supportData
#*********************** Apriori算法 **********************
# 輸入參數爲頻繁項集列表Lk,k位輸出的合成的項集的元素個數,
# 如當k = 2時,輸出爲CK [frozenset([1, 3]), frozenset([1, 2]), frozenset([1, 5]), frozenset([2, 3]), frozenset([3, 5]), frozenset([2, 5])]
# 輸出中,每個項集都是兩個元素
def aprioriGen(Lk,k):
retList = [] #創建一個空列表
lenLk = len(Lk) #計算Lk中的元素數目
for i in range(lenLk):
for j in range(i+1, lenLk):
#從這步開始,就是取列表Lk中每個集合的前面k-2個元素進行比較,
# 如果相等,就將這兩個集合合爲一個大小爲k的集合
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) # 創建C1
D = map(set, dataSet) # 讀入數據集並將其轉化爲D(集合列表)
L1,supportData = scanD(D,C1,minSupport) # 利用scanD創建L1,
L = [L1] # 將L1放入列表L中,L會包含L1,L2, L3 ....通過下面的while循環依次放入,直到下一個大的項集爲空
k = 2
while(len(L[k-2]) > 0): # 代表直到下一個大的項集爲空時,停止循環
CK = aprioriGen(L[k-2], k) # 首先使用aprioriGen來創建Ck
# 使用scanD基於Ck來創建Lk,Ck是一個候選項集列表,然後scanD會遍歷Ck,丟掉不滿足最小支持度要求的項集
LK, supK = scanD(D, CK, minSupport)
supportData.update(supK)
L.append(LK) # Lk列表被添加到L中
k += 1 # 同時增加k的值
return L, supportData
#主函數
# 輸入參數爲頻繁項集列表,包含那些頻繁項集支持數據的字典,最小可信度閾值
# 函數輸出爲一個包含可信度的規則列表
def generateRules(L, supportData, minConf = 0.7):
bigRuleList = []
# 因爲無法從單元素項集中構建關聯規則,所以要從包含兩個或更多元素的項集開始構建
for i in range(1, len(L)): #只可獲取有兩個或更多元素的集合,所以i從1開始
for freqSet in L[i]:# 遍歷L中的每一個頻繁項集,並對每個頻繁項集創建只包含單個元素集合的列表H1
H1 = [frozenset([item]) for item in freqSet]
if (i > 1):
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf) # 如果i > 1,頻繁項集的元素數目超過2,則進一步合併
else:
calcConf( freqSet, H1, supportData, bigRuleList, minConf) # 當i=1時,頻繁項集的元素數目爲2,此時直接進行計算可信度
return bigRuleList
# 計算規則的可信度以找到滿足最小可信度要求的規則
def calcConf(freqSet, H, supportData, brl, minConf = 0.7):
prunedH = [] #創建一個空列表,用來保存符合最小可信度要求的規則列表
for conseq in H: #遍歷H中的所有項集
# 根據可信度的計算式:一條規則P--> H的可信度定義爲support(P | H) / support(P)
# 所有一個項集 conseq的可信度計算如下:
conf = supportData[freqSet] / supportData[freqSet - conseq] # 計算可信度
if conf >= minConf:
print freqSet-conseq, '-->',conseq,'conf:',conf # 如果滿足最小可信度,則將規則輸出到屏幕顯示
brl.append((freqSet - conseq, conseq, conf)) # 將通過檢查的規則保存在brl中,即是bigRuleList
prunedH.append(conseq) # 保存符合最小可信度要求的規則列表,並返回
return prunedH
# 輸入參數,freqSet是頻繁項集,H是可以出現在規則右部的元素列表
def rulesFromConseq(freqSet, H, supportData, brl, minConf = 0.7):
m = len(H[0]) # 計算H中的頻繁集大小爲m
if (len(freqSet) > (m+1)): #看該頻繁項集是否大到可以移除大小爲m的子集
Hmp1 = aprioriGen(H, m+1) # 生成H中元素的無重複組合,結果存儲在Hmp1中,這也是下一次迭代的H列表,Hmp1中包含所有的規則
Hmp1 = calcConf( freqSet, Hmp1, supportData, brl, minConf) # 測試Hmp1中的規則的可信度以確定規則是否滿足要求,返回一個符合最小可信度要求的規則列表
if (len(Hmp1) > 1): #如果不止一天規則滿足,那麼使用Hmp1迭代調用函數rulesFromConseq
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
dataSet = loadDataSet()
L, supportData = apriori(dataSet, 0.5)
rules = generateRules(L, supportData, minConf = 0.5)
print rules
使用Apriori算法進行關聯分析--代碼學習
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.