fp算法例题_机器学习(九)—FP-growth算法
本來老師是想讓我學(xué)Hadoop的,也裝了Ubuntu,配置了Hadoop,一時(shí)間卻不知從何學(xué)起,加之自己還是想先看點(diǎn)自己喜歡的算法,學(xué)習(xí)Hadoop也就暫且擱置了,不過還是想問一下園子里的朋友有什么學(xué)習(xí)Hadoop好點(diǎn)的資料,求推薦~言歸正傳,繼Apriori算法之后,今天來學(xué)習(xí)FP-growth算法。
和Apriori算法相比,FP-growth算法只需要對(duì)數(shù)據(jù)庫進(jìn)行兩次遍歷,從而高效發(fā)現(xiàn)頻繁項(xiàng)集。對(duì)于搜索引擎公司而言,他們需要通過查看互聯(lián)網(wǎng)上的用詞來找出經(jīng)常在一塊出現(xiàn)的詞對(duì),因此這些公司就需要能夠高效的發(fā)現(xiàn)頻繁項(xiàng)集的方法,今天要學(xué)習(xí)的FP-growth算法就可以完成此重任。
一 FP-growth算法
1.概述
FP-growth算法是基于Apriori原理的,通過將數(shù)據(jù)集存儲(chǔ)在FP(Frequent Pattern)樹上發(fā)現(xiàn)頻繁項(xiàng)集,但不能發(fā)現(xiàn)數(shù)據(jù)之間的關(guān)聯(lián)規(guī)則。FP-growth算法只需要對(duì)數(shù)據(jù)庫進(jìn)行兩次掃描,而Apriori算法在求每個(gè)潛在的頻繁項(xiàng)集時(shí)都需要掃描一次數(shù)據(jù)集,所以說Apriori算法是高效的。其中算法發(fā)現(xiàn)頻繁項(xiàng)集的過程是:
(1)構(gòu)建FP樹;
(2)從FP樹中挖掘頻繁項(xiàng)集。
2. 構(gòu)建FP樹
FP表示的是頻繁模式,其通過鏈接來連接相似元素,被連起來的元素可以看成是一個(gè)鏈表。將事務(wù)數(shù)據(jù)表中的各個(gè)事務(wù)對(duì)應(yīng)的數(shù)據(jù)項(xiàng)按照支持度排序后,把每個(gè)事務(wù)中的數(shù)據(jù)項(xiàng)按降序依次插入到一棵以 NULL為根節(jié)點(diǎn)的樹中,同時(shí)在每個(gè)結(jié)點(diǎn)處記錄該結(jié)點(diǎn)出現(xiàn)的支持度。
FP-growth算法的流程為:首先構(gòu)造FP樹,然后利用它來挖掘頻繁項(xiàng)集。在構(gòu)造FP樹時(shí),需要對(duì)數(shù)據(jù)集掃描兩邊,第一遍掃描用來統(tǒng)計(jì)頻率,第二遍掃描至考慮頻繁項(xiàng)集。下面舉例對(duì)FP樹加以說明。
假設(shè)存在的一個(gè)事務(wù)數(shù)據(jù)樣例為,構(gòu)建FP樹的步驟如下:
事務(wù)ID
事務(wù)中的元素
001
r,z,h,j,p
002
z,y,x,w,v,u,t,s
003
z
004
r,x,n,o,s
005
y,r,x,z,q,t,p
006
y,z,x,e,q,s,t,m
結(jié)合Apriori算法中最小支持度的閾值,在此將最小支持度定義為3,結(jié)合上表中的數(shù)據(jù),那些不滿足最小支持度要求的將不會(huì)出現(xiàn)在最后的FP樹中,據(jù)此構(gòu)建FP樹,并采用一個(gè)頭指針表來指向給定類型的第一個(gè)實(shí)例,快速訪問FP樹中的所有元素,構(gòu)建的帶頭指針的FP樹如下:
結(jié)合繪制的帶頭指針表的FP樹,對(duì)表中數(shù)據(jù)進(jìn)行過濾,排序如下:
事務(wù)ID
事務(wù)中的元素
過濾和重排序后的事務(wù)
001
r,z,h,j,p
z,r
002
z,y,x,w,v,u,t,s
z,x,y,s,t
003
z
z
004
r,x,n,o,s
x,s,r
005
y,r,x,z,q,t,p
z,x,y,r,t
006
y,z,x,e,q,s,t,m
z,x,y,s,t
在對(duì)數(shù)據(jù)項(xiàng)過濾排序了之后,就可以構(gòu)建FP樹了,從NULL開始,向其中不斷添加過濾排序后的頻繁項(xiàng)集。過程可表示為:
根據(jù)該思想就可以實(shí)現(xiàn)FP樹的構(gòu)建,下面就采用Python進(jìn)行實(shí)現(xiàn)。我們知道,在第二次掃描數(shù)據(jù)集時(shí)會(huì)構(gòu)建一棵FP樹,并采用一個(gè)容器來保存樹。首先創(chuàng)建一個(gè)類來保存樹的每一個(gè)節(jié)點(diǎn),代碼如下:
#coding:utf-8
from numpy import *
classtreeNode:def __init__(self, nameValue, numOccur, parentNode):
self.name=nameValue
self.count=numOccur
self.nodeLink=None
self.parent= parentNode #needs to be updated
self.children ={}definc(self,numOccur):
self.count+=numOccurdef disp(self,ind = 1):print ' '*ind,self.name,' ',self.countfor child inself.children.values():
child.disp(ind+1)'''#test
rootNode = treeNode('pyramid',9,None)
rootNode.children['eye'] = treeNode('eye',13,None)
a = rootNode.disp()
print a'''
這樣,FP樹對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)就建好了,現(xiàn)在就可以構(gòu)建FP樹了,FP樹的構(gòu)建函數(shù)如下:
#FP構(gòu)建函數(shù)
def createTree(dataSet,minSup = 1):
headerTable={}for trans indataSet:for item intrans:
headerTable[item]= headerTable.get(item,0) + dataSet[trans]#記錄每個(gè)元素項(xiàng)出現(xiàn)的頻度
for k inheaderTable.keys():if headerTable[k] freqItemSet=set(headerTable.keys())if len(freqItemSet) == 0:#不滿足最小值支持度要求的除去returnNone,Nonefor k inheaderTable:headerTable[k]=[headerTable[k],None]retTree= treeNode('Null Set',1,None)for tranSet,count indataSet.items():localD={}for item intranSet:if item infreqItemSet:localD[item]=headerTable[item][0]if len(localD) >0:orderedItems= [v[0] for v in sorted(localD.items(),key = lambda p:p[1],reverse =True)]updateTree(orderedItems,retTree,headerTable,count)returnretTree,headerTabledefupdateTree(items, inTree, headerTable, count):if items[0] ininTree.children:inTree.children[items[0]].inc(count)else:inTree.children[items[0]]=treeNode(items[0], count, inTree)if headerTable[items[0]][1] ==None:headerTable[items[0]][1] =inTree.children[items[0]]else:updateHeader(headerTable[items[0]][1], inTree.children[items[0]])if len(items) > 1:updateTree(items[1::], inTree.children[items[0]], headerTable, count)defupdateHeader(nodeToTest, targetNode):while (nodeToTest.nodeLink !=None):nodeToTest=nodeToTest.nodeLinknodeToTest.nodeLink= targetNode在運(yùn)行上例之前還需要一個(gè)真正的數(shù)據(jù)集,結(jié)合之前的數(shù)據(jù)自定義數(shù)據(jù)集:defloadSimpDat():simpDat= [['r', 'z', 'h', 'j', 'p'],['z', 'y', 'x', 'w', 'v', 'u', 't', 's'],['z'],['r', 'x', 'n', 'o', 's'],['y', 'r', 'x', 'z', 'q', 't', 'p'],['y', 'z', 'x', 'e', 'q', 's', 't', 'm']]returnsimpDatdefcreateInitSet(dataSet):retDict={}for trans indataSet:retDict[frozenset(trans)]= 1return retDict運(yùn)行:#testsimpDat =loadSimpDat()initSet=createInitSet(simpDat)myFPtree,myHeaderTab= createTree(initSet,3)a=myFPtree.disp()print a這樣就構(gòu)建了FP樹,接下來就是使用它來進(jìn)行頻繁項(xiàng)集的挖掘。3. 從FP樹中挖掘頻繁項(xiàng)集在構(gòu)建了FP樹之后,就可以抽取頻繁項(xiàng)集了,這里的思想和Apriori算法大致類似,首先從氮元素項(xiàng)集合開始,然后在此基礎(chǔ)上逐步構(gòu)建更大的集合。大致分為三個(gè)步驟:(1)從FP樹中獲得條件模式基;(2)利用條件模式基,構(gòu)建一個(gè)條件FP樹;(3)迭代重復(fù)(1)和(2),直到樹包含一個(gè)元素項(xiàng)為止。首先,獲取條件模式基。條件模式基是以所查找元素項(xiàng)為結(jié)尾的路徑集合,表示的是所查找的元素項(xiàng)與樹根節(jié)點(diǎn)之間的所有內(nèi)容。結(jié)合構(gòu)建FP樹繪制的圖,r的前綴路徑就是{x,s}、{z,x,y}和{z},其中的每條前綴路徑都與一個(gè)計(jì)數(shù)值有關(guān),該計(jì)數(shù)值表示的是每條路徑上r的數(shù)目。為了得到這些前綴路徑,結(jié)合之前所得到的頭指針表,頭指針表中包含相同類型元素鏈表的起始指針,根據(jù)每一個(gè)元素項(xiàng)都可以上溯到這棵樹直到根節(jié)點(diǎn)為止。該過程對(duì)應(yīng)的代碼如下:def ascendTree(leafNode, prefixPath): #ascends from leaf node to rootif leafNode.parent !=None:prefixPath.append(leafNode.name)ascendTree(leafNode.parent, prefixPath)def findPrefixPath(basePat, treeNode): #treeNode comes from header tablecondPats ={}while treeNode !=None:prefixPath=[]ascendTree(treeNode, prefixPath)if len(prefixPath) > 1:condPats[frozenset(prefixPath[1:])] =treeNode.counttreeNode=treeNode.nodeLinkreturncondPats#testsimpDat =loadSimpDat()initSet=createInitSet(simpDat)myFPtree,myHeaderTab= createTree(initSet,3)a=myFPtree.disp()b= findPrefixPath('x',myHeaderTab['x'][1])print b運(yùn)行代碼,與所給數(shù)據(jù)一致。接下來就可以創(chuàng)建條件FP樹了。對(duì)于每一個(gè)頻繁項(xiàng),都需要?jiǎng)?chuàng)建一棵條件FP樹,使用剛才創(chuàng)建的條件模式基作為輸入,采用相同的建樹代碼來構(gòu)建樹,相應(yīng)的遞歸發(fā)現(xiàn)頻繁項(xiàng)、發(fā)現(xiàn)條件模式基和另外的條件樹。對(duì)應(yīng)的遞歸查找頻繁項(xiàng)集的函數(shù)如下:defmineTree(inTree, headerTable, minSup, preFix, freqItemList):bigL= [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])]#(sort header table)for basePat inbigL:newFreqSet=preFix.copy()newFreqSet.add(basePat)freqItemList.append(newFreqSet)condPattBases= findPrefixPath(basePat, headerTable[basePat][1])myCondTree, myHead=createTree(condPattBases, minSup)if myHead !=None:mineTree(myCondTree, myHead, minSup, newFreqSet, freqItemList)結(jié)合之前的數(shù)據(jù)驗(yàn)證發(fā)現(xiàn)無誤。二 ?從新聞網(wǎng)站點(diǎn)擊流中挖掘上述在自定義的數(shù)據(jù)中隊(duì)算法進(jìn)行了驗(yàn)證,現(xiàn)在選取實(shí)際的數(shù)據(jù)進(jìn)行測(cè)試。在這個(gè)數(shù)據(jù)集合中,包含了100萬條記錄,文件中的每一行包含某個(gè)用戶瀏覽過的新聞報(bào)道,用來尋找那些至少被10萬人瀏覽過的報(bào)道。代碼如下:#從新聞網(wǎng)站點(diǎn)擊流中挖掘parsedData = [line.split() for line in open('kosarak.dat').readlines()]initSet=createInitSet(parsedData)myFPtree,myHeaderTab= createTree(initSet,100000)myFreqList=[]a= mineTree(myFPtree,myHeaderTab,100000,set([]),myFreqList)b=len(myFreqList)printbprint myFreqList這樣就實(shí)現(xiàn)了此功能。以上是我自己的總結(jié)和理解,難免有錯(cuò),還望各位朋友不吝賜教~
總結(jié)
以上是生活随笔為你收集整理的fp算法例题_机器学习(九)—FP-growth算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: csgo卡住关不掉_csgo退出卡住了
- 下一篇: java自定义标签遍历_自定义标签 -