机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则
生活随笔
收集整理的這篇文章主要介紹了
机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#!/usr/bin/env python
# encoding: utf-8'''
<<機器學習實戰>> 讀書筆記 第11章 使用Apriori算法進行關聯分析---從頻繁項集中挖掘關聯規則關鍵:
1 關聯規則
某個元素或者某個元素集合可能會推導出另一個元素
舉例: 如果有一個頻繁項集{豆奶,萵苣},那么就可能有一條關聯規則: 豆奶 --> 萵苣,這意味著如果有人購買了豆奶,那么他購買萵苣的概率較大。
關聯規則的量化指標: 可信度
一條規則P --> H的可信度定義為support(P | H) / support(P)
注意: Python中,操作符 | 表示集合的并操作
P|H: 是指所有出現在集合P或者集合H中的元素2 頻繁項集產生關聯規則
舉例: {0, 1, 2, 3}產生的規則列表如下0123->空123->0 023->1 013->2 012->323->01 13->02 12->03 03->12 02->13 01->233->012 2->013 1->023 0->123如果: 0,1,2->3是一套低可信度規則,那么其他以3作為后件的規則的可信度也會較低
前件: 箭頭左邊的集合
后件: 箭頭右邊的集合如果某條規則并不滿足最小可信度要求-->那么該規則的所有子集也不會滿足最小可信度要求3 頻繁項集到關聯規則生成
算法思想:
從一個頻繁項集開始,創建一個規則列表,其中規則右部值包含一個元素,然后對這些規則進行測試。
接下來合并所有剩余規則來創建一個新的規則列表,其中規則右部包含兩個元素。
這種方法被稱為分級法。4 從頻繁項集中挖掘關聯規則算法
步驟1: 遍歷頻繁項集列表中的每個頻繁項1.1 對該頻繁項中每個元素進行遍歷,生成每個元素組成的frozenset得到的結果作為規則右部的候選元素列表H1.2 如果頻繁項集的元素數目只有2個,則計算該頻繁項集對應規則右部的元素列表。否則,執行1.31.3 表明當前頻繁項集中元素數目大于2個,則判定如果當前頻繁項集的長度大于規則右部候選元素列表H中H[0]的長度,則表明可以對規則右部候選元素列表生成H[0]長度+1的規則右部候選元素列表canH,1.4 計算規則右部候選元素列表為canH時,當前頻繁項集對應規則右部的元素列表realH1.5 如果當前頻繁項集對應規則右部的元素列表realH長度大于1,則使用realH作為規則右部的候選元素列表遞歸處理,轉步驟1''''''
作用:
輸入參數: 頻繁項集列表L,包含哪些頻繁項集支持數據的字典supportData, 最小可信度閾值
返回結果: 返回包含可信度的規則列表
算法:
步驟1: 遍歷頻繁項集列表中的每個頻繁項1.1 對該頻繁項中每個元素進行遍歷,生成每個元素組成的frozenset得到的結果作為規則右部的候選元素列表H1.2 如果頻繁項集的元素數目只有2個,則計算該頻繁項集對應規則右部的元素列表。否則,執行1.31.3 表明當前頻繁項集中元素數目大于2個,則判定如果當前頻繁項集的長度大于規則右部候選元素列表H中H[0]的長度,則表明可以對規則右部候選元素列表生成H[0]長度+1的規則右部候選元素列表canH,1.4 計算規則右部候選元素列表為canH時,當前頻繁項集對應規則右部的元素列表realH1.5 如果當前頻繁項集對應規則右部的元素列表realH長度大于1,則使用realH作為規則右部的候選元素列表遞歸處理,轉步驟1
'''
def generateRules(L, supportData, minConf=0.7):ruleList = []for i in range(1, len(L)):for freqSet in L[i]:candidateH = [frozenset([value]) for value in freqSet]if i > 1:rulesFromConseq(freqSet, candidateH, supportData, ruleList, minConf)else:calcConf(freqSet, candidateH, supportData, ruleList, minConf)return ruleList'''
作用: 如果頻繁項集種玫瑰只有兩個元素,則可用函數calcConf來計算可信度
輸入參數:頻繁項集freqSet,出現在規則右部的元素列表H,頻繁項集對應的支持度信息的字典supportData,最小可信度minConf
輸出參數:包含規則左部,規則右部,可信度的元組作為元素的列表ruleList
返回結果: 可以作為當前頻繁項集對應關聯規則右部的元素列表
算法:
步驟1: 創建一個空列表prunedH
步驟2: 遍歷H中所有項集并計算他們的可信度值2.1 如果某條規則滿足最小可信度值,那么將規則打印,并將規則加入到結果列表中
'''
def calcConf(freqSet, H, supportData, ruleList, minConf=0.7):if not freqSet:print "freqSet is empty"returnprunedH = list()for consequence in H:conf = supportData[freqSet] / supportData[freqSet - consequence]if conf >= minConf:print "{left}->{right}, conf: {conf}".format(left=freqSet - consequence,right=consequence,conf=conf)ruleList.append((freqSet - consequence, consequence, conf))prunedH.append(consequence)return prunedH'''
作用: 如果頻繁項集的元素數目超過2,會對它做進一步合并
輸入參數:頻繁項集freqSet,出現在規則右部的元素列表H,頻繁項集對應的支持度信息的字典supportData,最小可信度minConf
輸出參數:包含規則左部,規則右部,可信度的元組作為元素的列表ruleList
返回結果:
算法:
步驟1: 先計算H中的頻繁集大小m
步驟2: 查看該頻繁項集是否達到可以移除大小為m的子集。2.1 如果可以的話,將其移除。可以使用aprioriGen生成H中元素的無重復組合Hmp1Hmp1是下一次迭代的H列表 ,包含所有可能的規則2.2 計算該規則的可信度,看是否滿足要求;如果不止一條規則滿足要求,使用Hmp1遞歸調用rulesFromConseq來判斷是否可以進一步組合這些規則'''
def rulesFromConseq(freqSet, H, supportData, ruleList, minConf=0.7):hLen = len(H[0])fLen = len(freqSet)if fLen > hLen + 1:candidateHList = aprioriGen(H, hLen + 1)realHList = calcConf(freqSet, candidateHList, supportData, ruleList, minConf)# 這意味著規則右部多于一條,就可以合并規則右部生成新的規則右部,繼續處理if len(realHList) > 1:rulesFromConseq(freqSet, realHList, supportData, ruleList, minConf)def loadDataSet():return [ [1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5] ]'''
作用: 創建大小為1的所有候選項集的集合
算法:
步驟1: 解析數組中每個元素
步驟2: 構建每個元素組成的數組;2.1 如果該數組不在結果數組中,就放入到結果數組中;
步驟3: 對結果數組進行排序,并轉換為fronzenset并返回
'''
def createC1(dataSet):if not dataSet:return frozenset()result = []for arr in dataSet:for value in arr:if [value] not in result:result.append([value])result.sort()'''之所以使用frozenset:凍結集合是因為,它們不可改變,需要將這些集合作為字典鍵值使用。'''return map(frozenset, result)'''
作用: 用于從C1生成L1。
輸入參數: 數據集D, 候選項列表Ck, 感興趣項集的最小支持度minSupport
返回值: 返回一個包含支持度的字典
算法:
步驟1: 先創建一個空字典ssCnt
步驟2: 遍歷數據集中的所有交易記錄以及C1中的所有候選集。2.1 如果C1中的集合是記錄中的一部分,則增加字典中對應的計數值。
步驟3: 構建一個空列表作為滿足做小支持度的集合。
步驟4: 遍歷步驟1中的字典ssCnt中每個元素,計算其支持度。4.1 如果支持度滿足最小支持度要求,則將字典元素放到結果列表中4.2 更新頻繁項集的支持度字典
步驟5: 返回頻繁項集的結果列表,返回最頻繁項集的支持度總結: 掃描算法其實就是兩個過程。
第一個過程就是根據候選項集找到包含候選項的超集,并統計該候選項集出現的次數
第二個過程就是根據候選項集的出現次數,計算候選項的支持度,將滿足最小支持度的候選項加入到最終結果列表中。
'''
def scanD(D, Ck, minSupport):if not D or not Ck:print "D is empty or Ck is empty, D is: {D} , Ck is: {Ck}".format(D=D, Ck=Ck)canToTimes = {}for tid in D:for can in Ck:if can.issubset(tid):if canToTimes.has_key(can):canToTimes[can] += 1else:canToTimes[can] = 1result = []canToSupport = {}length = len(D)for can, times in canToTimes.iteritems():support = float(times) / lengthif support >= minSupport:result.insert(0, can)canToSupport[can] = supportreturn result, canToSupport'''
作用:
輸入參數: 頻繁項集列表Lk, 項集元素個數k(是輸入的頻繁項集列表中任意元素的長度值+1)
返回結果: 輸出Ck。
舉例: 該函數以{0}, {1},{2}作為輸入,會生成{0, 1}, {0, 2}和{1,2}
算法:
步驟1: 每次遍歷頻繁項集列表中任意兩個不同的頻繁項集
步驟2: 如果這兩個頻繁項集的前k-2是相同的,則將這兩個頻繁項集合并,并添加到結果列表中
'''
def aprioriGen(Lk, k):if not Lk or k < 2:print "Lk is empty or k < 2, Lk: {Lk}, k: {k}".format(Lk=Lk, k=k)returnlength = len(Lk)results = []for i in range(length):for j in range(i + 1, length):list1 = list(Lk[i])[: k - 2]list2 = list(Lk[j])[: k - 2]list1.sort()list2.sort()if list1 == list2:result = Lk[i] | Lk[j]results.append(result)return results'''
作用:
輸入參數: 數據集dataSet(是一個列表, 列表中每個元素是列表); 最小支持度minSupport(浮點數)
返回結果: 頻繁項集結果列表(該頻繁項集結果列表中的每個元素是一個列表,列表中的每個元素是frozenset類型的結果)每個頻繁項集對應的支持度
算法:
步驟1: 獲取長度為1的候選項列表C1,具體計算過程如下:1.1 遍歷數據集(實際是數組)中每個元素1.1.1 構建每個元素組成的數組;1.1.2 如果該數組不在結果數組中,就放入到結果數組中;1.2 對結果數組進行排序,并轉換為fronzenset并返回
步驟2: 根據C1,數據集和最小支持度計算出滿足最小支持度的頻繁項集L1,以及頻繁項集的支持度信息,具體從候選集計算得到頻繁集的過程如下:2.1: 先創建一個空字典ssCnt2.2: 遍歷數據集中的所有交易記錄以及C1中的所有候選集。2.2.1 如果C1中的集合是記錄中的一部分,則增加字典中對應的計數值。2.3: 構建一個空列表作為滿足做小支持度的集合。2.4: 遍歷步驟2.1中的字典ssCnt中每個元素,計算其支持度。2.4.1 如果支持度滿足最小支持度要求,則將字典元素放到結果列表中2.4.2 更新頻繁項集的支持度字典2.5: 返回頻繁項集的結果列表,返回頻繁項集的支持度信息
步驟3: 創建一個頻繁項集結果列表L,設定k=2
步驟4: 只要L[k-2]的長度大于0,就進入步驟5;否則,算法結束,返回頻繁項集列表L和頻繁項集對應的支持度信息
步驟5:根據頻繁項集列表L[k-2]和所要求出的頻繁項集的長度k,計算得到候選項集Ck,具體計算過程如下:5.1 每次遍歷頻繁項集列表中任意兩個不同的頻繁項集5.2 如果這兩個頻繁項集的前k-2是相同的,則將這兩個頻繁項集合并,并添加到結果列表中5.3 返回結果列表,即為Ck
步驟6: 根據Ck, 數據集和最小支持度計算出頻繁項集Lk和Lk頻繁項集的支持度信息,并更新總的頻繁項集的支持度信息
步驟7: 向頻繁項集總的結果列表L中加入當前頻繁項集Lk, 并令k累加總結:
根據候選集Ck,數據集,最小支持度 --> 頻繁集Lk
根據頻繁集Lk, 所要求出的頻繁項的長度k+1 -> 候選集Ck+1
根據候選集Ck+1, 數據集,最小支持度 --> 頻繁集Lk+1
...'''
def apriori(dataSet, minSupport=0.5):C1 = createC1(dataSet)D = map(set, dataSet)L1, supportDict = scanD(D, C1, minSupport)L = [L1]k = 2while len(L[k - 2]) > 0:Ck = aprioriGen(L[k-2], k)Lk, partialSupportDict = scanD(D, Ck, minSupport)supportDict.update(partialSupportDict)# note, Lk may be empty, if Lk is empty, it needs to end this recycleif not Lk:breakL.append(Lk)k += 1return L, supportDictdef process():dataSet = loadDataSet()L, supportDict = apriori(dataSet)print "頻繁項集支持度信息: {supportDict}".format(supportDict=supportDict)for i, arr in enumerate(L):print "頻繁項集長度為{length}的頻繁項集如下: {arr} ".format(length=i+1, arr=arr)rules = generateRules(L, supportDict, minConf=0.7)print rulesif __name__ == "__main__":process()
?
總結
以上是生活随笔為你收集整理的机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MediaType和文件类型对应关系
- 下一篇: 积分公式和常用方法总结