Apriori算法

#coding=utf-8
def load_data():
    return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
def create_c1(data):
    #把数据中单个元素转成列表格式,且不重复。
    c1=[]
    for transaction in data:
        for item in transaction:
            if not [item] in c1:
                c1.append([item])
    c1.sort()
    return map(frozenset,c1)
def prob(set_data,c1,min_frequency):
    #计算各种组合在数据中出现的概率并选出大于最小概率的组合
    ss_cnt={}
    for tid in set_data:
        for can in c1:
            if can.issubset(tid):
                #判断can是否在tid中
                if not ss_cnt.has_key(can):ss_cnt[can]=1
                #如果字典中不含can,则加进去并初始值为1
                else:ss_cnt[can]+=1
                #如果已经存在了,则对其出现次数进行统计
    num_items=float(len(set_data))
    #就是集合的数量
    ret_list=[]
    element_frequency={}
    for key in ss_cnt:
        frequency=ss_cnt[key]/num_items
        #也就单个元素出现的频率
        if frequency>=min_frequency:
            #判断成立的话就在ret_list中首位插入key
            ret_list.insert(0,key)
        element_frequency[key]=frequency
    return ret_list,element_frequency

def p_and_c(lk,k):
    #进行排列组合
    #步骤:根据最初的到的C1 [1,2,3,5] 俩俩组合 成k=2时的ck 即c2
    #再根据c2 [[1,2],[1,3],[1,5],[2,3],[2,5],[3,5]] 三三组合成 k=3时的ck 即 c3
    #c4即[1,2,3,5]
    ret_list=[]
    len_lk=len(lk)
    for i in range(len_lk):
        for j in range(i+1,len_lk):
            l1=list(lk[i])[:k-2]
            l2=list(lk[j])[:k-2]
            print l1,l2
            l1.sort();l2.sort()
            if l1==l2:
                #这里用并集进行组合,而不用itertools.combinations
                #是因为,每次组合都是在前者已经筛选过概率的基础上进行的
                #这样可以减少计算量
                ret_list.append(lk[i]|lk[j])
                #并集
    return ret_list
def apriori(data,min_frequency=0.5):
    c1=create_c1(data)
    d=map(set,data)
    l1,element_frequency=prob(d,c1,min_frequency)
    l=[l1]
    k=2
    #k即单个组合中元素数量
    while len(l[k-2]) >0:
        pc=p_and_c(l[k-2],k)
        #获取组合
        lk,supk=prob(d,pc,min_frequency)
        #计算组合概率并返回大于最小概率的
        element_frequency.update(supk)
        #更新并添加新的组合
        l.append(lk)
        print l
        k+=1
    return l,element_frequency
def test():
    data=load_data()
    l,s=apriori(data)
    print '\n',l,'\n',s
test()
def generate_rules(group,element_frequency,min_conf=0.7):
    '''筛选出出现条件概率在min_conf以上的组合'''
    #即1出现的情况下3出现的概率,选出这种概率在min_conf上的
    result=[]
    #大规则列表
    for i in range(1,len(group)):
        #之所以从1开始是因为group[0]是单个元素,这也是由数据样本定的。
        #数据量足够大,也可以从0开始
        for freqset in group[i]:
            #遍历上面函数计算出的大于某一概率的组合
            #分开组合中各元素,打包成列表
            h1= [frozenset([item]) for item in freqset]
          #  print h1
            if i > 1:
                #i>1是因为组合内元素数超过2了
                rules_from_conseq(freqset,h1,element_frequency,result,min_conf)
            else:
                calculate_probability(freqset,h1,element_frequency,result,min_conf)
    return result
def calculate_probability(freqset,h,element_frequency,result,min_conf=0.7):
    '''计算条件概率'''
    pruned_h=[]
    #修剪
    for conseq in h:
        #遍历组合计算以组合中非conseq为条件的概率
        #即组合[2,3],conseq=2,则计算以3为前提下出现组合[2,3]的概率
        probability=element_frequency[freqset]/element_frequency[freqset-conseq]
        if probability>=min_conf:
            #若条件概率大于阈值,则取这个组合并附加到结果里
            #并把conseq附加修剪列表,说明该元素不适合做前提条件
            print freqset-conseq,'--->',conseq,'probability:',probability
            result.append((freqset-conseq,conseq,probability))
            pruned_h.append(conseq)
    return pruned_h
def rules_from_conseq(freqset,h,element_frequency,result,min_conf=0.7):
    '''计算上面函数筛除的元素间是否存在大于指定概率的组合'''
    m=len(h[0])
    #这里m=1
    if len(freqset)>(m+1):
        #当组合中元素总数大于2时,将组合内所有元素两两组合
        #然后再计算条件概率
        hmp1=p_and_c(h,m+1)
        hmp1=calculate_probability(freqset,hmp1,element_frequency,result,min_conf)
        #返回的hmp1是不适合做前提条件的元素
        if len(hmp1)>1:
            #若hmp1大于1,则计算这一集合元素间是否存在大于阈值的组合
            rules_from_conseq(freqset,hmp1,element_frequency,result,min_conf)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值