关联分析与FP-growth算法
2016-04-12 19:18
591 查看
关联分析
关联分析:从大规模数据集中寻找物品见的隐含关系被称作关联分析或者关联规则学习。存在的问题:
寻找物品的不同组合是一项十分耗时的任务,所需要的计算代价很高,暴力搜索不能解决这个问题。
Apriori算法
优点:易于编码实习缺点:在大数据集上可能较慢
适用数据类型:数值型或者标称型数据
相关概念
频繁项集: 指经常出现在一起的物品的集合如何来考察物品是否出现频繁,我们通过支持度和可信度来考察。
项集的支持度:数据集中包含该项集所占的比例。
项集的可信度/支持度:是针对一条关联规则的来定义的。
example:
关联规则:{尿布}→{葡萄酒}
可信度:支持度({尿布,葡萄酒})支持度({尿布})
支持度和可信度是用来量化关联分析是否成功的方法。
Apriori原理
Apriori原理是说如果某个项集是频繁的那么它的所有子集也是频繁的。在做关联分析的时候我们反过来看,即一个项集值非频繁集,那么它的所有超集也是非频繁的。Apriori算法是用来发现频繁项集的一种方法,该算法的参数为最小支持度和数据集
求解频繁项集
算法流程:生成所有单个物品的项集列表
扫描交易记录查看哪些项集满足最小支持度要求,去除不满足的集合
生成包含两个元素的项集列表
重新扫描交易记录,去掉不满足最小支持度的项集
重复进行知道所有的项集都被去掉
如图所示:
从频繁项集中挖掘出关联规则
example:{豆奶}→{莴笋} :意味着如果有人购买豆奶,那么他买莴笋的概率很大。
箭头左边的集合称为前件,箭头右边的称为后件。
我们通过可信度来量化的考核一条关联规则:
关联规则:P→H,可以表示为 support(P∪H)support(P)
类比寻找频繁项集我们可以得出,如果某条规则不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求。
算法流程:
从一个频繁项集开始,接着创建一个规则列表,其中规则的后件只包含一个元素
然后对这些规则进行测试,去除不满足最小可信度要求的规则
合并所有剩余规则来创建一个新的规则列表,其中规则的后件包含两个元素。
然后重复执行上面的步骤
Code
Apriori.py#-*- coding:utf8 -*- def loadDataSet(): return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]] """ 生成单个物品的项集列表 """ def creatC1(dataSet): C1 = [] for transation in dataSet: for item in transation: if not [item] in C1: C1.append([item]) C1.sort() #frozenset一旦建立不可修改 return map(frozenset,C1) """ 扫描交易记录 参数:交易记录D,长度为k的项集的列表,最小支持度 """ def ScanD(D,Ck,minSupport): ssCnt = {} for tid in D: for can in Ck: if can.issubset(tid): if not ssCnt.has_key(can): ssCnt[can] = 1 else: ssCnt[can] +=1 numItems = float(len(D)) retList =[] supportData ={} for key in ssCnt: support = ssCnt[key]/numItems if support >= minSupport: retList.insert(0,key) supportData[key]=support return retList,supportData """ 创建k个物品的项集列表 参数:长度为K-1的数据项列表,新数据列表元素的长度K """ def aprioriGen(Lk,k): retList = [] lenLk = len(Lk) for i in range(lenLk): for j in range(i+1,lenLk): L1 = list(Lk[i])[:k-2] L2 = list(Lk[j])[:k-2] L1.sort() L2.sort() if L1 == L2: #若前K-2项一样则合并生成一个大小为K的数据项 retList.append(Lk[i] | Lk[j]) return retList """ 执行Apriori算法 参数:数据集,最小支持度 """ def apriori(dataSet,minSupport = 0.5): C1 = creatC1(dataSet) D = map(set,dataSet) L1 ,supportData = ScanD(D,C1,minSupport) L = [L1] k = 2 while len(L[k-2]) > 0: Ck = aprioriGen(L[k-2],k) Lk , supk = ScanD(dataSet,Ck,minSupport) supportData.update(supk) L.append(Lk) k += 1 return L,supportData """ 生成关联规则 参数:频繁项集列表,频繁项集支持数据的字典,最小可信度 """ def generateRules(L,supportData,minConf=0.7): bigRuleList =[] for i in range(1,len(L)): for freqSet in L[i]: H1 = [frozenset([item]) for item in freqSet] if i > 1: rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf) else: calcConf(freqSet,H1,supportData,bigRuleList,minConf) return bigRuleList """ 计算规则的可信度以及找到满足最小可信度要求的规则 参数:频繁项集,现有规则后件的元素列表 """ def calcConf(freqSet,H,supportData,br1,minConf=0.7): prunedH = [] for conseq in H: conf = supportData[freqSet]/supportData[freqSet-conseq] if conf >= minConf: print freqSet-conseq,'-->',conseq,'conf: ',conf br1.append((freqSet-conseq,conseq,conf)) prunedH.append(conseq) return prunedH """ 从初始项集生成更多的关联规则 参数:频繁项集,现有规则后件的元素列表 """ def rulesFromConseq(freqSet,H,supportData,br1,minConf = 0.7): m = len(H[0]) if len(freqSet) > (m+1): Hmp1 = aprioriGen(H,m+1) Hmp1 = calcConf(freqSet,Hmp1,supportData,br1,minConf) if len(Hmp1) > 1: rulesFromConseq(freqSet,Hmp1,supportData,br1,minConf)
test.py
__author__ = 'bigship' import Apriori #test load dataSet = Apriori.loadDataSet() print dataSet #test CreatC1 C1 = Apriori.creatC1(dataSet) D = map(set,dataSet) #test ScanD L1,supportData0 = Apriori.ScanD(D,C1,0.5) print L1 print supportData0 #test apriori L,supportData = Apriori.apriori(dataSet,0.5) print L #test generateRules rules = Apriori.generateRules(L,supportData,0.7) print rules
分析毒蘑菇的特征
mushroom.py
__author__ = 'bigship' import Apriori def split(str,cha): retList = [] for x in str: if x != cha[0] and x!= cha[1]: retList.append(x) return retList mushDataSet = [] data = open('mushroom.txt') cha = [',','\n'] for line in data.readlines(): mushDataSet.append(split(line,cha)) data.close() smallDataSet = mushDataSet[:10] print smallDataSet L , supportData = Apriori.apriori(smallDataSet,0.7) for item in L[4]: if item.intersection('e'): print item result = Apriori.generateRules(L,supportData,0.85)
Summary
关联分析是用于发现大数据集中元素间有趣关系的一个工具集,可以采用两种方式来量化这些有趣的关系。第一种方式是使用频繁项集,它会给出经常在一起出现的元素项。第二种方式是关联规则,每条关联规则意味着元素项之间的“如果……那么”关系。关联分析可以用在许多不同物品上。商店中的商品以及网站的访问页面是其中比较常见的例子。
每次增加频繁项集的大小,Apriori算法都会重新扫描整个数据集。当数据集很大时,这会显著降低频繁项集发现的速度。
FP-growth算法
FP-growth算法也是基于Apriori思想提出来的一共算法,但是其采用了一种高级的数据结构减少扫描次数,大大加快了算法速度。FP-growth算法只需要对数据库进行两次扫描,而Apriori算法对于每个潜在的频繁项集都会扫描数据集判定给定模式是否频繁,因此FP-growth算法的速度要比Apriori算法快。算法流程:
构建FP树
从FP树中挖掘出频繁项集
优缺点:
优点:一般快于Apriori算法
缺点:实现比较困难,在某些数据集上性能会下降
适用数据类型:标称型数据
构建FP树
事务数据:FP树:
其中没有出现p,q,的原因是因为我们实战的有最小支持度的阀值,当小于这个阀值的时候我们认为其是不频繁的。
在构建FP树时我们需要对原始数据扫描两遍:
第一遍对所有元素项的出现次数进行计数,去掉不满足最小支持度的元素项
第二遍扫描中只需要考虑那些频繁元素,读入每个项集将其添加到一条已经存在的路径中,若该路径不存在则创建一条新路径。
从FP树中挖掘频繁项集
从FP树中抽取频繁项集的三个步骤:从FP树中获得条件模式基
利用条件模式基,构建一颗条件FP树
迭代重复步骤(1),(2),直到树包含一个元素项为止
条件模式基: 以所查找元素项为结尾的路径集合,每一条路径都是一条前缀路径。
example:
频繁项 | 前缀路径 |
---|---|
z | {}5 |
r | {x,s}1,{z,x,y}1,{z}1 |
x | {z}3,{}1 |
y | {z,x}3 |
s | {z,x,y}2,{x}1 |
t | {z,y,x,s}2,{z,x,y,r}1 |
对于得到的每一个频繁项,我们都要创建一颗条件FP树,然后我们会递归的发现频繁项,发现条件基,以及发现另外的条件树,直到条件树没有元素为止。
Code
FPgrowth.py#-*- coding:utf8 -*- class treeNode: def __init__(self,nameValue,numOccur,parentNode): self.name = nameValue #节点的值 self.count = numOccur #节点值出现的次数 self.nodeLink = None #用于连接相似的元素项 self.parent = parentNode #父节点 self.children ={} #子结点 """ 修改count的值 """ 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) """ 创建FP树 参数:数据集合,最小支持度 """ 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 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) # 根节点 # 第二次遍历数据集,创建FP树 for tranSet, count in dataSet.items(): localD = {} # 对一个项集tranSet,记录其中每个元素项的全局频率,用于排序 for item in tranSet: if item in freqItemSet: localD[item] = headerTable[item][0] # 注意这个[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树 return retTree, headerTable def updateTree(items, inTree, headerTable, count): if items[0] in inTree.children: # 有该元素项时计数值+1 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函数 updateTree(items[1::], inTree.children[items[0]], headerTable, count) """ 更新头指针表 """ def updateHeader(nodeToTest,targetNode): while nodeToTest.nodeLink != None: nodeToTest = nodeToTest.nodeLink nodeToTest.nodeLink = targetNode def loadSimpDat(): 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 creatInitSet(dataSet): retDict = {} for trans in dataSet: retDict[frozenset(trans)] = 1 return retDict def ascendTree(leafNode, prefixPath): if leafNode.parent != None: prefixPath.append(leafNode.name) ascendTree(leafNode.parent, prefixPath) """ 根据headerTable表找到所要找的元素的条件模式基 参数:所要找的元素,headerTable的表头 """ 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 """ 递归查找频繁项集 参数:FP树,头指针表,最小支持度,前缀表,频繁项集 """ 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: 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) def fpGrowth(dataSet, minSup=3): initSet = creatInitSet(dataSet) myFPtree, myHeaderTab = createTree(initSet, minSup) freqItems = [] mineTree(myFPtree, myHeaderTab, minSup, set([]), freqItems) return freqItems
test.py
import FPgrowth #test TreeNode rootNode = FPgrowth.treeNode('pyramid',9,None) rootNode.children['eye']=FPgrowth.treeNode('eye',13,None) rootNode.disp() #test loadSimDat and initdata SimData = FPgrowth.loadSimpDat() initSet = FPgrowth.creatInitSet(SimData) #test creatTree myFPtree , myHeadTable = FPgrowth.createTree(initSet,3) myFPtree.disp() #test fpGrowth print FPgrowth.fpGrowth(SimData)
相关文章推荐
- 康诺云推出三款智能硬件产品,为健康管理业务搭建数据池
- MySQL中使用innobackupex、xtrabackup进行大数据的备份和还原教程
- 数据挖掘之Apriori算法详解和Python实现代码分享
- php+ajax导入大数据时产生的问题处理
- C# 大数据导出word的假死报错的处理方法
- 用Python实现协同过滤的教程
- Python利用多进程将大量数据放入有限内存的教程
- mongodb常遇到的错误。
- Stack数据结构的特点后进先出的应用:大数据运算
- YARN或将成为Hadoop新发力点
- Hadoop 1.x版本伪单机配置
- Glusterfs的编译选项 #pragma GCC poison system popen
- OSSIM平台安全事件关联分析实践
- Python 大数据思维导图
- Spark HA部署方案
- Spark HA原理架构图
- HADOOP的HA部署方案