• 数据关联分析 association analysis (Aprior算法,python代码)


    1基本概念

    购物篮事务(market basket transaction),如下表,表中每一行对应一个事务,包含唯一标识TID,和购买的商品集合。本文介绍一种成为关联分析(association analysis)的方法,这种方法,可以从下表可以提取出,{尿布}—>牛奶.

    clip_image002

    两个关键问题:1大型数据计算量很大。2发现的某种模式可能是虚假,偶然发生的。

    2问题定义

    把数据可以转换为如下表的二元表示,非二元不在本文讨论范围

    clip_image004

    项集

    clip_image006

    项集的支持度计数:

    clip_image008

    关联规则:

    clip_image010

    我们要发现,满足最小支持度与最小置信度的规则。

    l 频繁项集(frequent itemset):发现满足最小支持度阈值的所有项集,这些项集成为频繁项集。

    l 规则的产生:从上一步发现的频繁项集中提取所有高置信度的规则,这些规则成为强规则(strong rule)

    频繁项集的产生

    穷举法:

    利用格结构(lattice structure)产生所有候选项集(candidate itemset).

    clip_image012

    利用穷举法,计算每个候选项集的支持度计数。但是该方法计算量太大。

    clip_image014

    先验(apriori)原理:

    如果一个项集是频繁的,则的所有子集一定是频繁的。若某项集是非频繁的,则其所有的超级也一定是非频繁的。

    如下图,若{c,d,e}是频繁项集,则它的子集一定是频繁项集。

    clip_image016

    项集{a,b}是非频繁的,则其所有的超级也一定是非频繁的,如下图。

    clip_image018

    Aprior算法的频繁项集产生

    clip_image020

    1. 确定每个1-项集的支持度计数,删除不满足最小支持度的1-项集。(步骤1,2)

    2. 迭代:使用频繁(k-1)项集,产生新的候选k项集(步骤5)

    3. 为了对候选k项集计算支持度计数,再次扫描数据(6-10)

    4. 删去支持度小于最小支持度(minsup)的候选集

    5. 当Fk=NULL,结束。

    6. 候选集是所有频繁i项集的交际。i=1,2…

    clip_image022

    clip_image024方法:产生clip_image026(频繁k-项集)。(step5)

    函数aprior-gen的候选产生过程,合并一对频繁k-1项集,仅当他们前k-2个项都相同时,即

    clip_image028

    图例:clip_image030

    Python代码:

    def aprioriGen(Lk,k):#create ck(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:#比较i,j前k-1个项若相同,和合并它俩
                    retList.append(Lk[i] | Lk[j])#加入新的k项集 | stanf for union
        return retList
    支持度计数:算法(6-12)代码

    Python代码:

    def scanD(D,ck,minSupport):#dataset,a list of candidate set,最小支持率
        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
        
        numItem=float(len(D))
        retList=[]
        supportData={}
        for key in ssCnt:
            support=ssCnt[key]/numItem
            if support>=minSupport:
                retList.insert(0,key)
                supportData[key]=support
                
        return retList,supportData#返回频繁k项集,相应支持度

    频繁项集的产生:

    def apriori(dataSet,minSupport=0.5):
        C1=createC1(dataSet)
        D=map(set,dataSet)
        L1,supportData=scanD(D,C1,minSupport)#利用k项集生成频繁k项集(即满足最小支持率的k项集)
        L=[L1]#L保存所有频繁项集
        
        k=2
        while(len(L[k-2])>0):#直到频繁k-1项集为空
            Ck=aprioriGen(L[k-2],k)#利用频繁k-1项集 生成k项集
            Lk,supK= scanD(D,Ck,minSupport)
            supportData.update(supK)#保存新的频繁项集与其支持度
            L.append(Lk)#保存频繁k项集
            k+=1
        return L,supportData#返回所有频繁项集,与其相应的支持率

    规则产生(mining rules)

    定理:

    clip_image002

    例如下:若bcd ->a是低置信度的,则它的子代都是低置信度的。利用此定理可以避免不必要的计算,减少运算复杂度。

    clip_image004[4]

    算法流程如下:clip_image006[4]clip_image008[4]

     

    python代码:

    def calcConf(freqSet,H,supportData,brl,minConf=0.7):
        prunedH=[]
        for conseq in H:#后件中的每个元素
            conf=supportData[freqSet]/supportData[freqSet-conseq]
            if conf>=minConf:
                print freqSet-conseq,'-->',conseq,'conf:',conf
                brl.append((freqSet-conseq,conseq,conf))#添加入规则集中
                prunedH.append(conseq)#添加入被修剪过的H中
            
        return prunedH
    
    def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.7):
         
        m=len(H[0])#H是一系列后件长度相同的规则,所以取H0的长度即可
        if (len(freqSet)>m+1):
            Hmp1=aprioriGen(H,m+1)
            Hmp1=calcConf(freqSet,Hmp1,supportData,brl,minConf)
            if (len(Hmp1)>1):
                rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)
                
    def generateRules(L,supportData,minConf=0.7):
        import pdb
        pdb.set_trace()
        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

    整个prior算法的python代码

    算法函数:

    # -*- coding: utf-8 -*-
    """
    Created on Wed Dec 04 22:25:57 2013
    
    @author: Administrator
    """
    
    def loadDataSet():
        return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
    
    def createC1(dataSet):#产生单个item的集合
        C1=[]
        for transaction in dataSet:
            for item in transaction: 
                if not [item] in C1:
                    C1.append([item])
        
        C1.sort()
        
        return map(frozenset,C1)#给C1.list每个元素执行函数
        
        
    def scanD(D,ck,minSupport):#dataset,a list of candidate set,最小支持率
        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
        
        numItem=float(len(D))
        retList=[]
        supportData={}
        for key in ssCnt:
            support=ssCnt[key]/numItem
            if support>=minSupport:
                retList.insert(0,key)
                supportData[key]=support
                
        return retList,supportData#返回频繁k项集,相应支持度
            
    
    def aprioriGen(Lk,k):#create ck(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:#比较i,j前k-1个项若相同,和合并它俩
                    retList.append(Lk[i] | Lk[j])#加入新的k项集 | stanf for union
        return retList
        
        
    def apriori(dataSet,minSupport=0.5):
        C1=createC1(dataSet)
        D=map(set,dataSet)
        L1,supportData=scanD(D,C1,minSupport)#利用k项集生成频繁k项集(即满足最小支持率的k项集)
        L=[L1]#L保存所有频繁项集
        
        k=2
        while(len(L[k-2])>0):#直到频繁k-1项集为空
            Ck=aprioriGen(L[k-2],k)#利用频繁k-1项集 生成k项集
            Lk,supK= scanD(D,Ck,minSupport)
            supportData.update(supK)#保存新的频繁项集与其支持度
            L.append(Lk)#保存频繁k项集
            k+=1
        return L,supportData#返回所有频繁项集,与其相应的支持率
            
        
    def calcConf(freqSet,H,supportData,brl,minConf=0.7):
        prunedH=[]
        for conseq in H:#后件中的每个元素
            conf=supportData[freqSet]/supportData[freqSet-conseq]
            if conf>=minConf:
                print freqSet-conseq,'-->',conseq,'conf:',conf
                brl.append((freqSet-conseq,conseq,conf))#添加入规则集中
                prunedH.append(conseq)#添加入被修剪过的H中
            
        return prunedH
    
    def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.7):
         
        m=len(H[0])#H是一系列后件长度相同的规则,所以取H0的长度即可
        if (len(freqSet)>m+1):
            Hmp1=aprioriGen(H,m+1)
            Hmp1=calcConf(freqSet,Hmp1,supportData,brl,minConf)
            if (len(Hmp1)>1):
                rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)
                
    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

    测试代码:

    import apriori
    dataSet=apriori.loadDataSet()
    
    C1=apriori.createC1(dataSet)
    
    D=map(set,dataSet)
    L1,suppData0=apriori.scanD(D,C1,0.5)
    
    L,suppData=apriori.apriori(dataSet)
    
    print L
    rules=apriori.generateRules(L,suppData,minConf=0.5)

    参数文献:

    1数据挖掘导论

    2machine learning in action

  • 相关阅读:
    Pycharm在线/手动离线安装第三方库-以scapy为例(本地离线添加已经安装的第三方库通过添加Path实现)
    python+splinter实现12306网站刷票并自动购票流程
    利用RELK进行日志收集
    web安全之文件上传漏洞攻击与防范方法
    C# 使用 CancellationTokenSource 终止线程
    ASP.NET MVC 下拉框的传值的两种方式
    SQL Server(解决问题)已成功与服务器建立连接,但是在登录过程中发生错误。(provider: Shared Memory Provider, error:0
    C# .net中json字符串和对象之间的转化方法
    asp.net 未能加载文件或程序集“WebApi”或它的某一个依赖项。试图加载格式不正确的程序。
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/Dzhouqi/p/3464995.html
Copyright © 2020-2023  润新知