机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则
生活随笔
收集整理的這篇文章主要介紹了
机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
#!/usr/bin/env python
# encoding: utf-8'''
<<機(jī)器學(xué)習(xí)實(shí)戰(zhàn)>> 讀書筆記 第11章 使用Apriori算法進(jìn)行關(guān)聯(lián)分析---從頻繁項(xiàng)集中挖掘關(guān)聯(lián)規(guī)則關(guān)鍵:
1 關(guān)聯(lián)規(guī)則
某個(gè)元素或者某個(gè)元素集合可能會(huì)推導(dǎo)出另一個(gè)元素
舉例: 如果有一個(gè)頻繁項(xiàng)集{豆奶,萵苣},那么就可能有一條關(guān)聯(lián)規(guī)則: 豆奶 --> 萵苣,這意味著如果有人購(gòu)買了豆奶,那么他購(gòu)買萵苣的概率較大。
關(guān)聯(lián)規(guī)則的量化指標(biāo): 可信度
一條規(guī)則P --> H的可信度定義為support(P | H) / support(P)
注意: Python中,操作符 | 表示集合的并操作
P|H: 是指所有出現(xiàn)在集合P或者集合H中的元素2 頻繁項(xiàng)集產(chǎn)生關(guān)聯(lián)規(guī)則
舉例: {0, 1, 2, 3}產(chǎn)生的規(guī)則列表如下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是一套低可信度規(guī)則,那么其他以3作為后件的規(guī)則的可信度也會(huì)較低
前件: 箭頭左邊的集合
后件: 箭頭右邊的集合如果某條規(guī)則并不滿足最小可信度要求-->那么該規(guī)則的所有子集也不會(huì)滿足最小可信度要求3 頻繁項(xiàng)集到關(guān)聯(lián)規(guī)則生成
算法思想:
從一個(gè)頻繁項(xiàng)集開始,創(chuàng)建一個(gè)規(guī)則列表,其中規(guī)則右部值包含一個(gè)元素,然后對(duì)這些規(guī)則進(jìn)行測(cè)試。
接下來合并所有剩余規(guī)則來創(chuàng)建一個(gè)新的規(guī)則列表,其中規(guī)則右部包含兩個(gè)元素。
這種方法被稱為分級(jí)法。4 從頻繁項(xiàng)集中挖掘關(guān)聯(lián)規(guī)則算法
步驟1: 遍歷頻繁項(xiàng)集列表中的每個(gè)頻繁項(xiàng)1.1 對(duì)該頻繁項(xiàng)中每個(gè)元素進(jìn)行遍歷,生成每個(gè)元素組成的frozenset得到的結(jié)果作為規(guī)則右部的候選元素列表H1.2 如果頻繁項(xiàng)集的元素?cái)?shù)目只有2個(gè),則計(jì)算該頻繁項(xiàng)集對(duì)應(yīng)規(guī)則右部的元素列表。否則,執(zhí)行1.31.3 表明當(dāng)前頻繁項(xiàng)集中元素?cái)?shù)目大于2個(gè),則判定如果當(dāng)前頻繁項(xiàng)集的長(zhǎng)度大于規(guī)則右部候選元素列表H中H[0]的長(zhǎng)度,則表明可以對(duì)規(guī)則右部候選元素列表生成H[0]長(zhǎng)度+1的規(guī)則右部候選元素列表canH,1.4 計(jì)算規(guī)則右部候選元素列表為canH時(shí),當(dāng)前頻繁項(xiàng)集對(duì)應(yīng)規(guī)則右部的元素列表realH1.5 如果當(dāng)前頻繁項(xiàng)集對(duì)應(yīng)規(guī)則右部的元素列表realH長(zhǎng)度大于1,則使用realH作為規(guī)則右部的候選元素列表遞歸處理,轉(zhuǎn)步驟1''''''
作用:
輸入?yún)?shù): 頻繁項(xiàng)集列表L,包含哪些頻繁項(xiàng)集支持?jǐn)?shù)據(jù)的字典supportData, 最小可信度閾值
返回結(jié)果: 返回包含可信度的規(guī)則列表
算法:
步驟1: 遍歷頻繁項(xiàng)集列表中的每個(gè)頻繁項(xiàng)1.1 對(duì)該頻繁項(xiàng)中每個(gè)元素進(jìn)行遍歷,生成每個(gè)元素組成的frozenset得到的結(jié)果作為規(guī)則右部的候選元素列表H1.2 如果頻繁項(xiàng)集的元素?cái)?shù)目只有2個(gè),則計(jì)算該頻繁項(xiàng)集對(duì)應(yīng)規(guī)則右部的元素列表。否則,執(zhí)行1.31.3 表明當(dāng)前頻繁項(xiàng)集中元素?cái)?shù)目大于2個(gè),則判定如果當(dāng)前頻繁項(xiàng)集的長(zhǎng)度大于規(guī)則右部候選元素列表H中H[0]的長(zhǎng)度,則表明可以對(duì)規(guī)則右部候選元素列表生成H[0]長(zhǎng)度+1的規(guī)則右部候選元素列表canH,1.4 計(jì)算規(guī)則右部候選元素列表為canH時(shí),當(dāng)前頻繁項(xiàng)集對(duì)應(yīng)規(guī)則右部的元素列表realH1.5 如果當(dāng)前頻繁項(xiàng)集對(duì)應(yīng)規(guī)則右部的元素列表realH長(zhǎng)度大于1,則使用realH作為規(guī)則右部的候選元素列表遞歸處理,轉(zhuǎn)步驟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'''
作用: 如果頻繁項(xiàng)集種玫瑰只有兩個(gè)元素,則可用函數(shù)calcConf來計(jì)算可信度
輸入?yún)?shù):頻繁項(xiàng)集freqSet,出現(xiàn)在規(guī)則右部的元素列表H,頻繁項(xiàng)集對(duì)應(yīng)的支持度信息的字典supportData,最小可信度minConf
輸出參數(shù):包含規(guī)則左部,規(guī)則右部,可信度的元組作為元素的列表ruleList
返回結(jié)果: 可以作為當(dāng)前頻繁項(xiàng)集對(duì)應(yīng)關(guān)聯(lián)規(guī)則右部的元素列表
算法:
步驟1: 創(chuàng)建一個(gè)空列表prunedH
步驟2: 遍歷H中所有項(xiàng)集并計(jì)算他們的可信度值2.1 如果某條規(guī)則滿足最小可信度值,那么將規(guī)則打印,并將規(guī)則加入到結(jié)果列表中
'''
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'''
作用: 如果頻繁項(xiàng)集的元素?cái)?shù)目超過2,會(huì)對(duì)它做進(jìn)一步合并
輸入?yún)?shù):頻繁項(xiàng)集freqSet,出現(xiàn)在規(guī)則右部的元素列表H,頻繁項(xiàng)集對(duì)應(yīng)的支持度信息的字典supportData,最小可信度minConf
輸出參數(shù):包含規(guī)則左部,規(guī)則右部,可信度的元組作為元素的列表ruleList
返回結(jié)果:
算法:
步驟1: 先計(jì)算H中的頻繁集大小m
步驟2: 查看該頻繁項(xiàng)集是否達(dá)到可以移除大小為m的子集。2.1 如果可以的話,將其移除。可以使用aprioriGen生成H中元素的無重復(fù)組合Hmp1Hmp1是下一次迭代的H列表 ,包含所有可能的規(guī)則2.2 計(jì)算該規(guī)則的可信度,看是否滿足要求;如果不止一條規(guī)則滿足要求,使用Hmp1遞歸調(diào)用rulesFromConseq來判斷是否可以進(jìn)一步組合這些規(guī)則'''
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)# 這意味著規(guī)則右部多于一條,就可以合并規(guī)則右部生成新的規(guī)則右部,繼續(xù)處理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] ]'''
作用: 創(chuàng)建大小為1的所有候選項(xiàng)集的集合
算法:
步驟1: 解析數(shù)組中每個(gè)元素
步驟2: 構(gòu)建每個(gè)元素組成的數(shù)組;2.1 如果該數(shù)組不在結(jié)果數(shù)組中,就放入到結(jié)果數(shù)組中;
步驟3: 對(duì)結(jié)果數(shù)組進(jìn)行排序,并轉(zhuǎn)換為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:凍結(jié)集合是因?yàn)?#xff0c;它們不可改變,需要將這些集合作為字典鍵值使用。'''return map(frozenset, result)'''
作用: 用于從C1生成L1。
輸入?yún)?shù): 數(shù)據(jù)集D, 候選項(xiàng)列表Ck, 感興趣項(xiàng)集的最小支持度minSupport
返回值: 返回一個(gè)包含支持度的字典
算法:
步驟1: 先創(chuàng)建一個(gè)空字典ssCnt
步驟2: 遍歷數(shù)據(jù)集中的所有交易記錄以及C1中的所有候選集。2.1 如果C1中的集合是記錄中的一部分,則增加字典中對(duì)應(yīng)的計(jì)數(shù)值。
步驟3: 構(gòu)建一個(gè)空列表作為滿足做小支持度的集合。
步驟4: 遍歷步驟1中的字典ssCnt中每個(gè)元素,計(jì)算其支持度。4.1 如果支持度滿足最小支持度要求,則將字典元素放到結(jié)果列表中4.2 更新頻繁項(xiàng)集的支持度字典
步驟5: 返回頻繁項(xiàng)集的結(jié)果列表,返回最頻繁項(xiàng)集的支持度總結(jié): 掃描算法其實(shí)就是兩個(gè)過程。
第一個(gè)過程就是根據(jù)候選項(xiàng)集找到包含候選項(xiàng)的超集,并統(tǒng)計(jì)該候選項(xiàng)集出現(xiàn)的次數(shù)
第二個(gè)過程就是根據(jù)候選項(xiàng)集的出現(xiàn)次數(shù),計(jì)算候選項(xiàng)的支持度,將滿足最小支持度的候選項(xiàng)加入到最終結(jié)果列表中。
'''
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'''
作用:
輸入?yún)?shù): 頻繁項(xiàng)集列表Lk, 項(xiàng)集元素個(gè)數(shù)k(是輸入的頻繁項(xiàng)集列表中任意元素的長(zhǎng)度值+1)
返回結(jié)果: 輸出Ck。
舉例: 該函數(shù)以{0}, {1},{2}作為輸入,會(huì)生成{0, 1}, {0, 2}和{1,2}
算法:
步驟1: 每次遍歷頻繁項(xiàng)集列表中任意兩個(gè)不同的頻繁項(xiàng)集
步驟2: 如果這兩個(gè)頻繁項(xiàng)集的前k-2是相同的,則將這兩個(gè)頻繁項(xiàng)集合并,并添加到結(jié)果列表中
'''
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'''
作用:
輸入?yún)?shù): 數(shù)據(jù)集dataSet(是一個(gè)列表, 列表中每個(gè)元素是列表); 最小支持度minSupport(浮點(diǎn)數(shù))
返回結(jié)果: 頻繁項(xiàng)集結(jié)果列表(該頻繁項(xiàng)集結(jié)果列表中的每個(gè)元素是一個(gè)列表,列表中的每個(gè)元素是frozenset類型的結(jié)果)每個(gè)頻繁項(xiàng)集對(duì)應(yīng)的支持度
算法:
步驟1: 獲取長(zhǎng)度為1的候選項(xiàng)列表C1,具體計(jì)算過程如下:1.1 遍歷數(shù)據(jù)集(實(shí)際是數(shù)組)中每個(gè)元素1.1.1 構(gòu)建每個(gè)元素組成的數(shù)組;1.1.2 如果該數(shù)組不在結(jié)果數(shù)組中,就放入到結(jié)果數(shù)組中;1.2 對(duì)結(jié)果數(shù)組進(jìn)行排序,并轉(zhuǎn)換為fronzenset并返回
步驟2: 根據(jù)C1,數(shù)據(jù)集和最小支持度計(jì)算出滿足最小支持度的頻繁項(xiàng)集L1,以及頻繁項(xiàng)集的支持度信息,具體從候選集計(jì)算得到頻繁集的過程如下:2.1: 先創(chuàng)建一個(gè)空字典ssCnt2.2: 遍歷數(shù)據(jù)集中的所有交易記錄以及C1中的所有候選集。2.2.1 如果C1中的集合是記錄中的一部分,則增加字典中對(duì)應(yīng)的計(jì)數(shù)值。2.3: 構(gòu)建一個(gè)空列表作為滿足做小支持度的集合。2.4: 遍歷步驟2.1中的字典ssCnt中每個(gè)元素,計(jì)算其支持度。2.4.1 如果支持度滿足最小支持度要求,則將字典元素放到結(jié)果列表中2.4.2 更新頻繁項(xiàng)集的支持度字典2.5: 返回頻繁項(xiàng)集的結(jié)果列表,返回頻繁項(xiàng)集的支持度信息
步驟3: 創(chuàng)建一個(gè)頻繁項(xiàng)集結(jié)果列表L,設(shè)定k=2
步驟4: 只要L[k-2]的長(zhǎng)度大于0,就進(jìn)入步驟5;否則,算法結(jié)束,返回頻繁項(xiàng)集列表L和頻繁項(xiàng)集對(duì)應(yīng)的支持度信息
步驟5:根據(jù)頻繁項(xiàng)集列表L[k-2]和所要求出的頻繁項(xiàng)集的長(zhǎng)度k,計(jì)算得到候選項(xiàng)集Ck,具體計(jì)算過程如下:5.1 每次遍歷頻繁項(xiàng)集列表中任意兩個(gè)不同的頻繁項(xiàng)集5.2 如果這兩個(gè)頻繁項(xiàng)集的前k-2是相同的,則將這兩個(gè)頻繁項(xiàng)集合并,并添加到結(jié)果列表中5.3 返回結(jié)果列表,即為Ck
步驟6: 根據(jù)Ck, 數(shù)據(jù)集和最小支持度計(jì)算出頻繁項(xiàng)集Lk和Lk頻繁項(xiàng)集的支持度信息,并更新總的頻繁項(xiàng)集的支持度信息
步驟7: 向頻繁項(xiàng)集總的結(jié)果列表L中加入當(dāng)前頻繁項(xiàng)集Lk, 并令k累加總結(jié):
根據(jù)候選集Ck,數(shù)據(jù)集,最小支持度 --> 頻繁集Lk
根據(jù)頻繁集Lk, 所要求出的頻繁項(xiàng)的長(zhǎng)度k+1 -> 候選集Ck+1
根據(jù)候選集Ck+1, 數(shù)據(jù)集,最小支持度 --> 頻繁集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 "頻繁項(xiàng)集支持度信息: {supportDict}".format(supportDict=supportDict)for i, arr in enumerate(L):print "頻繁項(xiàng)集長(zhǎng)度為{length}的頻繁項(xiàng)集如下: {arr} ".format(length=i+1, arr=arr)rules = generateRules(L, supportDict, minConf=0.7)print rulesif __name__ == "__main__":process()
?
總結(jié)
以上是生活随笔為你收集整理的机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MediaType和文件类型对应关系
- 下一篇: 积分公式和常用方法总结