最近上数据挖掘的课程,其中学习到了频繁模式挖掘这一章,这章介绍了三种算法,Apriori、FP-Growth和Eclat算法;由于对于不同的数据来说,这三种算法的表现不同,所以我们本次就对这三种算法在不同情况下的效率进行对比。从而得出适合相应算法的情况。

GitHub:https://github.com/loyalzc/freqpattern

(一)算法原理

其中相应的算法原理在之前的博客中都有非常详细的介绍,这里就不再赘述,这里给出三种算法大概的介绍

但是这里给出每个算法的关键点:

1.1 Apriori算法:

  • 限制候选产生发现频繁项集
  • 重要性质:频繁项集所有非空子集也一定是频繁的。
  • 主要步骤:
  1. 连接
  2. 剪枝
  • 特点:需要多次扫描数据库,对于大规模数据效率很低!

Apriori算法原理详细介绍:http://www.cnblogs.com/90zeng/p/apriori.html

1.2 FP-Growth算法

  • 通过模式增长挖掘频繁模式
  • 主要步骤:
  1. 构建频繁模式树
  2. 构造条件模式基
  3. 挖掘频繁模式
  • 特点:两次扫描数据库,采用分治的策略有效降低搜索开销

FP-Growth算法原理详细介绍:http://www.cnblogs.com/datahunter/p/3903413.html

1.3 Eclat算法

  • 使用垂直格式挖掘频繁项集
  • 主要步骤:
  1. 将数据倒排{ item:TID_set }
  2. 通过求频繁k项集的交集来获取k+1项集
  • 特点:仅需要一次扫描数据库,TID集合很长的话需要消耗大量的内存和计算时间

Eclat算法原理详细介绍:http://www.cnblogs.com/catkins/p/5270484.html

(二)算法实现

由于各个博客给出的算法实现并不统一,而且本人在实现《机器学习实战》中FP-Growth算法的时候发现,在在创建FP-Tree时根据headTable中元素的支持度顺序的排序过程中,这个地方的排序方法写的有问题,当在模式稠密时,具有很多支持度相同的项集,书中的代码并没有考虑着一点,所以如果遇到支持度相同的项集那个就会出现一定的随机性,导致建树过程出错,最后的频繁项集结果会偏小,因此这里对改错误进行了纠正,在支持度相同时,添加了按照项集排序的规则,这样建立的FP-Tree才完全正确。

1.1 Apriori算法实现:

 1 # -*- coding: utf-8 -*-
 2 '''
 3 @author: Infaraway
 4 @time: 2017/4/15 12:54
 5 @Function:
 6 '''
 7 
 8 
 9 def init_c1(data_set_dict, min_support):
10     c1 = []
11     freq_dic = {}
12     for trans in data_set_dict:
13         for item in trans:
14             freq_dic[item] = freq_dic.get(item, 0) + data_set_dict[trans]
15     # 优化初始的集合,使不满足最小支持度的直接排除
16     c1 = [[k] for (k, v) in freq_dic.iteritems() if v >= min_support]
17     c1.sort()
18     return map(frozenset, c1)
19 
20 
21 def scan_data(data_set, ck, min_support, freq_items):
22     """
23     计算Ck中的项在数据集合中的支持度,剪枝过程
24     :param data_set:
25     :param ck:
26     :param min_support: 最小支持度
27     :param freq_items: 存储满足支持度的频繁项集
28     :return:
29     """
30     ss_cnt = {}
31     # 每次遍历全体数据集
32     for trans in data_set:
33         for item in ck:
34             # 对每一个候选项集, 检查是否是 term中的一部分(子集),即候选项能否得到支持
35             if item.issubset(trans):
36                 ss_cnt[item] = ss_cnt.get(item, 0) + 1
37     ret_list = []
38     for key in ss_cnt:
39         support = ss_cnt[key]  # 每个项的支持度
40         if support >= min_support:
41             ret_list.insert(0, key)  # 将满足最小支持度的项存入集合
42             freq_items[key] = support  #
43     return ret_list
44 
45 
46 def apriori_gen(lk, k):
47     """
48     由Lk的频繁项集生成新的候选项集  连接过程
49     :param lk:  频繁项集集合
50     :param k:  k 表示集合中所含的元素个数
51     :return: 候选项集集合
52     """
53     ret_list = []
54     for i in range(len(lk)):
55         for j in range(i+1, len(lk)):
56             l1 = list(lk[i])[:k-2]
57             l2 = list(lk[j])[:k-2]
58             l1.sort()
59             l2.sort()
60             if l1 == l2:
61                 ret_list.append(lk[i] | lk[j])  # 求并集
62     # retList.sort()
63     return ret_list
64 
65 
66 def apriori_zc(data_set, data_set_dict, min_support=5):
67     """
68     Apriori算法过程
69     :param data_set: 数据集
70     :param min_support: 最小支持度,默认值 0.5
71     :return:
72     """
73     c1 = init_c1(data_set_dict, min_support)
74     data = map(set, data_set)  # 将dataSet集合化,以满足scanD的格式要求
75     freq_items = {}
76     l1 = scan_data(data, c1, min_support, freq_items)  # 构建初始的频繁项集
77     l = [l1]
78     # 最初的L1中的每个项集含有一个元素,新生成的项集应该含有2个元素,所以 k=2
79     k = 2
80     while len(l[k - 2]) > 0:
81         ck = apriori_gen(l[k - 2], k)
82         lk = scan_data(data, ck, min_support, freq_items)
83         l.append(lk)
84         k += 1  # 新生成的项集中的元素个数应不断增加
85     return freq_items
View Code

相关文章:

  • 2022-01-10
  • 2022-12-23
  • 2022-12-23
  • 2022-01-18
  • 2021-12-30
  • 2021-11-22
  • 2021-12-25
  • 2021-12-12
猜你喜欢
  • 2021-05-29
  • 2021-05-26
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-27
相关资源
相似解决方案