关联分析
来源:互联网 发布:php一句话木马 编辑:程序博客网 时间:2024/06/04 00:38
1、综述
关联分析的目的是寻找交易记录中的频繁项集和关联规则。
置信度:set{e1,e2,e3,...}等一起出现的概率
支持度:set{e1,e2,e3...}发生时set{en,em,...}也发生的概率
在频繁项集中寻找关联规则???why?? 置信度和支持度的大小关系??
2、实现思想
a、将item进行排列组合生成各种长度的项集set,满足支持度要求的项集为频繁项集;
b、apriori算法减小了候选项;
c、Fp-Growth算法只需要两次遍历数据库:(1):找出len-1的频繁项集;(2):利用len-1的项集建立FP-Tree
3、apriori实现
# -*- coding:utf8 -*-__author__ = 'zhangpeng'def loadDataSet(): return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]# 生成len-1的候选项集列表C1def createC1(dataSet): C1 = [] # 把len-1的不重复item加入C1中 for transaction in dataSet: for item in transaction: if not [item] in C1: C1.append([item]) C1.sort() # 把c1中每个item变成frozenset集合 return map(frozenset,C1)# 从len-k的候选项集列表Ck中选出频繁项集列表Lkdef scanD(D,Ck,minSupport): ssCnt = {} # 遍历数据集和len-k的候选集 for transaction in D: for item in Ck: # set集合运算,判断transaction_set中是否包含item_set if transaction.issuperset(item): if not ssCnt.has_key(item): ssCnt[item] = 1 else: ssCnt[item] += 1 numItems = float(len(D)) retList = [] supportData = {} # 保留大于支持度的item_set for key in ssCnt: support = ssCnt[key]/numItems if support >= minSupport: retList.append(key) supportData[key] = support return retList,supportData# 从len-(k-1)的频繁项集列表Lk_1中生成len-k的候选项集列表Ckdef aprioriGen(Lk_1,k): retList = [] lenLk_1 = len(Lk_1) for i in range(lenLk_1): for j in range(i + 1, lenLk_1): # 如果两个项集前k-2个元素相同,则合并成len-k的list temp = frozenset(Lk_1[i] | Lk_1[j]) if len(temp) == k and temp not in retList: retList.append(temp) return retList# 寻找dataSet的频繁项集def apriori(dataSet, minSupport = 0.5): C1 = createC1(dataSet) D = map(frozenset,dataSet) L1,supportData = scanD(D,C1,minSupport) L = [] L.append(L1) k = 2 while len(L[k-2]) > 0: Ck = aprioriGen(L[k-2],k) Lk,supportK = scanD(D,Ck,minSupport) L.append(Lk) supportData.update(supportK) k += 1 return L,supportData# 从频繁项集L中找出关联规则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] #H1:频繁项集的元素项集列表,作为规则右边的项集列表 if i > 1: #项集长度大于2 rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf) else: #项集长度小于2,直接寻找关联规则 calcConf(freqSet,H1,supportData,bigRuleList,minConf) return bigRuleList# 对频繁项集进行评估。H:规则右边的项集列表def calcConf(freqSet,H,supportData,brl,minConf = 0.7): prunedH = [] for item in H: conf = supportData[freqSet]/supportData[freqSet - item] if conf >= minConf: brl.append((freqSet - item,item,conf)) prunedH.append(item) return prunedH# 生成关联规则候选集,并进行评估def rulesFromConseq(freqSet, H, supportData, brl, minConf = 0.7): m = len(H[0]) # 规则右边项集的长度 if len(freqSet) > m+1: #项集长度 > 右边项集长度 + 1,这样才能组合出len(m+1)的规则右边项集 Hm = aprioriGen(H,m+1) Hm = calcConf(freqSet,Hm,supportData,brl,minConf) #利用新的规则右边项集,寻找新的关联规则 if len(Hm) > 1: #只有规则右边项集 >= 2时,才有可能找到新的频繁项 rulesFromConseq(freqSet,Hm,supportData,brl,minConf) returnif __name__ == "__main__": dataSet = loadDataSet() L,supportData = apriori(dataSet,0.5) rules = generateRules(L,supportData, 0.7) # print L # print supportData print rules
算法总结:
生成C1候选项集-》挑选L1频繁项集-》生成C2候选项集-》挑选L2频繁项集.......直到length(Lk)=0结束寻找;
从频繁项集freqSet1中寻找后件项集H1,生成候选规则C_ruleH1-》挑选关联规则ruleH1-》利用rukeH1中的H1生成H2,生成候选规则C_ruleH2-》挑选ruleH2........直到Hk的k=len(freqSet1) - 1 or Hk中只有一个元素时停止迭代。接在对频繁项集freqSet2、freqSet3.....重复此过程(非最优解)
代码总结:
频繁项集用set()集合表示,[set1,set2,set3,....]中set集合为list的元素,{frozenset1:value1,frozenset2:value2,....}中frozenset集合为dict的key值,集合可以当做普通的数值类型应用于list和dict的各种方法中。set()集合包含很多集合操作和方法,如-、^、&、|、len()、==、in、is superset()、is subset()、add、update、remove、list(set1)等操作
4、FP-Growth实现
# -*- coding:utf8 -*-class treeNode: def __init__(self,name,count,parent): self.name = name # 节点在某一序列中出现的次数 self.count = count # 指向此item对应的下一个节点 self.nodeLink = None self.parent = parent # 此节点的子节点,{item1:item1Node,item2:item2Node,......} self.children = {} def inc(self,count): self.count += count def disp(self,ind = 1): print ' '*ind, self.name, '', self.count for child in self.children.values(): child.disp(ind + 1)# 创建FpGrowth树def createTree(dataSet,minSup = 1): headerTable = {} # 第一次遍历数据库找出len1的频繁项 for trans in dataSet: trans2set = set(trans) for item in trans2set: headerTable[item] = headerTable.get(item,0) + 1 # len1满足条件的item和其出现的次数加入头指针表中 for key in headerTable.keys(): if headerTable[key] < minSup: del(headerTable[key]) # len1的频繁项集 freqSet1 = set(headerTable.keys()) if len(freqSet1) == 0: return None,None for key in headerTable: # 头指针表value的第二个元素为该item节点链表的起始节点 headerTable[key] = [headerTable[key],None] # 根节点(父节点) rootNode = treeNode('Null Set',1,None) # 第二次遍历数据库,构建FP树 for trans in dataSet: localD = {} for item in trans: if item in freqSet1: # 获取一条trans中频繁元素和次数 localD[item] = headerTable[item][0] if len(localD) > 0: # 将trans中频繁元素按频率从大到小排序 orderedItems = [item[0] for item in sorted(localD.items(),key=lambda line:line[1],reverse=True)] # 把trans中排好序的元素列表插入树中 updateTree(orderedItems,rootNode,headerTable) return rootNode,headerTable# 根据父节点(最初为根节点)、排好序的元素列表、头指针表,来更新树和头指针表中的链表def updateTree(items,parentNode,headerTable): # 父节点含有此item的子节点 if items[0] in parentNode.children.keys(): parentNode.children[items[0]].inc(1) else: # 创建节点接入父节点中 parentNode.children[items[0]] = treeNode(items[0],1,parentNode) # 头指针表没有写入此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]]) # 传入的项集len >= 2,迭代更新树 if len(items) >= 2: # 剩下的元素列表在前一个节点后插入 updateTree(items[1:],parentNode.children[items[0]],headerTable) return# 传入头指针表该item的第一个节点,新的此item的节点,将新的此item节点插入到树中此item节点组成的链表上def updateHeader(nodeToTest,targetNode): while nodeToTest.nodeLink != None: nodeToTest = nodeToTest.nodeLink nodeToTest.nodeLink = targetNodedef loadData(): 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# 从leafNode出发上溯寻找节点,找到后将item加入到前缀路径prefixPath中def ascendTree(leafNode,prefixPath): # 当leafNode是根节点时停止递归 if leafNode.parent != None: prefixPath.append(leafNode.name) ascendTree(leafNode.parent,prefixPath) return# 传入item和其对应的第一个节点,遍历发现该item所有节点的前缀路径,组合成条件模式基def findPrefixPath(item,treeNode): # item的条件模式基 condPats = [] while treeNode != None: prefixPath = [] ascendTree(treeNode,prefixPath) if len(prefixPath) > 1: # 前缀路径最后一个元素表示此前缀路径出现的次数 # 出现n此,则item的条件基包含n次该前缀路径,即此路径和item共同出现过n次 for i in range(treeNode.count): condPats.append(prefixPath[1:]) treeNode = treeNode.nodeLink return condPats# 传入根节点、头指针表、频繁项集的后缀、最终频繁项集的列表# 对头指针表中的每个item搜索条件FP树,用来扩充前缀def mineTree(rootNode,headerTable,minSup,preFix,freqItemList): # 头指针表中item按从小到大排序 bigL = [v[0] for v in sorted(headerTable.items(),key=lambda p:p[1][0])] for basePat in bigL: # 对后缀项集进行浅赋值,新建内容相同的后缀项集,用来加入新元素,并且不改变之前的频繁项中的元素 newFreqSet = preFix.copy() # 后缀中增加新的item newFreqSet.add(basePat) # 频繁项集列表中加入扩充了的前缀 freqItemList.append(newFreqSet) # 获取item的条件模式基 condPattBases = findPrefixPath(basePat,headerTable[basePat][1]) # 利用item创建“条件FP树”和“新头指针表”,新头指针表中item和前缀同时出现的次数都满足最小支持度 myCondTree,myHead = createTree(condPattBases,minSup) # 条件树还有元素,还能对前缀进行扩充 if myHead != None: mineTree(myCondTree,myHead,minSup,newFreqSet,freqItemList)if __name__ == "__main__": dataSet = loadData() FpTree,headerTable = createTree(dataSet,3) # FpTree.disp() freqSetList = [] mineTree(FpTree,headerTable,3,set({}),freqSetList) print freqSetList算法主要步骤:
(1)第一次扫描数据库,找出满足支持度的item,建立item对应的头指针表,包含此item出现的次数(即指向item头节点的指针表);
(2)第二次扫描数据库,对每个trans过滤掉非频繁item,然后按item出现的次数从大到小排序,将排好序的序列中每个元素插入(部分合并,因为共用一些路径)到树中,并更新头指针表中对应的链表,建立FP-Tree;
(3)FP搜索:从原始头指针表中出现次数最少的item-level1开始,把其作为频繁项的前缀,找出其所有的前缀路径构成条件模式基,条件基作为输入构建条件FP-Tree和条件头指针表,条件头指针表中每个item-level2和之前的后缀item-level1共同出现的次数满足支持度,这里面的每个item-level2会和后缀item-level1组成新的频繁项集,然后分别把其中每一个item-level2作为新的后缀,找出其对应的条件模式基,利用新的条件模式构建新的条件FP-Tree和新的条件头指针表,若头指针表非空,则新头指针表里面的每个item-level3会和此其后缀item-level2、之前的后缀item-level1组成新的频繁项集;如为空,则停止递归,然后换一个新后缀item-level2重复重复,直到所有item-level2元素用完......接下来从原始头指针表中出现次数第二少的item-lwvel1出发,直到遍历完里面的所有item-level1,这样最终找到所有的频繁项集。
0 0
- 关联分析
- 关联分析
- 关联分析
- 关联分析
- 关联分析
- 关联分析算法
- 分析“关联”需仔细
- 关联规则分析
- 关联分析:Apriori
- 关联查询的分析
- 典型关联分析
- 关联分析算法
- 什么是关联分析?
- 数据挖掘 关联分析
- 典型关联分析
- 数据挖掘-关联分析
- 关联分析-Apriori算法
- Apriori关联分析
- 数据结构实验之查找五:平方之哈希表
- 数据结构::矩阵(二)--稀疏矩阵
- 设计模式学习笔记--前端控制器模式
- OpenCV学习笔记(十)双边滤波
- Solr全量索引、增量索引和定时增量索引配置
- 关联分析
- jquery datatable的使用的记录(自己使用的)
- juicer自定义函数使用方法(随便你用!!!)
- 婚姻:新报称中国年轻人掀"不婚独居潮":婚姻似乎没好处
- iscroll5做轮播滑动
- #OSG+VS#01
- sort,qsort函数
- 3809: Gty的二逼妹子序列 (莫队+树状数组)ps:强大的我没用分块,树状数组卡过去了哈哈
- 浅谈set的类型与应用