FP-Growth算法实现

2023-12-04 10:50
文章标签 算法 实现 growth fp

本文主要是介绍FP-Growth算法实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

频繁项集挖掘(二)FP-Growth算法

FP-Growth(Frequent Patterns)相比于Apriori是一种更加有效的频繁项集挖掘算法,FP-Growth算法只需要对数据库进行两次扫描,而Apriori算法对于每次产生的候选项集都会扫描一次数据集来判断是否频繁,因此当数据量特别巨大,且扫描数据库的成本比较高时,FP-Growth的速度要比Apriori快。

但是FP-Growth只能用于发现频繁项集,不能用于发现关联规则。

FP-Growth原理分析

FP-Growth算法实现步骤

  • 构建FP树
  • 从FP树中挖掘频繁项集

FP-Growth算法将数据存储在一种被称为FP树的紧凑数据结构中。
在这里插入图片描述

下图就是利用上面的数据构建的一棵FP树(最小支持度为3):
在这里插入图片描述

  • FP树中最小支持度指项集总共出现的次数
  • 一个元素项可以在一棵FP树中出现多次
  • FP树存储项集的出现频率,且每个项集会以路径的方式存储在树中
  • 存在相似元素的集合会共享树的一部分
  • 只有当集合之间完全不同时,树才会分叉
  • 树节点上给出集合中的单个元素及其在序列中的出现次数,路径会给出该序列的出现次数

FP-Growth算法工作流程:

  • 扫描数据集两遍
  • 第一遍对所有元素项的出现次数进行计数
  • 根据前面的结论,如果某元素是不频繁的,那么包含该元素的超集也是不频繁的
  • 第二遍扫描,只考虑那些频繁元素,并且第二遍扫描开始构建FP树
算法实现
class treeNode(object):def __init__(self, nameValue, numOccur, parentNode):# 节点名称self.name = nameValue# 节点计数self.count = numOccur# 记录相似的元素项self.nodeLink = None# 父节点对象self.parent = parentNode# 子节点self.children = {}def inc(self, numOccur):self.count += numOccurdef disp(self, ind=1):print('--'*ind, self.name, ' ', self.count)for child in self.children.values():child.disp(ind+1)def createTree(dataSet, minSup=1):  # create FP-tree from dataset but don't mine'''遍历数据集两遍'''# 第一遍对元素计数originHeaderTable = {}    # headerTable用于记录树的结构情况for trans in dataSet:for item in trans:originHeaderTable[item] = originHeaderTable.get(item, 0) + dataSet[trans]popKeys = []# 过滤掉非频繁项集for k in originHeaderTable.keys():# 记录非频繁项if originHeaderTable[k] < minSup:popKeys.append(k)freqItemSet = set(originHeaderTable.keys()) - set(popKeys)# headerTable用于记录树的结构情况headerTable = {}if len(freqItemSet) == 0:   # 如果初选没有频繁项集,那么直接退出return None, None# 重新构建headerTablefor k in freqItemSet:headerTable[k] = [originHeaderTable[k], None]  # reformat headerTable to use Node linkdel originHeaderTable# 构建空树,根节点为空集root_node = treeNode('Null Set', 1, None)# 第二遍扫描,开始构建FP树for tranSet, count in dataSet.items():  # go through dataset 2nd timelocalD = {}for item in tranSet:  # put transaction items in orderif 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, root_node, headerTable, count)  # populate tree with ordered freq itemsetreturn root_node, headerTable  # return tree and header tabledef updateTree(items, parentNode, headerTable, count):# 判断第一个项集是已经是当前节点的子节点if items[0] in parentNode.children:  # check if orderedItems[0] in retTree.children# 如果是,那么直接count + 1parentNode.children[items[0]].inc(count)  # incrament countelse:  # add items[0] to inTree.children# 如果不是,那么新建节点,并存储为当前节点的子节点parentNode.children[items[0]] = treeNode(items[0], count, parentNode)# 更新headerTable# 判断当前item是否是第一次记录if headerTable[items[0]][1] == None:# 如果是第一次,那么把新建的节点直接记录到头表中headerTable[items[0]][1] = parentNode.children[items[0]]else:# 如果不是第一次,那么说明新节点是当前item的节点的子节点,因此将它记录到当前分支的末位去,即设置为当前分支的叶子节点updateHeader(headerTable[items[0]][1], parentNode.children[items[0]])# 如果还有第二个元素,那么递归执行以上操作if len(items) > 1:updateTree(items[1::], parentNode.children[items[0]], headerTable, count)def updateHeader(lastNode, newLeafNode):# 判断上一节点是否有连接节点,如果没有,那么说明上一节点就是叶子节点,那么直接将新节点设为叶子节点while (lastNode.nodeLink != None):# 如果上一节点已经有连接节点,那么循环知道遍历到叶子节点,再设置新叶子节点lastNode = lastNode.nodeLink# 将新的叶子节点设置为旧叶子节点的连接节点lastNode.nodeLink = newLeafNodedef loadTestDataset():dataset = [['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 datasetdef createInitDataset(dataSet):dictDataset = {}for trans in dataSet:dictDataset[frozenset(trans)] = 1return dictDatasetdef buildCombinedItems(leafNode, combinedItems):if leafNode.parent != None:combinedItems.append(leafNode.name)buildCombinedItems(leafNode.parent, combinedItems)def buildCombinedDataset(nodeObject):# 根据节点名称,组合出新的项集节点combinedDataset = {}while nodeObject != None:combinedItems = []buildCombinedItems(nodeObject, combinedItems)if len(combinedItems) > 1:combinedDataset[frozenset(combinedItems[1:])] = nodeObject.countnodeObject = nodeObject.nodeLinkreturn combinedDatasetdef scanFPTree(headerTable, minSup, parentNodeNames, freqItemList):# 遍历排序后的headerTable,(节点名称,节点信息)for baseNode, nodeInfo in headerTable.items():# 根据prefixnewFreqSet = parentNodeNames.copy()newFreqSet.add(baseNode)# 节点计数值nodeCount = nodeInfo[0]# 节点对象nodeObject = nodeInfo[1]# 记录下频繁项集以及计数freqItemList.append((newFreqSet, nodeCount))# 根据当前节点的子节点,构建出新的项集组合combinedDataset = buildCombinedDataset(nodeObject)# 根据新的项集组合,重合构建子FP树subFPTree, subFPTreeHeaderTable = createTree(combinedDataset, minSup)# 如果头表不为空,那么递归新树的头表if subFPTreeHeaderTable != None:print('conditional tree for: ', newFreqSet)subFPTree.disp(1)# 根据新的头表 扫描FP-TreescanFPTree(subFPTreeHeaderTable, minSup, newFreqSet, freqItemList)if __name__ == '__main__':from pprint import pprintsimpDat = loadTestDataset()initSet = createInitDataset(simpDat)# 构建初始的FP-TreeinitFPtree, initFPtreeHeaderTable = createTree(initSet, 3)initFPtree.disp(1)freqItems = []    # 存储频繁项集# 扫描FP树,找出所有符合条件的频繁项集root_node_names = set([])    # 从根路径空集开始扫描scanFPTree(initFPtreeHeaderTable, 3, root_node_names, freqItems)pprint(freqItems)

freqItems = [] # 存储频繁项集
# 扫描FP树,找出所有符合条件的频繁项集

root_node_names = set([])    # 从根路径空集开始扫描
scanFPTree(initFPtreeHeaderTable, 3, root_node_names, freqItems)
pprint(freqItems)

这篇关于FP-Growth算法实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/453199

相关文章

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q