一、实验目的
1. 掌握Apriori算法的实现过程。
二、实验内容
1. 杂货店商品数据集频繁项集挖掘实验
(1)假设最小支持度阈值为0.1,复现Apriori算法并在杂货店商品数据集中找出所有的频繁项集,可参考以下流程:
1)找出数据集中的频繁1-项集;
2)根据频繁1-项集生成候选2-项集;
3)判断是否可对候选2-项集进行剪枝操作,然后计算剩余候选2-项集的支持度计数,最后筛选出频繁-2项集;
4)重复以上过程直至候选k-项集为空,最后输出所有的频繁项集。
三、实验报告评分标准
1. 完成实验(1)(70分)
6. 实验过程与实验结论的记录完整(10分)
7. 表述逻辑清晰(10分)
8. 排版工整自洽,图表标题准确(10分)
四、实验过程
4.1导入csv文件,并转化成list,以便后续操作
- def read_csv(file_name):
- f = open(file_name, 'r')
- content = f.read()
- ##将双引号“”删去
- content = content.replace('"', '')
- final_list = list()
- rows = content.split('\n')
- for row in rows:
- final_list.append(row.split(','))
- return final_list
4.2一些概念
Tuple和 set的区别:
1)元组tuple是有序的,可通过索引来访问的,而集合set是无序的,无法通过索引来访问元素;
2)元组tuple中的元素是可以重复的,而集合set自带去重的功能,其元素是无法重复的;
3)元组tuple中的元素值是不可修改的(但可以通过切片slice的方式来获取指定的索引起始位置和终止位置的元素),而集合set中的元素是可修改的,比如删除指定的元素。
哈希:
对于 Python 的内建类型来说,只要是创建之后无法修改的(immutable)类型都是 hashable 如字符串,可变动的都是 unhashable的比如:列表、字典、集合,他们在改变值的同时却没有改变id,无法由地址定位值的唯一性,因而无法哈希。
可哈希的数据类型有:字符串,元组,数字
不可哈希的有:字典,列表,集合
字典的键必须是可哈希的
在Python中,set 中的元素必须是可哈希(hashable)的数据类型,并且集合自身是不可哈希的。
(以上参考自csdn)
4.3计算频繁1项集
创建一个空字典,将4.1处理好的列表的每一项取出,以食物名为键,每种食物在事务集出现的次数作为值,食物每出现一次,给对应键的值+1,计算支持度计数,与阈值作比较,若大于阈值则为频繁项。
- def find_frequent_1_itemsets(transactions, min_support):
- item_counts = {}
- total_transactions = len(transactions)
- frequent_1_itemsets = []
- for transaction in transactions:
- for item in transaction:
- item_counts[item] = item_counts.get(item, 0) + 1
- for item, count in item_counts.items():
- support = count / total_transactions
- if support >= min_support:
- frequent_1_itemsets.append({item})#############{item}集合 去重
- return frequent_1_itemsets
4.4计算频繁2项集
将频繁1项集排列组合,求出候选集,在做支持度计算,与阈值比较。用两个for循环遍历一项集,注意第二个for循环遍历的项的index索引值需要大于第一个for中的item,避免出现重复的情况。
- def find_frequent_2_itemsets(frequent_itemsets,transactions,min_support):
- candidates = []###集合 自动去重
- for itemset1 in frequent_itemsets:
- for itemset2 in frequent_itemsets:
- if frequent_itemsets.index(itemset2) > frequent_itemsets.index(itemset1):
- candidate = itemset1.union(itemset2)
- # print(len(candidate))
- if len(candidate) == 2:##########!!!
- candidates.append(candidate) # 使用元组而不是集合
- item_counts = {}
- total_transactions = len(transactions)
- for transaction in transactions:
- for candidate in candidates:
- if candidate.issubset(transaction):
- candidate = tuple(candidate)#########
- item_counts[candidate] = item_counts.get(candidate, 0) + 1
- frequent_itemsets = []
- for itemset, count in item_counts.items():
- support = count / total_transactions
- if support >= min_support:
- frequent_itemsets.append(set(itemset))
- return frequent_itemsets
4.5接下来的3 4 5…项集可以用相同的方法来实现,我选择了Fk*F1方法。先将k-1频繁项集与1项集排列组合,然后用set进行自动去重。(A,B,C)与(A,C,B)情况相同,若两者都是set结构则可以当做相同的元素,但是set()中的元素必须可哈希,所以我选择先用list存储一个个排列组合的set,再对list进行去重。
list去重:
- unique_list = []
- [unique_list.append(x) for x in candidate_itemsets if x not in unique_list]
- candidate_itemsets = unique_list
- # 生成候选k-项集
- def generate_candidate_itemsets(frequent_itemsets,fre_1, k):
- candidates = list()###
- for itemset1 in frequent_itemsets:
- for itemset2 in fre_1:
- candidate = itemset1.union(itemset2)
- # print(len(candidate))
- if len(candidate) == k:##########!!!
- candidates.append(candidate) #
- return candidates