机器学习实战(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. 编写一个c++工程

    c++接触的很少,之前也只是会编写一个简单的cpp文件,但一个工程的实现,往往不仅包括源文件(.cpp后缀文件)一般还有头文件(.h后缀文件)等.一个c++工程中只能有一个main函数,这个函数所在的 ...

  2. Android 开发服务类 05_ ApkPatchDemo

    APP 增量更新服务端[https://github.com/cundong/SmartAppUpdates] import com.cundong.common.Constants; import ...

  3. CSS3实现纸张边角卷起效果

    html代码 <body> <div class="page"> <div class="page-box"> <h1 ...

  4. Linux 启动过程详解

    目录 1. Linux启动过程 2. 启动过程概述 3. 引导加载阶段 4. 内核阶段 4.1 内核加载阶段 4.2 内核启动阶段 5. 早期的用户空间 6. 初始化过程 6.1 SysV init ...

  5. 安装Windows 8.1过程中出现的各种问题(无损从MBR转GPT磁盘、不能定位已有分区)

    这个周末就安装了个系统,本以为一个小时就能搞定,没想到花费了将近一天. 我的机子是6G内存.500G硬盘,原装系统是Windows 7,现在想换成Windows 8.1,于是下载了64位的Window ...

  6. Excelbatis-一个将excel文件读入成实体列表、将实体列表解析成excel文件的ORM框架,简洁易于配置、可扩展性好

    欢迎使用Excelbatis! github地址:https://github.com/log4leo/Excelbatis Excelbatis的优点 和spring天然结合,易于接入 xsd支持, ...

  7. 【详解】ThreadPoolExecutor源码阅读(二)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...

  8. .gvimrc配置备份

    syn on "语法支持 colorscheme murphy set go= "common conf {{ 通用配置 "set ai "自动缩进 set b ...

  9. redhat 6 使用centos源 yum安装

    1.删除redhat原有的yum源 # rpm -aq | grep yum|xargs rpm -e --nodeps 2.下载新的yum安装包 这里我们使用CentOS的yum源 # wget h ...

  10. SSH-公私钥认证

    Linux下SSH的认证方式有两种,即密码认证和公私钥认证. 我们在日常的安全维护中,出于安全的考虑,密码不明文存放,会使用公私钥认证方式.这个时候我们就需要使用ssh-keygen,ssh-keyg ...