机器学习实战---使用FP-growth算法来高效发现频繁项集 一:参考资料 二:案例一(FP-growth算法原理) 三:案例二(更详细)尤其是频繁集挖掘 四:FP树结构定义 五:数据加载 六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树 七:开始从上面获取的FP树中,获取各个数据的条件模式基 八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪) 九:结果测试 十:再回头去看案例二,更好的理解八中挖掘频繁集

(一)机器学习实战

(二)以下3篇简单了解

https://baijiahao.baidu.com/s?id=1661651339862291744&wfr=spider&for=pc(不全,但简单)

https://blog.csdn.net/qq_40587575/article/details/79997195(稍微看看)

https://blog.csdn.net/qq1010885678/article/details/45244829(排版还可以)

(三)下面PPT不错(可以完全理解,且案例丰富)

https://wenku.baidu.com/view/5a28e351bed126fff705cc1755270722182e594b.html(下面两则案例来自此处)

二:案例一(FP-growth算法原理)

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

 机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

三:案例二(更详细)尤其是频繁集挖掘

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

 机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集 

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

机器学习实战---使用FP-growth算法来高效发现频繁项集
一:参考资料
二:案例一(FP-growth算法原理)
三:案例二(更详细)尤其是频繁集挖掘
四:FP树结构定义
五:数据加载
六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
七:开始从上面获取的FP树中,获取各个数据的条件模式基
八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
九:结果测试
十:再回头去看案例二,更好的理解八中挖掘频繁集

四:FP树结构定义

#一:FP树结构定义
class treeNode:
    def __init__(self,nameValue,nameOccur,parentNode):  #nameValue节点名称,nameOccur计数,parentNode指向父节点
        self.name = nameValue   #节点名称
        self.count = nameOccur  #计数器
        self.nodeLink = None    #用来存放节点信息,用来指向下一个同类(同名称)的节点
        self.parent = parentNode    #指向父节点
        self.children = {}  #子节点使用字典进行存放

    def inc(self,numOccur):
        self.count += numOccur

五:数据加载

#二:加载数据
def loadSimDat():
    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

    #返回字典类型{frozenset({'j', 'h', 'z', 'r', 'p'}): 1, frozenset({'y', 'v', 'x', 'w', 'u', 's', 't', 'z'}): 1...}
    return retDict

六:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树

#三:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
#1.建树主函数
def createTree(dataSet,minSup=1):
    headerTable = {}    #存放头指针表
    for trans in dataSet:   #遍历数据,注意我们使用dataSet.items()可以遍历(key,val)对,直接遍历dataSet是对key的操作
        for item in trans:  #item是frozenset类型
            headerTable[item] = headerTable.get(item,0) + dataSet[trans]    #计数操作,其中dataSet[trans]返回字典对于values

    #重点:进行初次剪枝,去掉那些单个元素支持度太低的数据元素
    keys = list(headerTable.keys())
    for k in keys:
        if headerTable[k] < minSup:
            del(headerTable[k]) #达到剪枝效果

    #检查剪枝后是否还有数据存在
    freqItemSet = set(headerTable.keys())
    if len(freqItemSet) == 0:
        return None,None    #因为我们在正常情况下,返回的数据是FP树和头指针表

    #修改头指针表的格式,使得可以指向同类节点(实现链表操作)
    for k in headerTable:
        headerTable[k] = [headerTable[k],None]  #多出的None用来保存后面需要的节点信息

    #先产生根节点
    retTree = treeNode("Null Set",1,None)   #节点名称,出现次数,父节点

    #开始建树
    for tranSet,count in dataSet.items():
        localD = {} #用来保存本样本frozenset({'j', 'h', 'z', 'r', 'p'}): 1的keys是否是频繁项集
        for item in tranSet:
            if item in freqItemSet: #是在频繁项集中
                localD[item] = headerTable[item][0] #添加到localD保存次数
        if len(localD) > 0: #如果在本次样本中有数据在频繁项集中,则开始进行更新树---重点
            #对我们得到的临时localD频繁项集进行排序,将在更新树按照出现最高顺序进行更新(例如最大堆,但不是)
            orderItems = [v[0] for v in sorted(localD.items(),key=lambda p:p[1],reverse=True)]  #大到小排序
            updateTree(orderItems,retTree,headerTable,count)

    return retTree,headerTable  #返回我们需要的树和头指针表

#2.按照传入的一个样本frozenset({'j', 'h', 'z', 'r', 'p'})《注意:是排序好的,大到小》,对树进行更新
def updateTree(items,inTree,headerTable,count):
    """
    重点:我们使用递归方法建树
    :param items: 是传入的排序好的样本frozenset({'j', 'h', 'z', 'r', 'p'})
    :param inTree: 是我们要建立的树
    :param headerTable: 是我们要对头指针表进行修改节点指向,
    :param count: 是本样本在数据集中出现的次数
    """
    if items[0] in inTree.children: #已经存在该增加计数
        inTree.children[items[0]].inc(count)    #增加计数
    else:   #开始进行新增节点
        inTree.children[items[0]] = treeNode(items[0],count,inTree)  #节点按照特定的数据结构修改
        #由于我们有新增的节点,所以我们需要更新头指针表中的nodeLink链表信息,达到链表将同类型的节点链接
        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)

#3.更新头指针表
def updateHeader(headerNode,newNode):
    while headerNode.nodeLink != None:
        headerNode = headerNode.nodeLink
    headerNode.nodeLink = newNode

七:开始从上面获取的FP树中,获取各个数据的条件模式基

#四:开始从上面获取的FP树中,获取各个数据的条件模式基
#1.从FP树种获取头指针表中的各个数据的条件模式基(即找前缀路径,设置计数为当前节点计数值)
def findPrefixPath(treeNode):   #书本上多了一个参数??这里直接传我们指定的节点,查找前缀路径
    condPats = {}
    while treeNode != None:
        prefixPath = []
        ascendTree(treeNode,prefixPath) #获取前缀路径
        #保存前缀路径,和计数值
        if len(prefixPath) > 1: #保证除了本身节点之外,还存在其他前缀
            condPats[frozenset(prefixPath[1:])] = treeNode.count    #注意:使用frozenset类型作为key,并且保存时不含有本身节点
        treeNode = treeNode.nodeLink    #遍历下一个同类型节点

    return condPats #返回所有的前缀路径

#2.向上递归遍历树,找前缀节点信息
def ascendTree(treeNode,prefixPath):    #将结果保存在prefixPath中
    while treeNode.parent != None:  #除了根节点(无用)之外,都进行添加节点
        prefixPath.append(treeNode.name)
        treeNode = treeNode.parent

八:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)

#五:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
#根据条件基模型来构建条件FP树
def mineTree(headerTable,minSup,preFix,freqItemList):
    """
    :param headerTable: 是我们生成FP树时,生成的头指针表
    :param minSup: 最小支持度,用来对复合的数据进行筛选
    :param preFix: 首次为空集合,用来保存当前前缀
    :param 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) #都是frozenset类型---------注意:
        #1.newFreqSet.add(basePat)这一步我们可以看案例I5推导,这里先加入I5,再获取条件FP树,
        #之后根据HeaderTable判断是否为None
        #由案例可知,返回非None,
        #2.对headerTable中I2 I1建树,newFreqSet中含有I5,再分别加上I1,I2
        #2.1先加上I1,即得到I1 I5
        #之后根据HeaderTable判断是否为None
        #由案例可知,返回非None,
        #2.1.1对headerTable中I2建树,newFreqSet中含有I1 I5,再加上I2 即可得到I2 I1 I5
        #2.2再在I5基础上,加上I2,即可得到I2 I5
        #之后根据HeaderTable判断是否为None
        #由案例可知,返回None,退出
        #得到I2 I5, I1 I5,    I2 I1 I5

        #将每个频繁元素添加到频繁项集列表中
        freqItemList.append(newFreqSet)
        #将每个频繁项,都调用findPrefixPath函数,找到前缀路径
        condPattBases = findPrefixPath(headerTable[basePat][1])
        #重点:根据当前元素项生成的前缀路径和最小支持度,生成条件FP树(内部会增加计数值)
        myCondTree,myHead = createTree(condPattBases,minSup)    #从这里可以看出,我们要保存原始数据和前缀路径发现函数返回相同数据类型
        #如果条件FP树中有元素项,则可以再次递归生成条件树
        if myHead != None:  #所以对于我们新的myHead必须在使用条件模型基时,满足最小支持度
            #递归挖掘该条件树,每次向上推一个节点(条件模型基都不包含本节点,所以一直在向上走)
            mineTree(myHead,minSup,newFreqSet,freqItemList)

九:结果测试

dataSet = createInitSet(loadSimDat())
tree,headertable = createTree(dataSet,3)    #注意:因为我们建树的时候,支持度相同的节点不止一个,比如t:3,s:3,所以建树结果顺序可能不同
freqItemList = []
mineTree(headertable,3,set([]),freqItemList)
print(freqItemList)
[{'r'}, {'s'}, {'x', 's'}, {'y'}, {'z', 'y'}, {'x', 'y'}, {'z', 'x', 'y'}, {'t'}, {'z', 't'}, {'x', 't'}, {'z', 'x', 't'}, {'y', 't'}, {'z', 'y', 't'}, {'y', 't', 'x'}, {'z', 'y', 't', 'x'}, {'x'}, {'z', 'x'}, {'z'}]

全部代码:

#一:FP树结构定义
class treeNode:
    def __init__(self,nameValue,nameOccur,parentNode):  #nameValue节点名称,nameOccur计数,parentNode指向父节点
        self.name = nameValue   #节点名称
        self.count = nameOccur  #计数器
        self.nodeLink = None    #用来存放节点信息,用来指向下一个同类(同名称)的节点
        self.parent = parentNode    #指向父节点
        self.children = {}  #子节点使用字典进行存放

    def inc(self,numOccur):
        self.count += numOccur

#二:加载数据
def loadSimDat():
    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

    #返回字典类型{frozenset({'j', 'h', 'z', 'r', 'p'}): 1, frozenset({'y', 'v', 'x', 'w', 'u', 's', 't', 'z'}): 1...}
    return retDict

#三:根据createInitSet方法得到的数据集类型,创建FP树 和 FP条件树
#1.建树主函数
def createTree(dataSet,minSup=1):
    headerTable = {}    #存放头指针表
    for trans in dataSet:   #遍历数据,注意我们使用dataSet.items()可以遍历(key,val)对,直接遍历dataSet是对key的操作
        for item in trans:  #item是frozenset类型
            headerTable[item] = headerTable.get(item,0) + dataSet[trans]    #计数操作,其中dataSet[trans]返回字典对于values

    #重点:进行初次剪枝,去掉那些单个元素支持度太低的数据元素
    keys = list(headerTable.keys())
    for k in keys:
        if headerTable[k] < minSup:
            del(headerTable[k]) #达到剪枝效果

    #检查剪枝后是否还有数据存在
    freqItemSet = set(headerTable.keys())
    if len(freqItemSet) == 0:
        return None,None    #因为我们在正常情况下,返回的数据是FP树和头指针表

    #修改头指针表的格式,使得可以指向同类节点(实现链表操作)
    for k in headerTable:
        headerTable[k] = [headerTable[k],None]  #多出的None用来保存后面需要的节点信息

    #先产生根节点
    retTree = treeNode("Null Set",1,None)   #节点名称,出现次数,父节点

    #开始建树
    for tranSet,count in dataSet.items():
        localD = {} #用来保存本样本frozenset({'j', 'h', 'z', 'r', 'p'}): 1的keys是否是频繁项集
        for item in tranSet:
            if item in freqItemSet: #是在频繁项集中
                localD[item] = headerTable[item][0] #添加到localD保存次数
        if len(localD) > 0: #如果在本次样本中有数据在频繁项集中,则开始进行更新树---重点
            #对我们得到的临时localD频繁项集进行排序,将在更新树按照出现最高顺序进行更新(例如最大堆,但不是)
            orderItems = [v[0] for v in sorted(localD.items(),key=lambda p:p[1],reverse=True)]  #大到小排序
            updateTree(orderItems,retTree,headerTable,count)

    return retTree,headerTable  #返回我们需要的树和头指针表

#2.按照传入的一个样本frozenset({'j', 'h', 'z', 'r', 'p'})《注意:是排序好的,大到小》,对树进行更新
def updateTree(items,inTree,headerTable,count):
    """
    重点:我们使用递归方法建树
    :param items: 是传入的排序好的样本frozenset({'j', 'h', 'z', 'r', 'p'})
    :param inTree: 是我们要建立的树
    :param headerTable: 是我们要对头指针表进行修改节点指向,
    :param count: 是本样本在数据集中出现的次数
    """
    if items[0] in inTree.children: #已经存在该增加计数
        inTree.children[items[0]].inc(count)    #增加计数
    else:   #开始进行新增节点
        inTree.children[items[0]] = treeNode(items[0],count,inTree)  #节点按照特定的数据结构修改
        #由于我们有新增的节点,所以我们需要更新头指针表中的nodeLink链表信息,达到链表将同类型的节点链接
        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)

#3.更新头指针表
def updateHeader(headerNode,newNode):
    while headerNode.nodeLink != None:
        headerNode = headerNode.nodeLink
    headerNode.nodeLink = newNode

#四:开始从上面获取的FP树中,获取各个数据的条件模式基
#1.从FP树种获取头指针表中的各个数据的条件模式基(即找前缀路径,设置计数为当前节点计数值)
def findPrefixPath(treeNode):   #书本上多了一个参数??这里直接传我们指定的节点,查找前缀路径
    condPats = {}
    while treeNode != None:
        prefixPath = []
        ascendTree(treeNode,prefixPath) #获取前缀路径
        #保存前缀路径,和计数值
        if len(prefixPath) > 1: #保证除了本身节点之外,还存在其他前缀
            condPats[frozenset(prefixPath[1:])] = treeNode.count    #注意:使用frozenset类型作为key,并且保存时不含有本身节点
        treeNode = treeNode.nodeLink    #遍历下一个同类型节点

    return condPats #返回所有的前缀路径

#2.向上递归遍历树,找前缀节点信息
def ascendTree(treeNode,prefixPath):    #将结果保存在prefixPath中
    while treeNode.parent != None:  #除了根节点(无用)之外,都进行添加节点
        prefixPath.append(treeNode.name)
        treeNode = treeNode.parent

#五:开始查找频繁集(注意:上面只对单个数据进行了一次支持度裁剪,下面会对各个组合进行裁剪)
#根据条件基模型来构建条件FP树
def mineTree(headerTable,minSup,preFix,freqItemList):
    """
    :param headerTable: 是我们生成FP树时,生成的头指针表
    :param minSup: 最小支持度,用来对复合的数据进行筛选
    :param preFix: 首次为空集合,用来保存当前前缀
    :param 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) #都是frozenset类型---------注意:
        #1.newFreqSet.add(basePat)这一步我们可以看案例I5推导,这里先加入I5,再获取条件FP树,
        #之后根据HeaderTable判断是否为None
        #由案例可知,返回非None,
        #2.对headerTable中I2 I1建树,newFreqSet中含有I5,再分别加上I1,I2
        #2.1先加上I1,即得到I1 I5
        #之后根据HeaderTable判断是否为None
        #由案例可知,返回非None,
        #2.1.1对headerTable中I2建树,newFreqSet中含有I1 I5,再加上I2 即可得到I2 I1 I5
        #2.2再在I5基础上,加上I2,即可得到I2 I5
        #之后根据HeaderTable判断是否为None
        #由案例可知,返回None,退出
        #得到I2 I5, I1 I5,    I2 I1 I5

        #将每个频繁元素添加到频繁项集列表中
        freqItemList.append(newFreqSet)
        #将每个频繁项,都调用findPrefixPath函数,找到前缀路径
        condPattBases = findPrefixPath(headerTable[basePat][1])
        #重点:根据当前元素项生成的前缀路径和最小支持度,生成条件FP树(内部会增加计数值)
        myCondTree,myHead = createTree(condPattBases,minSup)    #从这里可以看出,我们要保存原始数据和前缀路径发现函数返回相同数据类型
        #如果条件FP树中有元素项,则可以再次递归生成条件树
        if myHead != None:  #所以对于我们新的myHead必须在使用条件模型基时,满足最小支持度
            #递归挖掘该条件树,每次向上推一个节点(条件模型基都不包含本节点,所以一直在向上走)
            mineTree(myHead,minSup,newFreqSet,freqItemList)

dataSet = createInitSet(loadSimDat())
tree,headertable = createTree(dataSet,3)    #注意:因为我们建树的时候,支持度相同的节点不止一个,比如t:3,s:3,所以建树结果顺序可能不同
freqItemList = []
mineTree(headertable,3,set([]),freqItemList)
print(freqItemList)
View Code

十:再回头去看案例二,更好的理解八中挖掘频繁集

https://wenku.baidu.com/view/5a28e351bed126fff705cc1755270722182e594b.html

本文较为简略,后面需要再次理解。最近时间紧,任务重....,没有结合关联分析