本来老师是想让我学Hadoop的,也装了Ubuntu,配置了Hadoop,一时间却不知从何学起,加之自己还是想先看点自己喜欢的算法,学习Hadoop也就暂且搁置了,不过还是想问一下园子里的朋友有什么学习Hadoop好点的资料,求推荐~言归正传,继Apriori算法之后,今天来学习FP-growth算法。

  和Apriori算法相比,FP-growth算法只需要对数据库进行两次遍历,从而高效发现频繁项集。对于搜索引擎公司而言,他们需要通过查看互联网上的用词来找出经常在一块出现的词对,因此这些公司就需要能够高效的发现频繁项集的方法,今天要学习的FP-growth算法就可以完成此重任。

一 FP-growth算法                    

1.概述

  FP-growth算法是基于Apriori原理的,通过将数据集存储在FP(Frequent Pattern)树上发现频繁项集,但不能发现数据之间的关联规则。FP-growth算法只需要对数据库进行两次扫描,而Apriori算法在求每个潜在的频繁项集时都需要扫描一次数据集,所以说Apriori算法是高效的。其中算法发现频繁项集的过程是:

(1)构建FP树;

(2)从FP树中挖掘频繁项集。

2. 构建FP树

  FP表示的是频繁模式,其通过链接来连接相似元素,被连起来的元素可以看成是一个链表。将事务数据表中的各个事务对应的数据项按照支持度排序后,把每个事务中的数据项按降序依次插入到一棵以 NULL为根节点的树中,同时在每个结点处记录该结点出现的支持度。

  FP-growth算法的流程为:首先构造FP树,然后利用它来挖掘频繁项集。在构造FP树时,需要对数据集扫描两边,第一遍扫描用来统计频率,第二遍扫描至考虑频繁项集。下面举例对FP树加以说明。

  假设存在的一个事务数据样例为,构建FP树的步骤如下:

事务ID

事务中的元素

  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

  结合Apriori算法中最小支持度的阈值,在此将最小支持度定义为3,结合上表中的数据,那些不满足最小支持度要求的将不会出现在最后的FP树中,据此构建FP树,并采用一个头指针表来指向给定类型的第一个实例,快速访问FP树中的所有元素,构建的带头指针的FP树如下:

结合绘制的带头指针表的FP树,对表中数据进行过滤,排序如下:

事务ID 事务中的元素 过滤和重排序后的事务
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

在对数据项过滤排序了之后,就可以构建FP树了,从NULL开始,向其中不断添加过滤排序后的频繁项集。过程可表示为:

  根据该思想就可以实现FP树的构建,下面就采用Python进行实现。我们知道,在第二次扫描数据集时会构建一棵FP树,并采用一个容器来保存树。首先创建一个类来保存树的每一个节点,代码如下:

#coding:utf-8
from numpy import * class treeNode:
def __init__(self, nameValue, numOccur, parentNode):
self.name = nameValue
self.count = numOccur
self.nodeLink = None
self.parent = parentNode #needs to be updated
self.children = {} def inc(self,numOccur):
self.count += numOccur def disp(self,ind = 1):
print ' '*ind,self.name,' ',self.count
for child in self.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树对应的数据结构就建好了,现在就可以构建FP树了,FP树的构建函数如下:

#FP构建函数
def createTree(dataSet,minSup = 1):
headerTable = {}
for trans in dataSet:
for item in trans:
headerTable[item] = headerTable.get(item,0) + dataSet[trans]#记录每个元素项出现的频度
for k in headerTable.keys():
if headerTable[k] < minSup:
del(headerTable[k])
freqItemSet = set(headerTable.keys())
if len(freqItemSet) == 0:#不满足最小值支持度要求的除去
return None,None
for k in headerTable:
headerTable[k] = [headerTable[k],None]
retTree = treeNode('Null Set',1,None)
for tranSet,count in dataSet.items():
localD = {}
for item in tranSet:
if item in freqItemSet:
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)
return retTree,headerTable def updateTree(items, inTree, headerTable, count):
if items[0] in inTree.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) def updateHeader(nodeToTest, targetNode):
while (nodeToTest.nodeLink != None):
nodeToTest = nodeToTest.nodeLink
nodeToTest.nodeLink = targetNode

在运行上例之前还需要一个真正的数据集,结合之前的数据自定义数据集:

def loadSimpDat():
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']]
return simpDat def createInitSet(dataSet):
retDict = {}
for trans in dataSet:
retDict[frozenset(trans)] = 1
return retDict

运行:

#test
simpDat = loadSimpDat()
initSet = createInitSet(simpDat)
myFPtree,myHeaderTab = createTree(initSet,3)
a = myFPtree.disp()
print a

这样就构建了FP树,接下来就是使用它来进行频繁项集的挖掘。

3. 从FP树中挖掘频繁项集

  在构建了FP树之后,就可以抽取频繁项集了,这里的思想和Apriori算法大致类似,首先从氮元素项集合开始,然后在此基础上逐步构建更大的集合。大致分为三个步骤:

(1)从FP树中获得条件模式基;

(2)利用条件模式基,构建一个条件FP树;

(3)迭代重复(1)和(2),直到树包含一个元素项为止。

  首先,获取条件模式基。条件模式基是以所查找元素项为结尾的路径集合,表示的是所查找的元素项与树根节点之间的所有内容。结合构建FP树绘制的图,r的前缀路径就是{x,s}、{z,x,y}和{z},其中的每条前缀路径都与一个计数值有关,该计数值表示的是每条路径上r的数目。为了得到这些前缀路径,结合之前所得到的头指针表,头指针表中包含相同类型元素链表的起始指针,根据每一个元素项都可以上溯到这棵树直到根节点为止。该过程对应的代码如下:

def ascendTree(leafNode, prefixPath): #ascends from leaf node to root
if leafNode.parent != None:
prefixPath.append(leafNode.name)
ascendTree(leafNode.parent, prefixPath) def findPrefixPath(basePat, treeNode): #treeNode comes from header table
condPats = {}
while treeNode != None:
prefixPath = []
ascendTree(treeNode, prefixPath)
if len(prefixPath) > 1:
condPats[frozenset(prefixPath[1:])] = treeNode.count
treeNode = treeNode.nodeLink
return condPats #test
simpDat = loadSimpDat()
initSet = createInitSet(simpDat)
myFPtree,myHeaderTab = createTree(initSet,3)
a = myFPtree.disp()
b = findPrefixPath('x',myHeaderTab['x'][1])
print b

  运行代码,与所给数据一致。接下来就可以创建条件FP树了。对于每一个频繁项,都需要创建一棵条件FP树,使用刚才创建的条件模式基作为输入,采用相同的建树代码来构建树,相应的递归发现频繁项、发现条件模式基和另外的条件树。对应的递归查找频繁项集的函数如下:

def mineTree(inTree, headerTable, minSup, preFix, freqItemList):
bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])]#(sort header table)
for basePat in bigL:
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)

结合之前的数据验证发现无误。

二  从新闻网站点击流中挖掘

上述在自定义的数据中队算法进行了验证,现在选取实际的数据进行测试。在这个数据集合中,包含了100万条记录,文件中的每一行包含某个用户浏览过的新闻报道,用来寻找那些至少被10万人浏览过的报道。代码如下:

#从新闻网站点击流中挖掘
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)
print b
print myFreqList

这样就实现了此功能。

以上是我自己的总结和理解,难免有错,还望各位朋友不吝赐教~

机器学习(九)—FP-growth算法的更多相关文章

  1. 机器学习(十五)— Apriori算法、FP Growth算法

    1.Apriori算法 Apriori算法是常用的用于挖掘出数据关联规则的算法,它用来找出数据值中频繁出现的数据集合,找出这些集合的模式有助于我们做一些决策. Apriori算法采用了迭代的方法,先搜 ...

  2. Frequent Pattern 挖掘之二(FP Growth算法)(转)

    FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结 ...

  3. FP—Growth算法

    FP_growth算法是韩家炜老师在2000年提出的关联分析算法,该算法和Apriori算法最大的不同有两点: 第一,不产生候选集,第二,只需要两次遍历数据库,大大提高了效率,用31646条测试记录, ...

  4. 关联规则算法之FP growth算法

    FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结 ...

  5. Frequent Pattern (FP Growth算法)

    FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达 到这样的效果,它采用了一种简洁的数据 ...

  6. Frequent Pattern 挖掘之二(FP Growth算法)

    Frequent Pattern 挖掘之二(FP Growth算法) FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断 ...

  7. FP Tree算法原理总结

    在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题,FP Tree算法(也称F ...

  8. FP Tree算法原理总结(转载)

    FP Tree算法原理总结 在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题 ...

  9. FP - growth 发现频繁项集

    FP - growth是一种比Apriori更高效的发现频繁项集的方法.FP是frequent pattern的简称,即常在一块儿出现的元素项的集合的模型.通过将数据集存储在一个特定的FP树上,然后发 ...

  10. 机器学习六--K-means聚类算法

    机器学习六--K-means聚类算法 想想常见的分类算法有决策树.Logistic回归.SVM.贝叶斯等.分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别 ...

随机推荐

  1. 解锁CHM文件

    刚在网上下载了CHM格式的文件,打开之后,右侧部分一片空白. 原因:可能是,系统针对来源不明文件的一种保存措施吧 解决方法: 1.选中文件,右键打开属性对话框,在 “常规”选项卡中 勾选 [解除锁定] ...

  2. ActionScript和js交互

    新建的ActionScript项目,默认新建会在“默认包”中创建一个和项目名称相同以as结尾的文件,as项目开始执行时要new一个这样的类在类上方加入一些参数可以为生成的swf初始化一些样式 [SWF ...

  3. CAS单点登出的原理

    单点登出功能跟单点登录功能是相对应的,旨在通过Cas Server的登出使所有的Cas Client都登出. Cas Server的登出是通过请求“/logout”发生的,即如果你的Cas Serve ...

  4. Oracle数据库的删除

    在Windows中彻底删除原先的Oracle,然后再重新安装Oracle数据库.具体步骤如下:   1. 开始->设置->控制面板->管理工具->服务,停止所有Oracle服务 ...

  5. 饭卡管理系统学生E-R图

    - 2 - 1.1 可行性分析 1.1.1 项目背景 近年来学生食堂饭卡的使用给高校餐饮管理带来了一次革命, 从结算方式到账户管理, 从卫生便捷到数据统计等,不仅给就餐者带来了方便,也使餐饮结算手段发 ...

  6. jmeter-执行多个sql查询语句

    1.添加jdbc connection(注意标红部分) 2.添加jdbc request 3.查看结果树

  7. 使用ConcurrentLinkedQueue惨痛的教训

    服务端原本有个定时任务对一个集合ArrayList 中的消息做处理. 因为考虑到处理消息是先进先出原则,所以优化的时候考虑改用ConcurrentLinkedQueue 当时没仔细深入研究过这个集合就 ...

  8. crm开发(基于ssh)(五)

    1 信息查询 (1)多条件组合查询 -拼接hql语句 -使用离线对象 2 添加数据字典表 (1)改造添加客户功能 3 统计分析 (1)调用普通sql实现 (2)结果处理操作 4 使用ssh注解整合 ( ...

  9. JavaEE 技术体系

    JavaEE 技术体系总结: 一:常见模式与工具 设计模式,流行的框架与组件 常见的设计模式,编码必备 Spring5,做应用必不可少的最新框架 MyBatis,玩数据库必不可少的组件 二:工程化与工 ...

  10. Python Falling back to the 'python' engine because the 'c' engine does not support regex separators

    环境 Anaconda3 Python 3.6, Window 64bit 书籍 O'Reilly出版的Wes McKinney编的<Python for Data Analysis> 警 ...