机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集

关键字:FPgrowth、频繁项集、条件FP树、非监督学习
作者:米仓山下
时间:2018-11-3
机器学习实战(Machine Learning in Action,@author: Peter Harrington)
源码下载地址:https://www.manning.com/books/machine-learning-in-action
git@github.com:pbharrin/machinelearninginaction.git

*************************************************************
一、使用FPgrowth算法来高效发现频繁项集

FPgrowth算法原理:
基于Apriori构建,但在完成相同任务时,采用了一些不同的的技术。这里的任务是将数据集存储在一个特定的称为FP树的结构之后发现频繁项集或则频繁项对,即在一块出现的的元素项的集合FP树。这种做法的执行速度要快于Apriori,通常性能要好两个数量级以上。
FP——Frequent pattern(频繁模式)

*************************************************************
二、FPgrowth算法——构建FP树

FP树构建函数
----------------------------------------------------------------------------
输入:dataSet——待挖掘数据集;minSup——最小支持度,默认为1
输出:retTree——构建的FP树; headerTable——头指针表

def createTree(dataSet, minSup=1): #create FP-tree from dataset but don't mine
headerTable = {} #扫描两次数据集dataSet
for trans in dataSet:#第一次扫描,统计所有元素出现的频次
for item in trans:
headerTable[item] = headerTable.get(item, 0) + dataSet[trans]
for k in headerTable.keys(): #移除不符合minSup的items
if headerTable[k] < minSup:
del(headerTable[k])
freqItemSet = set(headerTable.keys())
#print 'freqItemSet: ',freqItemSet
if len(freqItemSet) == 0: return None, None #没有items符合minSup,返回None退出
for k in headerTable:
headerTable[k] = [headerTable[k], None] #结构化headerTable
#print 'headerTable: ',headerTable
retTree = treeNode('Null Set', 1, None) #创建FP树根节点
for tranSet, count in dataSet.items(): #第二次扫描,构建FP树retTree
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) #更新FP树retTree
return retTree, headerTable #返回FP树retTree,头指针表headerTable

注:createTree足够灵活,下面构建条件FP树时还要用到

#更新FP树retTree
def updateTree(items, inTree, headerTable, count):
if items[0] in inTree.children: #如果第一个元素orderedItems[0]在子节点中
inTree.children[items[0]].inc(count) #增加计数
else: #不存在,增加子节点
inTree.children[items[0]] = treeNode(items[0], count, inTree)
if headerTable[items[0]][1] == None: #头指针表中items没有指向节点
headerTable[items[0]][1] = inTree.children[items[0]]
else: #头指针表中items以指向某个相似节点,追加到后面
updateHeader(headerTable[items[0]][1], inTree.children[items[0]])
if len(items) > 1: #items不止一个元素,去掉第一个元素,递归调用updateTree构建树
updateTree(items[1::], inTree.children[items[0]], headerTable, count)

----------------------------------------------------------------------------
测试:

>>> import fpGrowth
>>> simpdata=fpGrowth.loadSimpDat()
>>> initset=fpGrowth.createInitSet(simpdata)
>>> simpdata
[['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']]
>>> initset
{frozenset(['e', 'm', 'q', 's', 't', 'y', 'x', 'z']): 1, frozenset(['x', 's', 'r', 'o', 'n']): 1, frozenset(['s', 'u', 't', 'w', 'v', 'y', 'x', 'z']): 1, frozenset(['q', 'p', 'r', 't', 'y', 'x', 'z']): 1, frozenset(['h', 'r', 'z', 'p', 'j']): 1, frozenset(['z']): 1}
>>> minSup = 3
>>> myFPtree, myHeaderTab = fpGrowth.createTree(initset, minSup)
>>> myFPtree.disp()
Null Set 1
x 1
s 1
r 1
z 5
x 3
y 3
s 2
t 2
r 1
t 1
r 1
>>> myHeaderTab
{'s': [3, <fpGrowth.treeNode instance at 0x00000000039FE608>], 'r': [3, <fpGrowth.treeNode instance at 0x00000000039FE788>], 't': [3, <fpGrowth.treeNode instance at 0x00000000039FE688>], 'y': [3, <fpGrowth.treeNode instance at 0x00000000039FE5C8>], 'x': [4, <fpGrowth.treeNode instance at 0x00000000039FE588>], 'z': [5, <fpGrowth.treeNode instance at 0x00000000039FE548>]}
>>>

*************************************************************
三、从一棵FP树种挖掘频繁项集

#递归查找频繁项:mineTree函数
----------------------------------------------------------------------------

#输入:inTree——输入FP树,递归调用时为此时的元素preFix条件FP树;headerTable——头指针表;minSup——最小支持数;preFix——初始化为set([]),递归调用时为条件FP树inTree对应的元素;freqItemList——初始化为[],用来存储频繁项集。
#输出:freqItemList——用来存储频繁项集
def mineTree(inTree, headerTable, minSup, preFix, freqItemList):
bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])] #头指针表排序
for basePat in bigL: #从头指针表bigL(headerTable)底端开始遍历(从小到大)
newFreqSet = preFix.copy()
newFreqSet.add(basePat) #递归前,newFreqSet为单元素频繁项;递归时preFix不为空,开始组合
freqItemList.append(newFreqSet) #将每个频繁项加入到列表freqItemList中
condPattBases = findPrefixPath(basePat,\ #抽取条件模式基condPattBases,去掉了元素本身
headerTable[basePat][1])
myCondTree, myHead = createTree(condPattBases,\ #根据条件模式基condPattBases构建条件频繁树myCondTree
minSup)
if myHead != None: #挖掘FP条件树
#print 'conditional tree for: ',newFreqSet
#myCondTree.disp(1)
mineTree(myCondTree, myHead, minSup, \ #newFreqSet不为空set([]),递归调用mineTree函数
newFreqSet, freqItemList)

----------------------------------------------------------------------------
将源码中下面两行取消注释:
#print 'conditional tree for: ',newFreqSet
#myCondTree.disp(1)      #打印条件树

测试:

>>> myFreqList = []
>>> reload(fpGrowth)
<module 'fpGrowth' from 'fpGrowth.py'> #遍历头指针表myHeaderTab,将其单元素频繁项加入myFreqList后,再找出每个元素的条件FP树。递归调用组合频繁项
>>> fpGrowth.mineTree(myFPtree, myHeaderTab, minSup, set([]), myFreqList)
conditional tree for: set(['y'])
Null Set 1
x 3
z 3
conditional tree for: set(['y', 'z'])
Null Set 1
x 3
conditional tree for: set(['s'])
Null Set 1
x 3
conditional tree for: set(['t'])
Null Set 1
y 3
x 3
z 3
conditional tree for: set(['x', 't'])
Null Set 1
y 3
conditional tree for: set(['z', 't'])
Null Set 1
y 3
x 3
conditional tree for: set(['x', 'z', 't'])
Null Set 1
y 3
conditional tree for: set(['x'])
Null Set 1
z 3
>>> myFreqList
[set(['y']), set(['y', 'z']), set(['y', 'x', 'z']), set(['y', 'x']), set(['s']), set(['x', 's']), set(['t']), set(['z', 't']), set(['x', 'z', 't']), set(['y', 'x', 'z', 't']), set(['y', 'z', 't']), set(['x', 't']), set(['y', 'x', 't']), set(['y', 't']), set(['r']), set(['x']), set(['x', 'z']), set(['z'])]
>>> len(myFreqList)
18
>>>

*************************************************************
四、示例:从新闻网站点击流中挖掘
kosarak.dat中有将近100万条记录,每一行包含了某个用户浏览过得新闻报道。有些用户只看过一篇,有的用户看过2498篇报道。用户和报道编码成整数,利用FPgrowth算法

#读取数据,数据集格式化

>>> parsedDat=[line.split() for line in open('kosarak.dat').readlines()]
>>> len(parsedDat)
990002
>>> initset=fpGrowth.createInitSet(parsedDat) #构建FP树,寻找阅读量10+的新闻报道
>>> myFPtree, myHeaderTab = fpGrowth.createTree(initset, 100000) #创建条件FP树
>>> myFreqList = []
>>> fpGrowth.mineTree(myFPtree, myHeaderTab, 100000, set([]), myFreqList)
>>> len(myFreqList)
9
>>> myFreqList
[set(['']), set(['', '']), set(['']), set(['', '']), set(['', '', '']), set(['', '']), set(['']), set(['', '']), set([''])]
>>>

----------------------------------------------------------------------------
总结:

优点:FPgrowth算法相比Apriori只需要对数据库进行两次扫描,能够显著加快频繁项集发现速度
缺点:该算法能够更高效的发现频繁项集,但不能用于发现关联规则
应用:搜索引擎推荐词(经常在一块出现的词对)等

机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集的更多相关文章

  1. 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...

  2. 【机器学习实战】第12章 使用FP-growth算法来高效发现频繁项集

    第12章 使用FP-growth算法来高效发现频繁项集 前言 在 第11章 时我们已经介绍了用 Apriori 算法发现 频繁项集 与 关联规则.本章将继续关注发现 频繁项集 这一任务,并使用 FP- ...

  3. 【机器学习实战】第12章 使用 FP-growth 算法来高效发现频繁项集

    第12章 使用FP-growth算法来高效发现频繁项集 前言 在 第11章 时我们已经介绍了用 Apriori 算法发现 频繁项集 与 关联规则.本章将继续关注发现 频繁项集 这一任务,并使用 FP- ...

  4. 机器学习实战 [Machine learning in action]

    内容简介 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中萃取有价值的信息或模式,成为各行业求生存.谋发展的决定性手段,这使得这一过去为分析师和数学家所专属 ...

  5. 学习笔记之机器学习实战 (Machine Learning in Action)

    机器学习实战 (豆瓣) https://book.douban.com/subject/24703171/ 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中 ...

  6. K近邻 Python实现 机器学习实战(Machine Learning in Action)

    算法原理 K近邻是机器学习中常见的分类方法之间,也是相对最简单的一种分类方法,属于监督学习范畴.其实K近邻并没有显式的学习过程,它的学习过程就是测试过程.K近邻思想很简单:先给你一个训练数据集D,包括 ...

  7. Coursera 机器学习 第6章(下) Machine Learning System Design 学习笔记

    Machine Learning System Design下面会讨论机器学习系统的设计.分析在设计复杂机器学习系统时将会遇到的主要问题,给出如何巧妙构造一个复杂的机器学习系统的建议.6.4 Buil ...

  8. 【python与机器学习实战】感知机和支持向量机学习笔记(一)

    对<Python与机器学习实战>一书阅读的记录,对于一些难以理解的地方查阅了资料辅以理解并补充和记录,重新梳理一下感知机和SVM的算法原理,加深记忆. 1.感知机 感知机的基本概念 感知机 ...

  9. Machine Learning(Andrew Ng)学习笔记

    1.监督学习(supervised learning)&非监督学习(unsupervised learning) 监督学习:处理具有若干属性且返回值不同的对象.分为回归型和分类型:回归型的返回 ...

随机推荐

  1. Webflux快速入门

    SpringWebflux是SpringFramework5.0添加的新功能,WebFlux本身追随当下最火的Reactive Programming而诞生的框架,那么本篇就来简述一下这个框架到底是做 ...

  2. java操作特殊字符需要注意的点

    在使用字符串替换,分离时 我们如果想替换一个字符串中的问号,我们就不能直接写问号,而要写[?] 实例如下 str = str.replaceAll("\""," ...

  3. Spring Boot 解决方案 - JUnit 测试

    简单的 JUnit 项目 回顾一下创建并运行简单的 JUnit 测试项目,先添加 JUnit 依赖然后编写类似如下模板的测试类,使用 IDE 的话直接用插件运行就行, 使用 Maven 的话运行命令 ...

  4. find_package()的查找*.cmake的顺序

    1. find_package(<Name>)命令首先会在模块路径中寻找 Find<name>.cmake,这是查找库的一个典型方式.具体查找路径依次为CMake: 变量${C ...

  5. 修改linux的ssh默认端口号22的方法

    一.修改配置文件 vi /etc/ssh/sshd_config 找到#Port 22 修改为自己要使用的端口号:Port 26000 然后 :x  退出保存 二.重启ssh服务 /etc/init. ...

  6. WPF中的TextBlock隐藏边框

    TextBlock默认是有边框的,显示效果如下:有一个淡蓝色的边框围绕着 如果需要隐藏这个边框,则只需要在代码中加上以下代码即可: BorderBrush="{x:Null}" B ...

  7. java 正则例子

    1.不易开头.结尾:小数:圆角字符 包含数字.字母.圆角字符 不以<br/>开头.结尾,但中间可以存在 小数中的小数点是半角 正则表达式 "^(?!<br/>)(([ ...

  8. windows开机提示文件损坏

    今早按部就班的开机,然后准备吃热干面,很多时候事情都是同步进行的... 然后眼前出现这样一个界面 心情果断灰暗下来,按照提示一步步操作,点enter进入高级选项,试过了安全模式启动.最后一次正确配置启 ...

  9. UIKit 框架之WebView

    // // ViewController.m // UIWebView // // Created by City--Online on 15/5/18. // Copyright (c) 2015年 ...

  10. CompletableFuture 专题

    /** * @Auther: cheng.tang * @Date: 2019/3/2 * @Description: */ package com.tangcheng.learning.concur ...