Educoder-候选剪枝Apriori算法

任务描述

本关任务:编写一个能实现候选剪枝的小程序。

相关知识

为了完成本关任务,你需要掌握:1.Apripori 算法候选剪枝,2.Apripori 算法候选剪枝代码实现。

Apripori 算法候选剪枝

候选集的剪枝操作基于两个定理: 定理1:若某项集是频繁项集,则它的所有子集都是频繁项集。 例如:{a, b, c}是频繁项集,则{a}、{b}、{c}、{a, b}、{b, c}、{a, c}也是频繁项集。

定理2:若某项集不是频繁项集,则它的所有超集都不是频繁项集。 例如:{a, b}不是频繁项集,则{a, b, c}也不是频繁项集。

基于以上两个定理,我们需要对进行连接操作后的候选集进行剪枝操作,减小搜索空间。

剪枝:Ck+1​ 中的某项集 c ,若 c 的某大小为 k 的子集 s 不存在于Lk​ ,则将 cCk+1 删除。

上图为剪枝过程例图,蓝色表示项集在频繁3项集中,可以看到在生成的候选4项集 ABCE 中,其子集ABE 并不在频繁3项集中,所以剪枝删去。

Apripori 算法候选剪枝代码实现

剪枝的核心在于检查候选项集 Ck​ 的子集是否都在频繁项集 Lk−1​ 中。 检查函数主体如下:

在候选生成中添加剪枝伪代码示例

比起无剪枝的候选生成,多了一个判断该候选项的子集是否都在Lk-1中的条件判断。

根据提示,在右侧编辑器补充代码,对生成的候选集剪枝。

预期输出:2

class Apriori():
    def create_c1(self, dataset):  # 遍历整个数据集生成c1候选集
        c1 = set()
        for i in dataset:
            for j in i:
                item = frozenset([j])
                c1.add(item)
        return c1
    
    def has_infrequent_setdata(self, Ck_item, Lk_1):  
        ##########begin##########
        # 检查候选项Ck_item的子集是否都在Lk-1中函数定义
        for item in Ck_item:
            sub_Ck = Ck_item - frozenset([item])
            if sub_Ck not in Lk_1:
                return False
        ##########end##########
        return True
    
    def create_ck(self, Lk_1, size):  # 通过频繁项集Lk-1创建ck候选项集
        Ck = set()
        l = len(Lk_1)
        lk_list = list(Lk_1)
        for i in range(l):
            for j in range(i + 1, l):  
                ##########begin##########
                # 两次遍历Lk-1,找出前n-1个元素相同的项
                l1 = list(lk_list[i])
                l2 = list(lk_list[j])
                l1.sort()
                l2.sort() #小写英文字母也可以排序
                ##########end##########
                if l1[0:size - 2] == l2[0:size - 2]:  
                    ##########begin##########
                    #只有最后一项不同时,生成下一候选项
                    #检查该候选项的子集是否都在Lk-1中
                    Ck_item = lk_list[i] | lk_list[j]
                    if self.has_infrequent_setdata(Ck_item, Lk_1):
                        Ck.add(Ck_item)
                        
                    ##########end##########
        return Ck

    

    def generate_lk_by_ck_ergodic(self, data_set, ck, min_support, support_data): 
        item_count = {}  
        Lk = set()
        for t in data_set:  
            for item in ck:  
                if item.issubset(t):
                    if item not in item_count:
                        item_count[item] = 1
                    else:
                        item_count[item] += 1
        t_num = float(len(data_set))
        for item in item_count:  
            if item_count[item] / t_num >= min_support:
                Lk.add(item)
                support_data[item] = item_count[item]
        return Lk


if __name__ == "__main__":

    data = [['a','c','e'],['b','d'],['b','c'],['a','b','c','d'],['a','b'],['b','c'],['a','b'],
            ['a','b','c','e'],['a','b','c'],['a','c','e']]
    apriori = Apriori()
    support_data = {}
    c1 = apriori.create_c1(data)
    l1 = apriori.generate_lk_by_ck_ergodic(data_set=data, ck=c1, min_support=0.2, support_data=support_data)
    c2 = apriori.create_ck(l1,size=2)
    l2 = apriori.generate_lk_by_ck_ergodic(data_set=data,ck=c2,min_support=0.2,support_data=support_data)
    c3 = apriori.create_ck(l2, size=3)
    print(len(c3))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值