1. FP-growth算法概述
FP-growth算法是一种用于发现频繁项集的挖掘算法。它是由Han et al.于2000年提出的。根据数据挖掘的定义,频繁项集是指在数据集中经常出现在一起的物品集合。FP-growth算法是一种快速、高效的挖掘算法。相比于Apriori算法,它无需生成候选项集,从而减少了时间和空间的开销,能够非常快速地发现频繁项集。
2. FP-growth算法原理
2.1 FP树的构建
FP-growth算法的核心是FP树,是一种用于存储频繁项集信息的数据结构。FP树由树结构和头指针表构成。其中,树结构用于存储频繁项集,头指针表则连接相同元素项的链表。
在构建FP树之前,需对数据集进行处理。首先,需要对数据集进行去重处理,并按照项集出现次数进行排序。然后,根据排序后的项集,利用每个项集中的元素构建节点,频数则存储在节点上。
FP树的构建采用递归方式进行,每次插入一个项集,从根节点开始遍历。如果已经存在相同的元素,则加上其频数,并继续遍历;否则,新建节点并挂在当前节点下面,并进行头指针表连接。最后,构建完成的FP树就是一个由节点和指针构成的树结构。
2.2 FP-growth的递归流程
FP-growth算法的递归过程由两部分组成:挖掘频繁项集和创建条件FP树。
挖掘频繁项集是一个基于递归的过程。首先,遍历头指针表,将每个元素项单独作为频繁项加入到频繁项集中。然后,从头指针表中选择一个元素项作为“基础元素”,并挖掘其对应的频繁项集。从而得到满足条件的频繁项集。
创建条件FP树是指构建以“基础元素”为根节点的子FP树。在创建条件FP树时,需对数据集进行预处理,去掉不满足条件的项。然后,针对新的数据集,构建FP树。
以上两部分递归过程反复进行,直到FP树不再包含任何元素项,或者只剩下一个元素项。
3. FP-growth算法流程
FP-growth算法的流程如下:
1. 对数据集进行预处理,去掉不满足条件的项。
2. 构建FP树。
3. 按照频繁度从大到小遍历FP树中的元素,构建条件FP树。
4. 对条件FP树进行递归挖掘,得到满足条件的频繁项集。
4. FP-growth算法优缺点
4.1 优点
FP-growth算法的优点主要体现在以下几个方面:
1. 相比于Apriori算法,FP-growth算法无需生成候选项集,从而减少了时间和空间的开销。
2. 由于FP树的特殊结构,FP-growth算法能够非常高效地挖掘频繁项集。
3. FP-growth算法不受项集中元素个数的限制,可以处理大规模的数据集。
4.2 缺点
FP-growth算法的缺点主要体现在以下几个方面:
1. 构建FP树的过程需要遍历整个数据集,因此,构建FP树可能会消耗大量的内存。
2. 构建条件FP树的过程需要在FP树上进行多次递归,因此,对于数据集中包含大量元素的频繁项集而言,递归次数可能较多,效率较低。
5. FP-growth算法应用案例
以下是使用FP-growth算法进行商品推荐的一个简单案例:
假设有一个在线商城,用户购买商品时,系统需要向用户推荐其他可能感兴趣的商品。为此,我们需要通过挖掘历史用户购买记录,发现频繁购买项集,从而推荐新的商品。
首先,根据历史用户购买记录,可以构建一个购买项集。然后,使用FP-growth算法挖掘频繁购买项集。最后,根据频繁购买项集,可以推荐与用户当前购买行为相似的商品。
6. 代码实现
以下是使用Python语言实现FP-growth算法的一个简单示例:
class TreeNode:
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 += numOccur
def 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):
headerTable = {}
for trans in dataSet:
for item in trans:
headerTable[item] = headerTable.get(item, 0) + dataSet[trans]
for k in list(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 ascendTree(leafNode, prefixPath):
if leafNode.parent != None:
prefixPath.append(leafNode.name)
ascendTree(leafNode.parent, prefixPath)
def findPrefixPath(basePat, treeNode):
condPats = {}
while treeNode != None:
prefixPath = []
ascendTree(treeNode, prefixPath)
if len(prefixPath) > 1:
condPats[frozenset(prefixPath[1:])] = treeNode.count
treeNode = treeNode.nodeLink
return condPats
def mineTree(inTree, headerTable, minSup, preFix, freqItemList):
bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1][0])]
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)
data = [['a', 'b', 'd', 'f'], ['b', 'c', 'e'], ['a', 'b', 'c', 'e', 'f'], ['a', 'd', 'e'], ['a', 'f'], ['a', 'b', 'c', 'f'], ['b', 'd'], ['b', 'c', 'd', 'f'], ['b', 'f'], ['a', 'b', 'c', 'e', 'f']]
dataSet = {}
for i in range(len(data)):
dataSet[frozenset(data[i])] = 1
minSup = 2
myFPtree, myHeaderTab = createTree(dataSet, minSup)
myFreqList = []
mineTree(myFPtree, myHeaderTab, minSup, set([]), myFreqList)
print(myFreqList)