数据挖掘与机器学习:Apripori算法
目录
第一关:候选生成
任务描述:
相关知识:
一、Apripori算法候选生成:
二、Apripori算法候选生成代码实现:
编程要求:
测试说明:
第二关:候选剪枝
任务描述:
相关知识:
Apripori算法候选剪枝:
Apripori算法候选剪枝代码实现:
编程要求:
测试说明:
第三关:基于遍历的支持度计算
任务描述:
相关知识:
一、基于遍历的支持度计算:
二、基于遍历的支持度计算代码实现:
编程要求:
测试说明:
第四关:基于hash的支持度计算
任务描述:
相关知识:
一、基于hash的支持度计算:
二、基于hash的支持度计算代码实现:
编程要求:
测试说明:
第一关:候选生成
任务描述:
本关任务:编写一个能实现Apripori算法候选生成的小程序。
相关知识:
为了完成本关任务,你需要掌握:1.Apripori 算法候选生成,2.Apripori 算法候选生成代码实现。
一、Apripori算法候选生成:
Apripori算法利用自连接生成候选集:
自连接:对Lk
中的2个k项集l1
和l2
,若l1
和l2
有且仅有1个项不同,则将l1
∪l2
加入Ck+1
。
直观理解:生成可能的(k+1)项集:
上图为频繁3项集L3
生成候选4项集C4
过程示例,可以看到L3
中的2个3项集ABC
和ABD
有且仅有1个项不同,则将 ABC
∪ABD
=ABCD
加入C4
。
二、Apripori算法候选生成代码实现:
Apripori 算法候选1项集生成函数如下:
def create_c1(self, dataset): # 遍历整个数据集生成c1候选集c1 = set()for i in dataset:for j in i:item = frozenset([j])c1.add(item)return c1
其中 dataset 为数据集列表。
Apripori 算法候选 k 项集生成函数(无剪枝操作)代码思路如下:
- 创建Ck集合。
- 获取Lk_1的长度。
- 将Lk_1转换为列表。
- 两次遍历Lk-1,找出前n-1个元素相同的项。
- 只有最后一项不同时,生成下一候选项。
- 返回Ck集合。
伪代码示例:
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): # 两次遍历Lk-1,找出前n-1个元素相同的项# 只有最后一项不同时,生成下一候选项return Ck
编程要求:
根据提示,在右侧编辑器补充代码,生成候选3项集C3
。
测试说明:
平台会对你编写的代码进行测试:
预期输出:4
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 c1def 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个元素相同的项##########end##########if l1[0:size - 2] == l2[0:size - 2]: ##########begin###########只有最后一项不同时,生成下一候选项##########end##########return Ckdef 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] = 1else:item_count[item] += 1t_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 Lkif __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))
通过代码:
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 c1def 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###########只有最后一项不同时,生成下一候选项Ck_item = lk_list[i] | lk_list[j]Ck.add(Ck_item)##########end##########return Ckdef 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] = 1else:item_count[item] += 1t_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 Lkif __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))
第二关:候选剪枝
任务描述:
本关任务:编写一个能实现候选剪枝的小程序。
相关知识:
为了完成本关任务,你需要掌握: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
,则将 c
从 Ck+1
删除。
上图为剪枝过程例图,蓝色表示项集在频繁3项集中,可以看到在生成的候选4项集 ABCE
中,其子集ABE
并不在频繁3项集中,所以剪枝删去。
Apripori算法候选剪枝代码实现:
剪枝的核心在于检查候选项集 Ck
的子集是否都在频繁项集 Lk−1
中。 检查函数主体如下:
def has_infrequent_subset(self, Ck_item, Lk_1): # 检查候选项Ck_item的子集是否都在Lk-1中for item in Ck_item:sub_Ck = Ck_item - frozenset([item])#进行条件判断,如果存在候选项Ck_item子集不在Lk-1中则返回Falsereturn 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): # 两次遍历Lk-1,找出前n-1个元素相同的项# 只有最后一项不同时,生成下一候选项# 检查该候选项的子集是否都在Lk-1中Ck.add(Ck_item)return Ck
比起无剪枝的候选生成,多了一个判断该候选项的子集是否都在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 c1def has_infrequent_subset(self, Ck_item, Lk_1): ##########begin########### 检查候选项Ck_item的子集是否都在Lk-1中函数定义##########end##########return Truedef 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个元素相同的项##########end##########if l1[0:size - 2] == l2[0:size - 2]: ##########begin###########只有最后一项不同时,生成下一候选项#检查该候选项的子集是否都在Lk-1中##########end##########return Ckdef 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] = 1else:item_count[item] += 1t_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 Lkif __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))
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 c1def has_infrequent_subset(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 Truedef 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_subset(Ck_item, Lk_1):Ck.add(Ck_item)##########end##########return Ckdef 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] = 1else:item_count[item] += 1t_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 Lkif __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))
第三关:基于遍历的支持度计算
任务描述:
本关任务:编写一个能实现基于遍历的支持度计算的小程序。
相关知识:
为了完成本关任务,你需要掌握:1.基于遍历的支持度计算,2.基于遍历的支持度计算代码实现。
一、基于遍历的支持度计算:
二、基于遍历的支持度计算代码实现:
基于遍历的支持度计算函数如下:
def generate_lk_by_ck_ergodic(self, data_set, ck, min_support, support_data): # 通过候选项ck生成lk,基于遍历的支持度计算并将各频繁项的支持度保存到support_data字典中item_count = {} # 用于标记各候选项在数据集出现的次数Lk = set()for t in tqdm(data_set): # 遍历数据集for item in ck: #检查候选集ck中的每一项是否出现在事务t中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
其中 data_set 为数据集,ck 为候选 k 项集,min_support为最小支持度, support_data 为各项的支持度记录字典。遍历数据集for
循环中检查候选集ck中的每一项是否出现在事务t中请同学自行完成。
编程要求:
根据提示,在右侧编辑器补充代码,使用遍历计算支持度。
测试说明:
平台会对你编写的代码进行测试:
预期输出:6
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 c1def 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): # 两次遍历Lk-1,找出前n-1个元素相同的项l1 = list(lk_list[i])l2 = list(lk_list[j])l1.sort()l2.sort()if l1[0:size - 2] == l2[0:size - 2]: # 只有最后一项不同时,生成下一候选项Ck_item = lk_list[i] | lk_list[j]if self.has_infrequent_subset(Ck_item, Lk_1): # 检查该候选项的子集是否都在Lk-1中Ck.add(Ck_item)return Ckdef has_infrequent_subset(self, Ck_item, Lk_1): # 检查候选项Ck_item的子集是否都在Lk-1中for item in Ck_item:sub_Ck = Ck_item - frozenset([item])if sub_Ck not in Lk_1:return Falsereturn Truedef generate_lk_by_ck_ergodic(self, data_set, ck, min_support, support_data): # 通过候选项ck生成lk,基于遍历的支持度计算并将各频繁项的支持度保存到support_data字典中item_count = {} # 用于标记各候选项在数据集出现的次数Lk = set()# 基于遍历的支持度计算for t in data_set: # 遍历数据集for item in ck:##########begin########### 检查候选集ck中的每一项是否出现在事务t中##########end##########t_num = float(len(data_set))for item in item_count:##########begin########### 将满足支持度的候选项添加到频繁项集中##########end##########return Lkif __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)print(len(l2))
通过代码:
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 c1def 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): # 两次遍历Lk-1,找出前n-1个元素相同的项l1 = list(lk_list[i])l2 = list(lk_list[j])l1.sort()l2.sort()if l1[0:size - 2] == l2[0:size - 2]: # 只有最后一项不同时,生成下一候选项Ck_item = lk_list[i] | lk_list[j]if self.has_infrequent_subset(Ck_item, Lk_1): # 检查该候选项的子集是否都在Lk-1中Ck.add(Ck_item)return Ckdef has_infrequent_subset(self, Ck_item, Lk_1): # 检查候选项Ck_item的子集是否都在Lk-1中for item in Ck_item:sub_Ck = Ck_item - frozenset([item])if sub_Ck not in Lk_1:return Falsereturn Truedef generate_lk_by_ck_ergodic(self, data_set, ck, min_support, support_data): # 通过候选项ck生成lk,基于遍历的支持度计算并将各频繁项的支持度保存到support_data字典中item_count = {} # 用于标记各候选项在数据集出现的次数Lk = set()# 基于遍历的支持度计算for t in data_set: # 遍历数据集for item in ck:##########begin########### 检查候选集ck中的每一项是否出现在事务t中if item.issubset(t):if item not in item_count:item_count[item] = 1else:item_count[item] += 1##########end##########t_num = float(len(data_set))for item in item_count:##########begin########### 将满足支持度的候选项添加到频繁项集中if item_count[item] / t_num >= min_support:Lk.add(item)support_data[item] = item_count[item]##########end##########return Lkif __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)print(len(l2))
第四关:基于hash的支持度计算
任务描述:
本关任务:编写一个能实现基于 hash 的支持度计算的小程序。
相关知识:
为了完成本关任务,你需要掌握:1.基于 hash 的支持度计算,2.基于 hash 的支持度计算代码实现。
一、基于hash的支持度计算:
基于遍历的支持度计算非常耗时间,而基于 hash 的支持度计算可以将所有候选项集以 hash 结构中,每条事务只需要匹配其对应桶里的候选项集,从而节省时间开销。
假设有15个候选3-项集: {1 4 5}, {1 2 4}, {4 5 7}, {1 2 5}, {4 5 8}, {1 5 9}, {1 3 6}, {2 3 4}, {5 6 7}, {3 4 5}, {3 5 6}, {3 5 7}, {6 8 9}, {3 6 7}, {3 6 8}
可构建如下 hash 树: 树的每个内部结点都使用hash函数h(p)=p mod 3
来确定应当沿着当前结点的哪个分支向下。例如,项 1,4 和 7 应当散列到相同的分支(即最左分支),因为除以 3 之后它们都具有相同的余数。所有的候选项集都存放在hash树的叶结点中。下图图中显示的 hash 树包含 15个候选 3-项集,分布在 9 个叶结点中。
构建过程如下:
给定一个事务 t , 跟哪些候选 3 项集匹配?例如下图中的例子:
匹配过程如下:
考虑一个事务 t={1,2,3,5,6} 。为了更新候选项集的支持度计数,必须这样遍历 Hash 树:所有包含属于事务 t 的候选 3 -项集的叶结点至少访问一次。
注意:包含在t中的候选 3 -项集必须以项 1,2或3 开始,如上图中第一层前缀结构所示。这样,在Hash树的根结点,事务中的项 1,2 和 3 将分别散列。项 1 被散列到根结点的左子女,项 2 被散列到中间子女,而项 3 被散列到右子女。在树的下一层,事务根据上图中的第二层结构列出的第二项进行散列。
例如,在根结点散列项1之后,散列事务的项 2、3 和 5 。项 2 和 5 散列到中间子女,而 3 散列到右子女,如上图所示。继续该过程,直至到达 Hash 树的叶结点。存放在被访问的叶结点中的候选项集与事务进行比较,如果候选项集是该事务的子集,则增加它的支持度计数。在这个例子中,访问了 9 个叶结点中的 5 个, 15 个项集中的 9 个与事务进行比较。可以看到匹配过程只需要进行 11 次比较。
二、基于hash的支持度计算代码实现:
基于 hash 的支持度计算关键在于 hash 树的构建。 首先构建节点类:
#Hash节点类定义
class Hash_node:def __init__(self):self.children = {} #指向子节点的指针self.Leaf_status = True #了解当前节点是否为叶子节点的状态self.bucket = {} #在储存桶中包含项目集
然后构建hash树类:
#构造得到Hash树类
class HashTree:# class constructordef __init__(self, max_leaf_count, max_child_count):self.root = Hash_node()self.max_leaf_count = max_leaf_countself.max_child_count = max_child_countself.frequent_itemsets = []# 进行递归插入以生成hashtreedef recursively_insert(self, node, itemset, index, count):if index == len(itemset):if itemset in node.bucket:node.bucket[itemset] += countelse:node.bucket[itemset] = countreturnif node.Leaf_status: #如果node是叶结点if itemset in node.bucket:node.bucket[itemset] += countelse:node.bucket[itemset] = countif len(node.bucket) == self.max_leaf_count: #如果储存桶容量增加for old_itemset, old_count in node.bucket.items():hash_key = self.hash_function(old_itemset[index]) #对下一个索引做哈希if hash_key not in node.children:node.children[hash_key] = Hash_node()self.recursively_insert(node.children[hash_key], old_itemset, index + 1, old_count)del node.bucketnode.Leaf_status = Falseelse: #如果node不是是叶结点#需要进行递归式的嵌入def insert(self, itemset):itemset = tuple(itemset)self.recursively_insert(self.root, itemset, 0, 0)# 添加支持度到候选项集中. 遍历树并找到该项集所在的储存桶.def add_support(self, itemset):Transverse_HNode = self.rootitemset = tuple(itemset)index = 0while True:if Transverse_HNode.Leaf_status:if itemset in Transverse_HNode.bucket: #在此储存桶中找到项集Transverse_HNode.bucket[itemset] += 1 #增加此项目集的计数breakhash_key = self.hash_function(itemset[index])if hash_key in Transverse_HNode.children:Transverse_HNode = Transverse_HNode.children[hash_key]else:breakindex += 1def get_frequent_itemsets(self, node, support_count,frequent_itemsets):if node.Leaf_status:for key, value in node.bucket.items():if value >= support_count: #如果满足支持数条件frequent_itemsets.append(list(key)) #将其添加到频繁项集中Frequent_items_value[key] = valuereturnfor child in node.children.values():self.get_frequent_itemsets(child, support_count,frequent_itemsets)# 用于构造hash树的hash函数定义def hash_function(self, val):return int(val) % self.max_child_count
其中如果node不是叶结点,需要进行递归式的嵌入,请同学自行完成。
提示:
调用hash函数计算hash值。
判断hash值是否在子节点中。
如果不在就构建新节点。
调用recursively_insert嵌入。
编程要求:
根据提示,在右侧编辑器补充代码,构造正确的hash树类实现hash的支持度计算。
测试说明:
平台会对你编写的代码进行测试:
预期输出:
['1 3 5', '2 4', '1 2 3 4', '1 2', '2 3', '1 2', '2 3', '1 2 3 5', '1 2 3', '1 3 5']
[['1'], ['3'], ['5'], ['2'], ['4']]
{('1',): 7, ('3',): 7, ('5',): 3, ('2',): 8, ('4',): 2}
All frequent itemsets with their support count:
{('1',): 7, ('3',): 7, ('5',): 3, ('2',): 8, ('4',): 2, ('1', '3'): 5, ('1', '5'): 3, ('1', '2'): 5, ('3', '5'): 3, ('2', '3'): 5, ('2', '4'): 2, ('1', '3', '5'): 3, ('1', '2', '3'): 3}
开始你的任务吧,祝你成功!
import itertools
import timefilename = "data.csv"min_support = 2#读取数据集
with open(filename) as f:content = f.readlines()content = [x.strip() for x in content]
print(content)Transaction = [] #保存事务列表
Frequent_items_value = {} #保存所有频繁项集字典#将数据集的内容添加到事物列表
for i in range(0,len(content)):Transaction.append(content[i].split())#获得频繁一项集
def frequent_one_item(Transaction,min_support):candidate1 = {}for i in range(0,len(Transaction)):for j in range(0,len(Transaction[i])):if Transaction[i][j] not in candidate1:candidate1[Transaction[i][j]] = 1else:candidate1[Transaction[i][j]] += 1frequentitem1 = [] #获得满足最小支持度的频繁一项集for value in candidate1:if candidate1[value] >= min_support:frequentitem1 = frequentitem1 + [[value]]Frequent_items_value[tuple(value)] = candidate1[value]return frequentitem1values = frequent_one_item(Transaction,min_support)
print(values)
print(Frequent_items_value)# 从事物中删除不频繁的一项集
Transaction1 = []
for i in range(0,len(Transaction)):list_val = []for j in range(0,len(Transaction[i])):if [Transaction[i][j]] in values:list_val.append(Transaction[i][j])Transaction1.append(list_val)#Hash节点类定义
class Hash_node:def __init__(self):self.children = {} #指向子节点的指针self.Leaf_status = True #了解当前节点是否为叶子节点的状态self.bucket = {} #在储存桶中包含项目集#构造得到Hash树类
class HashTree:# class constructordef __init__(self, max_leaf_count, max_child_count):self.root = Hash_node()self.max_leaf_count = max_leaf_countself.max_child_count = max_child_countself.frequent_itemsets = []# 进行递归插入以生成hashtreedef recursively_insert(self, node, itemset, index, count):if index == len(itemset):if itemset in node.bucket:node.bucket[itemset] += countelse:node.bucket[itemset] = countreturnif node.Leaf_status:##########begin###########如果node是叶结点所进行的操作代码##########end########## else:##########begin###########如果node不是是叶结点所进行的操作代码##########end##########def insert(self, itemset):itemset = tuple(itemset)self.recursively_insert(self.root, itemset, 0, 0)# 添加支持度到候选项集中. 遍历树并找到该项集所在的储存桶.def add_support(self, itemset):Transverse_HNode = self.rootitemset = tuple(itemset)index = 0while True:if Transverse_HNode.Leaf_status:if itemset in Transverse_HNode.bucket: #在此储存桶中找到项集Transverse_HNode.bucket[itemset] += 1 #增加此项目集的计数breakhash_key = self.hash_function(itemset[index])if hash_key in Transverse_HNode.children:Transverse_HNode = Transverse_HNode.children[hash_key]else:breakindex += 1# 基于hash的支持度计算def get_frequent_itemsets(self, node, support_count,frequent_itemsets):##########begin###########获取频繁项集函数定义##########end########### hash function for making HashTreedef hash_function(self, val):return int(val) % self.max_child_count#生成hashTree
def generate_hash_tree(candidate_itemsets, max_leaf_count, max_child_count):htree = HashTree(max_child_count, max_leaf_count) #create instance of HashTreefor itemset in candidate_itemsets:htree.insert(itemset) #to insert itemset into Hashtreereturn htree#to generate subsets of itemsets of size k
def generate_k_subsets(dataset, length):subsets = []for itemset in dataset:subsets.extend(map(list, itertools.combinations(itemset, length)))return subsetsdef subset_generation(ck_data,l):return map(list,set(itertools.combinations(ck_data,l)))# 候选生成def apriori_generate(dataset,k):ck = []#join steplenlk = len(dataset)for i in range(lenlk):for j in range(i+1,lenlk):L1 = list(dataset[i])[:k - 2]L2 = list(dataset[j])[:k - 2]if L1 == L2:ck.append(sorted(list(set(dataset[i]) | set(dataset[j]))))#prune stepfinal_ck = []for candidate in ck:all_subsets = list(subset_generation(set(candidate), k - 1))found = Truefor i in range(len(all_subsets)):value = list(sorted(all_subsets[i]))if value not in dataset:found = Falseif found == True:final_ck.append(candidate)return ck,final_ck# 候选剪枝def generateL(ck,min_support):support_ck = {}for val in Transaction1:for val1 in ck:value = set(val)value1 = set(val1)if value1.issubset(value):if tuple(val1) not in support_ck:support_ck[tuple(val1)] = 1else:support_ck[tuple(val1)] += 1frequent_item = []for item_set in support_ck:if support_ck[item_set] >= min_support:frequent_item.append(sorted(list(item_set)))Frequent_items_value[item_set] = support_ck[item_set]return frequent_item# apriori算法主函数
def apriori(L1,min_support):k = 2;L = []L.append(0)L.append(L1)max_leaf_count = 6 #每个hash树节点的最大容量max_child_count = 6 #每个hash树节点的最大子节点数start = time.time()while(len(L[k-1])>0):ck,final_ck = apriori_generate(L[k-1],k) #生成候选项集# print("C%d" %(k))# print(final_ck)h_tree = generate_hash_tree(ck,max_leaf_count,max_child_count) #生成hash树if (k > 2):while(len(L[k-1])>0):l = generateL(final_ck, min_support)L.append(l)# print("Frequent %d item" % (k))# print(l)k = k + 1ck, final_ck = apriori_generate(L[k - 1], k)# print("C%d" % (k))# print(final_ck)breakk_subsets = generate_k_subsets(Transaction1,k) #生成事物子集for subset in k_subsets:h_tree.add_support(subset) #像hash树的项集添加支持数lk = []h_tree.get_frequent_itemsets(h_tree.root,min_support,lk) #获取频繁项集# print("Frequent %d item" %(k))# print(lk)L.append(lk)k = k + 1end = time.time()return L,(end-start)L_value,time_taken = apriori(values,min_support)
#print("final L_value")
#print(L_value)
print("All frequent itemsets with their support count:")
print(Frequent_items_value)
import itertools
import timefilename = "data.csv"min_support = 2#读取数据集
with open(filename) as f:content = f.readlines()content = [x.strip() for x in content]
print(content)Transaction = [] #保存事务列表
Frequent_items_value = {} #保存所有频繁项集字典#将数据集的内容添加到事物列表
for i in range(0,len(content)):Transaction.append(content[i].split())#获得频繁一项集
def frequent_one_item(Transaction,min_support):candidate1 = {}for i in range(0,len(Transaction)):for j in range(0,len(Transaction[i])):if Transaction[i][j] not in candidate1:candidate1[Transaction[i][j]] = 1else:candidate1[Transaction[i][j]] += 1frequentitem1 = [] #获得满足最小支持度的频繁一项集for value in candidate1:if candidate1[value] >= min_support:frequentitem1 = frequentitem1 + [[value]]Frequent_items_value[tuple(value)] = candidate1[value]return frequentitem1values = frequent_one_item(Transaction,min_support)
print(values)
print(Frequent_items_value)# 从事物中删除不频繁的一项集
Transaction1 = []
for i in range(0,len(Transaction)):list_val = []for j in range(0,len(Transaction[i])):if [Transaction[i][j]] in values:list_val.append(Transaction[i][j])Transaction1.append(list_val)#Hash节点类定义
class Hash_node:def __init__(self):self.children = {} #指向子节点的指针self.Leaf_status = True #了解当前节点是否为叶子节点的状态self.bucket = {} #在储存桶中包含项目集#构造得到Hash树类
class HashTree:# class constructordef __init__(self, max_leaf_count, max_child_count):self.root = Hash_node()self.max_leaf_count = max_leaf_countself.max_child_count = max_child_countself.frequent_itemsets = []# 进行递归插入以生成hashtreedef recursively_insert(self, node, itemset, index, count):if index == len(itemset):if itemset in node.bucket:node.bucket[itemset] += countelse:node.bucket[itemset] = countreturnif node.Leaf_status:##########begin###########如果node是叶结点所进行的操作代码if itemset in node.bucket:node.bucket[itemset]+=countelse:node.bucket[itemset]=countif len(node.bucket)==self.max_leaf_count:如果储存桶容量增加for old_itemset, old_count in node.bucket.items():hash_key = self.hash_function(old_itemset[index]) #对下一个索引做哈希if hash_key not in node.children:node.children[hash_key] = Hash_node()self.recursively_insert(node.children[hash_key], old_itemset, index + 1, old_count)del node.bucketnode.Leaf_status = False##########end########## else:##########begin###########如果node不是是叶结点所进行的操作代码hash_key=self.hash_function(itemset[index])if hash_key not in node.children:node.children[hash_key]=Hash_node()self.recursively_insert(node.children[hash_key],itemset,index+1,count)##########end##########def insert(self, itemset):itemset = tuple(itemset)self.recursively_insert(self.root, itemset, 0, 0)# 添加支持度到候选项集中. 遍历树并找到该项集所在的储存桶.def add_support(self, itemset):Transverse_HNode = self.rootitemset = tuple(itemset)index = 0while True:if Transverse_HNode.Leaf_status:if itemset in Transverse_HNode.bucket: #在此储存桶中找到项集Transverse_HNode.bucket[itemset] += 1 #增加此项目集的计数breakhash_key = self.hash_function(itemset[index])if hash_key in Transverse_HNode.children:Transverse_HNode = Transverse_HNode.children[hash_key]else:breakindex += 1# 基于hash的支持度计算def get_frequent_itemsets(self, node, support_count,frequent_itemsets):##########begin###########获取频繁项集函数定义if node.Leaf_status:for key, value in node.bucket.items():if value >= support_count: #如果满足支持数条件frequent_itemsets.append(list(key)) #将其添加到频繁项集中Frequent_items_value[key] = valuereturnfor child in node.children.values():self.get_frequent_itemsets(child, support_count,frequent_itemsets)##########end########### hash function for making HashTreedef hash_function(self, val):return int(val) % self.max_child_count#生成hashTree
def generate_hash_tree(candidate_itemsets, max_leaf_count, max_child_count):htree = HashTree(max_child_count, max_leaf_count) #create instance of HashTreefor itemset in candidate_itemsets:htree.insert(itemset) #to insert itemset into Hashtreereturn htree#to generate subsets of itemsets of size k
def generate_k_subsets(dataset, length):subsets = []for itemset in dataset:subsets.extend(map(list, itertools.combinations(itemset, length)))return subsetsdef subset_generation(ck_data,l):return map(list,set(itertools.combinations(ck_data,l)))# 候选生成def apriori_generate(dataset,k):ck = []#join steplenlk = len(dataset)for i in range(lenlk):for j in range(i+1,lenlk):L1 = list(dataset[i])[:k - 2]L2 = list(dataset[j])[:k - 2]if L1 == L2:ck.append(sorted(list(set(dataset[i]) | set(dataset[j]))))#prune stepfinal_ck = []for candidate in ck:all_subsets = list(subset_generation(set(candidate), k - 1))found = Truefor i in range(len(all_subsets)):value = list(sorted(all_subsets[i]))if value not in dataset:found = Falseif found == True:final_ck.append(candidate)return ck,final_ck# 候选剪枝def generateL(ck,min_support):support_ck = {}for val in Transaction1:for val1 in ck:value = set(val)value1 = set(val1)if value1.issubset(value):if tuple(val1) not in support_ck:support_ck[tuple(val1)] = 1else:support_ck[tuple(val1)] += 1frequent_item = []for item_set in support_ck:if support_ck[item_set] >= min_support:frequent_item.append(sorted(list(item_set)))Frequent_items_value[item_set] = support_ck[item_set]return frequent_item# apriori算法主函数
def apriori(L1,min_support):k = 2;L = []L.append(0)L.append(L1)max_leaf_count = 6 #每个hash树节点的最大容量max_child_count = 6 #每个hash树节点的最大子节点数start = time.time()while(len(L[k-1])>0):ck,final_ck = apriori_generate(L[k-1],k) #生成候选项集# print("C%d" %(k))# print(final_ck)h_tree = generate_hash_tree(ck,max_leaf_count,max_child_count) #生成hash树if (k > 2):while(len(L[k-1])>0):l = generateL(final_ck, min_support)L.append(l)# print("Frequent %d item" % (k))# print(l)k = k + 1ck, final_ck = apriori_generate(L[k - 1], k)# print("C%d" % (k))# print(final_ck)breakk_subsets = generate_k_subsets(Transaction1,k) #生成事物子集for subset in k_subsets:h_tree.add_support(subset) #像hash树的项集添加支持数lk = []h_tree.get_frequent_itemsets(h_tree.root,min_support,lk) #获取频繁项集# print("Frequent %d item" %(k))# print(lk)L.append(lk)k = k + 1end = time.time()return L,(end-start)L_value,time_taken = apriori(values,min_support)
#print("final L_value")
#print(L_value)
print("All frequent itemsets with their support count:")
print(Frequent_items_value)
数据挖掘与机器学习:Apripori算法相关推荐
- 数据挖掘与机器学习基本算法总结
第一次写学习总结,主要是现在自己所学的东西,知识更新速度之快,自己的遗忘速度也是非常之恐怖.遂决定,压着自己的头皮,写一写总结,也算是给自己这么多年的学习有个交代和梳理. 数据挖掘与数据分析好书推荐: ...
- 美国 2006 年机器学习和知识发现年会数据挖掘使用率较高算法排名
在美国 2006 年机器学习和知识发现年会,数据挖掘(Data Mining)哪些算法使用率较高?现场投票结果可以给我们一点线索.数据挖掘有十大经典算法为:C4.5,K-Means,SVM,Aprio ...
- 数据挖掘和机器学习:基本概念和算法(附电子书PPT)
来源:专知本文多图,建议阅读5分钟这本书奠定了数据分析.模式挖掘.聚类.分类和回归的基础,集中在算法和潜在的代数.几何和概率概念上. 数据挖掘和机器学习的基本算法构成了数据科学的基础,利用自动化方法分 ...
- Python数据挖掘与机器学习,快速掌握聚类算法和关联分析
摘要:前文数据挖掘与机器学习技术入门实战与大家分享了分类算法,在本文中将为大家介绍聚类算法和关联分析问题.分类算法与聚类到底有何区别?聚类方法应在怎样的场景下使用?如何使用关联分析算法解决个性化推荐问 ...
- 阿里资深AI工程师教你逐个击破机器学习核心算法
01 近年来,随着 Google 的 AlphaGo 打败韩国围棋棋手李世乭之后,机器学习尤其是深度学习的热潮席卷了整个 IT 界. 所有的互联网公司,尤其是 Google 微软,百度,腾讯等巨头,无 ...
- 带你入门Python数据挖掘与机器学习(附代码、实例)
作者:韦玮 来源:Python爱好者社区 本文共7800字,建议阅读10+分钟. 本文结合代码实例待你上手python数据挖掘和机器学习技术. 本文包含了五个知识点: 1. 数据挖掘与机器学习技术简介 ...
- 数据挖掘与机器学习介绍
数据挖掘 1.定义: 数据挖掘(Data Mining)是有组织有目的地收集数据,通过分析数据使之成为信息,从而在大量数据中寻找潜在规律以形成规则或知识的技术. 2.数据挖掘与机器学习的关系: 机器学 ...
- 数据挖掘十大经典算法之——EM 算法
数据挖掘十大经典算法系列,点击链接直接跳转: 数据挖掘简介及十大经典算法(大纲索引) 1. 数据挖掘十大经典算法之--C4.5 算法 2. 数据挖掘十大经典算法之--K-Means 算法 3. 数据挖 ...
- 数据挖掘十大经典算法之——AdaBoost 算法
数据挖掘十大经典算法系列,点击链接直接跳转: 数据挖掘简介及十大经典算法(大纲索引) 1. 数据挖掘十大经典算法之--C4.5 算法 2. 数据挖掘十大经典算法之--K-Means 算法 3. 数据挖 ...
最新文章
- 吸收和实践的同时推进
- 分享我对领域驱动设计(DDD)的学习成果
- 体验最火的敏捷-SCRUM!(网络直播课程 免费)
- ASP.NET MVC 后台传值前端乱码解决方案 富文本Ueditor编辑
- 电脑技巧:Win10自带远程控制软件介绍
- POJ2104 (平方分割)二分查找理解。
- 在Visual Studio中利用NTVS创建Pomelo项目
- php 接口有几种,【后端开辟】php接口有哪些范例?
- 删除某个路径下的文件夹
- 求解简单的四则运算表达式
- NodeJS 数组超出部分以弹出框显示。
- vs2012 设置默认的 include 目录
- 浅谈智能电能表的远程预付费 系统设计
- Go 语言网络库 getty 的那些事
- Java实现首字母转大写、小写StringUtils.capitalize
- 夜神模拟器无法安装Charles证书
- cass坡度土方计算案例_CASS土方量计算总结
- 中国五笔 恶意软件清理助手
- 鸿蒙系统吹了多少年了还没出,实话实说,在鸿蒙系统上,余承东吹了几次牛都没实现...
- freeswitch拨打分机号源代码跟踪
热门文章
- 多样数字人民币钱包来袭,阻力与动力并存
- SDHK_Tool.Static.SS_EulerAngleConversion 欧拉角,角度转换计算
- java 方法实现数学黑洞
- 国内的windows硬件检测软件算是很牛逼的吧!!!?
- 膨胀卷积神经网络_用膨胀的卷积神经网络生成钢琴音乐
- USACO 2018 January Contest Platinum A: Lifeguards 题解
- G120变频器本地_远程切换(CDS切换)的具体方法和步骤
- 全国大学生交通科技大赛交科赛交通运输科技大赛智能交通创新技术应用大赛国家三等奖论文文字作品资料经验分享
- 12306那些事-技术并没有想象中那么简单
- Activiti 自定义流程图颜色