数据挖掘十大算法之Apriori算法原理及源码实现

来源:互联网 发布:suse linux 防火墙 编辑:程序博客网 时间:2024/06/14 18:20

一、基本概念

    频繁模式:指频繁地出现在数据集中的模式。例如,频繁地同时出现在交易数据集中的商品(如牛奶和面包)的集合就是频繁项集。

    支持度:支持度的公式是support(A->B) = P(A U B),即A和B同时出现的概率。

    置信度:置信度大的公式是confidence ( A-> B ) = P(A | B) = support ( A U B) / support ( A ),揭示的是A出现时,B出现的概率有多大。如果置信度为1,则A、B可进行捆绑销售了

二、Apriori算法的实现原理

    频繁项集数据挖掘的一个典型例子就是购物篮分析。该过程通过发现顾客放入购物篮中的商品之间的关联来分析顾客的行为,这样可以帮助零售商指定更好的销售策略。

    如何产生规则呢。可以分两步走。

  •     首先找出频繁集(frequent itemset)。所谓频繁集指满足最小支持度或置信度的集合。
  •     其次从频繁集中找出强规则(strong rules)。强规则指既满足最小支持度又满足最小置信度的规则。

    这其中有一个定理。即频繁集的子集也一定是频繁集。比如,如果{A,B,C}是一个3项的频繁集,则其子集{A,B},{B,C},{A,C}也一定是2项的频繁集。为方便,可以把含有k项的集合称之为k-itemsets.

    这里,我们给出具体的例子:

  1. 在算法的第一次迭代中,每个项都是候选1项集L1的成员,算法扫描所以的项,并对出现次数进行计数,然后计算每个项的支持度,若大于等于最小支持度,则存入L中
  2. 为了找到频繁二项集L2的集合,采用连接算法,两个L1进行连接,找到二项集,计算支持度,若大于等于最小支持度,则存入L中
  3. 依次类推,两个L2连接找到候选三项集,并计算支持度,若大于等于最小支持度,则存入L中
  4. 生成强规则
  5. 计算置信度,若大于等于最小置信度,则输出

三、源代码(Python实现)

<span style="font-size:14px;">'''Created on 2015-1-17@author: lzy'''class associationRule:    def __init__(self,dataSet):        self.sentences=map(set,dataSet)        self.minSupport=0.5        self.minConf=0.98        self.numSents=float(len(self.sentences))  #total number of the words        self.supportData={}                       #The support of all the words        self.L=[]        self.ruleList=[]                          #The words whose support >= minSupport    def createC1(self):        """create candidate itemsets of size 1 C1"""        """if word is not in C1,append it,then return map"""        C1=[]        for sentence in self.sentences:            for word in sentence:                if not [word] in C1:                    C1.append([word])        C1.sort()        return map(frozenset,C1)    def scan(self,Ck):        """generate frequent itemsets Lk from candidate itemsets Ck"""        wscnt={}         retList=[]        #calculate support for every itemset in Ck        for words in Ck:            for sentence in self.sentences:                if words.issubset(sentence):                    if not wscnt.has_key(words): wscnt[words]=1                    else: wscnt[words]+=1        for key in wscnt:            support=wscnt[key]/self.numSents #The value of the key divide by the total number            if support>=self.minSupport:                retList.append(key)            self.supportData[key]=support        self.L.append(retList)    def aprioriGen(self,Lk,k):        """the candidate generation: merge a pair of frequent (k-1)-itemsets         only if their first k-2 items are identical        """        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:                    retList.append(Lk[i]|Lk[j])        return retList    def apriori(self):        """generate a list of frequent itemsets"""        C1=self.createC1()        self.scan(C1)        k=2        while(k<=3):            Ck=self.aprioriGen(self.L[k-2],k)            self.scan(Ck)            k+=1         def generateRules(self):        """generate a list of rules"""        for i in range(1,len(self.L)):    #get only sets with two or more items            for freqSet in self.L[i]:                H1=[frozenset([word]) for word in freqSet]                if(i>1): self.rulesFromConseq(freqSet,H1)                else: self.calcConf(freqSet,H1)  #set with two items    def calcConf(self,freqSet,H):        """calculate confidence, eliminate some rules by confidence-based pruning"""        prunedH=[]        for conseq in H:            conf=self.supportData[freqSet]/self.supportData[freqSet-conseq]            if conf>=self.minConf:                print "%s --> %s, conf=%.3f"%(map(str,freqSet-conseq), map(str,conseq), conf)                self.ruleList.append((freqSet-conseq,conseq,conf))                prunedH.append(conseq)        return prunedH    def rulesFromConseq(self,freqSet,H):        """generate more association rules from freqSet+H"""        m=len(H[0])        if len(freqSet)>m+1:                #try further merging            Hmp1=self.aprioriGen(H,m+1)     #create new candidate Hm+1            hmp1=self.calcConf(freqSet,Hmp1)            if len(Hmp1)>1:                self.rulesFromConseq(freqSet,Hmp1)</span>

测试代码(Python实现)

<span style="font-size:14px;">'''Created on 2015-1-17@author: lzy'''import Aprioridef read_file(raw_file):    """read file"""    return [sorted(list(set(e.split()))) for e in             open(raw_file).read().strip().split('\n')]def main():    sentences=read_file('test.txt')    assrules=Apriori.associationRule(sentences)    assrules.apriori()    assrules.generateRules()if __name__=="__main__":    main()</span>

其中,测试数据集为:测试数据集

运行结果如下


四、源码分析

    createC1函数的作用是读取数据集中的每一个word

    scan函数的作用是计算每个word出现的次数,然后计算每个频繁1项集的支持度

    aprioriGen即是上文所提到的连接操作

    calcConf用于计算置信度

    rulesFromConseq用于产生更强的规则,例如考虑{I1,I2,I5}。其子集有{I1,I2}, {I1,I5}, {I2,I5}, {I1}, {I2}, {I5}。可以产生规则,{I1,I2}=> {I5} , {I1,I5}=> {I2} , {I2,I5} =>{I1} ,{I1} => {I2,I5} , {I2} =>{I1,I5} ,{I5} =>{I1,I2} 。

五、其他

    set与frozenset的区别:

  set是可变的,有add(),remove()等方法。既然是可变的,所以它不存在哈希值。

  frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。

  举例如下

fza=frozenset('a')
adict={fza:1,'b':2} #正确
setb=set('a')
bdict={setb:1,'b':2} #错误

<span style="font-size:14px;">fza=frozenset('a')adict={fza:1,'b':2} #正确setb=set('a')bdict={setb:1,'b':2} #错误</span>

0 0
原创粉丝点击