summary:
- 关联分析是用于发现大数据集中元素间有趣关系的一个工具集,可以采用两种方式来量化这些有趣的关系。第一种方式是频繁项集,它会给出经常出现在一起的元素项;第二种方式是关联规则,每条关联规则意味着元素项之间“如果……那么”的关系。
- 发现元素项间不同的组合是个十分耗时的任务,不可避免需要大量昂贵的计算资源,这就需要更智能的方法在合理时间范围内找到频繁项集。
- 使用Apriori原理可以减少在数据库上进行检查的集合的数目。Apriori算法从单元素项集开始,通过组合满足最小支持度要求的项集来形成更大的集合。
- 缺点:每次增加频繁集的大学,Apriori算法都会重新扫描整个数据集。
- 准备数据:标称型或数值型数据类型都可以,因为我们只保存集合。
from numpy import * def loadDataSet(): return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]] dataSet=loadDataSet() dataSet def createC1(dataSet): #生成只包含一个元素的项集的集合C1 C1 = [] for transaction in dataSet: for item in transaction: if not [item] in C1: C1.append([item]) C1.sort() return map(frozenset, C1)#use frozen set so we #can use it as a key in a dict C1=createC1(dataSet) C1 D=map(set,dataSet) D #计算Ck的项集的在数据集D中的支持度support,并检查数据确保每个项集都是频繁的 def scanD(D, Ck, minSupport): """ D:Lst[frozenset] Ck:Lst[frozenset] minSupport:int """ ssCnt = {} #统计Ck中的项在D中的项中出现的次数 for tid in D: for can in Ck: if can.issubset(tid): #如果can是tid的子集 ssCnt[can]=ssCnt.get(can,0)+1 # if can.issubset(tid): # if not ssCnt.has_key(can): ssCnt[can]=1 # else: ssCnt[can] += 1 numItems = float(len(D)) #D中共有多少条记录 retList = [] supportData = {} for key in ssCnt: support = ssCnt[key]/numItems #计算支持度:数据集中包含该项集的记录所占的比例 if support >= minSupport: retList.append(key) # retList.insert(0,key) supportData[key] = support return retList, supportData L1,suppData0=scanD(D,C1,0.5) print(L1) print(suppData0) def aprioriGen(Lk, k): #creates Ck:这里k表示一个项集中包含几个元素 """ Lk: List(frozenset) """ 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: #if first k-2 elements are equal retList.append(Lk[i] | Lk[j]) #set union """ 判断Lk集合的前k-2个元素相同,然后将Lk[i],Lk[j]合并 这就能保证后面生成的L(k+1)集合中的项集中的元素个数为k+1 这里k-2用于定位,举个栗子,当k=3,Lk=[{1,2},{1,3},{1,5},{2,3},{2,5},{3,5}] 此时就判断Lk[i][1]和Lk[][1]即项集的第1个元素是否相等来决定是否将它们合并 从而retList=[{1,2,3},{1,3,5},{1,2,5},{2,3,5}] 若k=4,就判断Lk[i]和Lk[j]的前2个元素是否相等, Lk是输入,所有项集的元素都是k-1个 因为我们要生成含有k个元素的所有项集的集合retList 所以需要前k-2个元素相等,最后一个元素不相等,这样合并起来刚好有k个元素 """ return retList def apriori(dataSet, minSupport = 0.5): C1 = createC1(dataSet) D = map(set, dataSet) L1, supportData = scanD(D, C1, minSupport) L = [L1] k = 2 #下面利用L(k-1)来构建L(k),并添加新支持度字典数据 while (len(L[k-2]) > 0): #当集合中项的个数大于0时 Ck = aprioriGen(L[k-2], k) #构建一个k个项组成的候选项集的列表 Lk, supK = scanD(D, Ck, minSupport)#scan DB to get Lk supportData.update(supK) #将生成的新的支持度的字典添加进原来的包含支持度的字典中 L.append(Lk) # k += 1 #k用于定位到相应的L的位置上,即当计算L2时定位到L[0],因为L[0]表示的是L1 return L, supportData L,suppData=apriori(dataSet,minSupport = 0.5) print(L) print(suppData) aprioriGen(L[0], 2) L,suppData=apriori(dataSet,minSupport=0.7) print(L) print(suppData) def generateRules(L, supportData, minConf=0.7): #supportData is a dict coming from scanD bigRuleList = [] for i in range(1, len(L)):#only get the sets with two or more items i=2 for freqSet in L[i]: H = [frozenset([item]) for item in freqSet] if (i > 1): rulesFromConseq(freqSet, H, supportData, bigRuleList, minConf) """ 当项集中的元素个数大于2时,调用rulesFromConseq rulesFromConseq: 调用aprioriGen来生成conseq,便于生成不重复的关联规则 根据关联规则调用calcConf计算conf """ else: calcConf(freqSet, H, supportData, bigRuleList, minConf) """ 当项集中的元素个数等于2时,调用calcConf(筛选大于minconf的项集) """ return bigRuleList def calcConf(freqSet, H, supportData, brl, minConf=0.7): prunedH = [] #create new list to return for conseq in H: conf = supportData[freqSet]/supportData[freqSet-conseq] #calc confidence if conf >= minConf: print(freqSet-conseq,'-->',conseq,'conf:',conf) brl.append((freqSet-conseq, conseq, conf)) prunedH.append(conseq) return prunedH def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7): m = len(H[0]) if (len(freqSet) > (m + 1)): #try further merging Hmp1 = aprioriGen(H, m+1)#create Hm+1 new candidates Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf) if (len(Hmp1) > 1): #need at least two sets to merge #再对大于1个元素的频繁项集再细分计算关联规则 rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf) def pntRules(ruleList, itemMeaning): for ruleTup in ruleList: for item in ruleTup[0]: print itemMeaning[item] print " -------->" for item in ruleTup[1]: print itemMeaning[item] print "confidence: %f" % ruleTup[2] print #print a blank line L,suppData=apriori(dataSet,minSupport = 0.5) rules=generateRules(L,suppData,minConf=0.7)
算法介绍
算法利用Apriori原理,第1步,得到频繁集(计算支持度);第2步,从频繁集中挖掘关联规则(计算可信度)。
- 支持度support:数据集中包含该项集的记录占总记录的比例,即用于度量一个集合在原始数据种出现的频率
- 可信度confidence:一条规则P→H的可信度的计算公式为 support({P,H})/support({P})
- 频繁集frequent item sets:是指经常出现在一块的物品的集合
- 关联规则association rules:是指两个物品间可能存在很强的关系
Apriori原理是指,一个项集是频繁的,那么这个项集的子集也是频繁的;反过来,一个项集是非频繁的,那么包含这个项集的超集也是非频繁的。利用Apriori原理可以减少在数据库上进行检查的集合的数目。
应用于购物(比如关联分析中著名的例子是啤酒与尿布,说的是美国中西部的一家连锁店发现,男人们会在周四购买尿布和啤酒),还可以应用于搜索引擎中的查询词之间的关联规则。
示例:发现毒蘑菇的相似特征
mushroom.dat的前几行如下:
1 3 9 13 23 25 34 36 38 40 52 54 59 63 67 76 85 86 90 93 98 107 113
2 3 9 14 23 26 34 36 39 40 52 55 59 63 67 76 85 86 90 93 99 108 114
2 4 9 15 23 27 34 36 39 41 52 55 59 63 67 76 85 86 90 93 99 108 115
1 3 10 15 23 25 34 36 38 41 52 54 59 63 67 76 85 86 90 93 98 107 113
2 3 9 16 24 28 34 37 39 40 53 54 59 63 67 76 85 86 90 94 99 109 114
第1个特征的值为1和2分别表示有毒和无毒 。下一个特征是蘑菇伞的形状,有六种可能的值,分别用整数3-8表示。
为了找到毒蘑菇中存在的公共特征,可以运用Apriori算法来寻找包含特征值为2的频繁项集。
mushDatSet=[line.split() for line in open('mushroom.dat').readlines()]
L,suppData=apriori.apriori(mushDatSet,minSupport=0.3)
for item in L[1]:
if item.intersection('2'):print(item) #查看与特征值2相交的item
结果如下:
frozenset(['2', '59']) frozenset(['39', '2']) frozenset(['2', '67']) frozenset(['2', '34']) frozenset(['2', '23']) frozenset(['2', '86']) frozenset(['76', '2']) frozenset(['90', '2']) frozenset(['2', '53']) frozenset(['93', '2']) frozenset(['63', '2']) frozenset(['2', '28']) frozenset(['2', '85']) frozenset(['2', '36'])
接下来你需要观察这些特征,以便了解毒蘑菇的哪些方面,如果看到其中任何一个特征就不要吃这些蘑菇了。
当然,尽管上述这些特征在毒蘑菇中很普遍,但是没有这些特征并不意味着该蘑菇就是无毒可食用的。
示例:发现国会投票中的模式(略)
需要注册自己的key,故略去。
注:
- python中frozenset类型,是指被“冰冻”的集合,就是说它们是不可改变的,用户不能修改它们。frozenset和set的还有个区别是frozenset可以作为字典的键值使用。
- python中的List.append(obj),List.extend(obj),List.insert(index,obj)之间的区别是,append是在列表末尾添加一个新元素obj,extend是在列表末尾添加obj中的所有元素,inset是在特定的位置添加一个新元素。
- 参照该页面了解votesmart包。
- 有一个组织(致力于将政府数据公开化的组织)是智能投票工程Project Vote Smart,它提供了一个公共的API,可以方便我们从votesmart.org获取数据。第一,安装python-votesmart,第二,获得API key(需要在http://votesmart.org/share/api/register申请自己的key),这样就可以使用votesmartAPI了。
- python中set集合运算