关联分析---Apriori算法和FPGrowth算法挖掘规则计算频繁项间的置信度
Apriori算法和FPGrowth算法挖掘规则计算频繁项间的置信度
- 数据准备
- Apriori算法:
- apriori算法流程
- 实现代码
- FP-growth算法
- FP-growth算法优点
- FP-growth算法流程
- 实现代码
博主在进行了Apriori算法和FPgrowth算法的学习与完成置信度计算之后写下此篇文章,没有过多的理论介绍,理论学习可以 点击这里进行查看,此篇文章主要写出实现功能的代码,有些中间结果并未输出。但最终的置信度是进行了输出的。
数据准备
此处演示所用的数据集为书中作业题目的数据集:
dataset = [
[‘M’, ‘O’, ‘N’, ‘K’, ‘E’, ‘Y’],
[‘D’, ‘O’, ‘N’, ‘K’, ‘E’, ‘Y’],
[‘M’, ‘A’, ‘K’, ‘E’],
[‘M’, ‘U’, ‘C’, ‘K’, ‘Y’],
[‘C’, ‘O’, ‘O’, ‘K’, ‘I’, ‘E’]
]
另外,你使用的数据也可以来至文本文件,最终的结果也可以保存至文件中,如有需要可以联系我!微:18385457714
Apriori算法:
apriori算法流程
输入:数据集合D,支持度阈值α
输出:最大的频繁k项集
1)扫描整个数据集,得到所有出现过的数据,作为候选频繁1项集。k=1,频繁0项集为空集。
2)挖掘频繁k项集
a) 扫描数据计算候选频繁k项集的支持度
b) 去除候选频繁k项集中支持度低于阈值的数据集,得到频繁k项集。如果得到的频繁k项集为空,则直接返回频繁k-1项集的集合作为算法结果,算法结束。如果得到的频繁k项集只有一项,则直接返回频繁k项集的集合作为算法结果,算法结束。
c) 基于频繁k项集,连接生成候选频繁k+1项集。
3) 令k=k+1,转入步骤2。
实现代码
import itertoolsdef item(dataset): # 求第一次扫描数据库后的 候选集,(它没法加入循环)c1 = [] # 存放候选集元素for x in dataset: # 就是求这个数据库中出现了几个元素,然后返回for y in x:if [y] not in c1:c1.append([y])c1.sort()# print(c1)return c1def get_frequent_item(dataset, c, min_support):cut_branch = {} # 用来存放所有项集的支持度的字典for x in c:for y in dataset:if set(x).issubset(set(y)): # 如果 x 不在 y中,就把对应元素后面加 1cut_branch[tuple(x)] = cut_branch.get(tuple(x),0) + 1 # cut_branch[y] = new_cand.get(y, 0)表示如果字典里面没有想要的关键词,就返回0print("----------------候选集--------------------")print(cut_branch)Fk = [] # 支持度大于最小支持度的项集, 即频繁项集sup_dataK = {} # 用来存放所有 频繁 项集的支持度的字典for i in cut_branch:if cut_branch[i] >= min_support: # Apriori定律1 小于支持度,则就将它舍去,它的超集必然不是频繁项集Fk.append(list(i))sup_dataK[i] = cut_branch[i]print("=============频繁项集==============")print(Fk)return Fk, sup_dataKdef get_candidate(Fk, K): # 求第k次候选集ck = [] # 存放产生候选集for i in range(len(Fk)):for j in range(i + 1, len(Fk)):L1 = list(Fk[i])[:K - 2]L2 = list(Fk[j])[:K - 2]L1.sort()L2.sort() # 先排序,在进行组合if L1 == L2:if K > 2: # 第二次求候选集,不需要进行减枝,因为第一次候选集都是单元素,且已经减枝了,组合为双元素肯定不会出现不满足支持度的元素new = list(set(Fk[i]) ^ set(Fk[j])) # 集合运算 对称差集 ^ (含义,集合的元素在t或s中,但不会同时出现在二者中)# new表示,这两个记录中,不同的元素集合# 为什么要用new? 比如 1,2 1,3 两个合并成 1,2,3 我们知道1,2 和 1,3 一定是频繁项集,但 2,3呢,我们要判断2,3是否为频繁项集# Apriori定律1 如果一个集合不是频繁项集,则它的所有超集都不是频繁项集else:new = set()for x in Fk:if set(new).issubset(set(x)) and list(set(Fk[i]) | set(Fk[j])) not in ck: # 减枝 new是 x 的子集,并且 还没有加入 ck 中ck.append(list(set(Fk[i]) | set(Fk[j])))print(ck)return ckdef Apriori(dataset, min_support=2):c1 = item(dataset) # 返回一个二维列表,里面的每一个一维列表,都是第一次候选集的元素f1, sup_1 = get_frequent_item(dataset, c1, min_support) # 求第一次候选集F = [f1] # 将第一次候选集产生的频繁项集放入 F ,以后每次扫描产生的所有频繁项集都放入里面sup_data = sup_1 # 一个字典,里面存放所有产生的候选集,及其支持度K = 2 # 从第二个开始循环求解,先求候选集,在求频繁项集while (len(F[K - 2]) > 1): # k-2是因为F是从0开始数的 #前一个的频繁项集个数在2个或2个以上,才继续循环,否则退出ck = get_candidate(F[K - 2], K) # 求第k次候选集fk, sup_k = get_frequent_item(dataset, ck, min_support) # 求第k次频繁项集F.append(fk) # 把新产生的候选集假如Fsup_data.update(sup_k) # 字典更新,加入新得出的数据K += 1return F, sup_data # 返回所有频繁项集, 以及存放频繁项集支持度的字典def generate_association_rules(patterns, confidence_threshold):"""Given a set of frequent itemsets, return a dictof association rules in the form{(left): ((right), confidence)}"""rules = []for itemset in patterns.keys():upper_support = patterns[itemset]for i in range(1, len(itemset)):for antecedent in itertools.combinations(itemset, i):antecedent = tuple(sorted(antecedent))consequent = tuple(sorted(set(itemset) - set(antecedent)))if antecedent in patterns:lower_support = patterns[antecedent]confidence = float(upper_support) / lower_supportif confidence >= confidence_threshold:rules.append([antecedent, consequent, confidence])return rulesdef printPatterns(patterns):keys1 = list(patterns.keys())values1 = list(patterns.values())for i in range(len(keys1)):keys1[i] = list(keys1[i])for i in range(len(keys1)):for j in range(len(keys1[i])):print(keys1[i][j], end=" ")for i2 in range(10 - 2 * len(keys1[i])):print(" ", end="")print(" : ", end="")print(values1[i], end="\n")def printRules2(rlues):keys1 = []values1 = []for i in range(len(rules)):keys1.append(list(rules[i][0]))values1.append(list(rules[i][1]))for i in range(len(keys1)):for j in range(len(keys1[i])):print(keys1[i][j], end=" ")for i2 in range(10 - 2 * len(keys1[i])):print(" ", end="")print(" --> ", end="")for i1 in range(len(values1[i])):print(values1[i][i1], end=" ")for i3 in range(10 - 2 * len(values1[i])):print(" ", end="")print(": " + str(rules[i][2]), end="\n")if __name__ == '__main__':dataset = [['M', 'O', 'N', 'K', 'E', 'Y'],['D', 'O', 'N', 'K', 'E', 'Y'],['M', 'A', 'K', 'E'],['M', 'U', 'C', 'K', 'Y'],['C', 'O', 'O', 'K', 'I', 'E']] # 装入数据 二维列表F, sup_data = Apriori(dataset, min_support=3) # 最小支持度设置为3rules = generate_association_rules(sup_data, 0.8) # 置信度(条件概率)删选print("各频繁集及其出现次数如下", end="\n")printPatterns(sup_data)print('---------------------------------')print("各强关联规则及其置信度如下", end="\n")printRules2(rules)
执行结果示例:
FP-growth算法
FP-growth算法优点
FP-growth算法比Apriori算法效率更高,在整个算法执行过程中,只需遍历数据集2次,就能够完成频繁模式发现,其发现频繁项集的基本过程如下:
第一次:构建FP树
第二次:从FP树中挖掘频繁项集
FP-growth算法流程
FP-growth的一般流程如下:
1:先扫描一遍数据集,得到频繁项为1的项目集,定义最小支持度(项目出现最少次数),删除那些小于最小支持度的项目,然后将原始数据集中的条目按项目集中降序进行排列。
2:第二次扫描,创建项头表(从上往下降序),以及FP树。
3:对于每个项目(可以按照从下往上的顺序)找到其条件模式基(CPB,conditional patten base),递归调用树结构,删除小于最小支持度的项。如果最终呈现单一路径的树结构,则直接列举所有组合;非单一路径的则继续调用树结构,直到形成单一路径即可。
实现代码
# -*- coding: utf-8 -*-from tqdm import tqdmdef load_data(): # 根据路径加载数据集ans = [] # 将数据保存到该数组reader = [['M', 'O', 'N', 'K', 'E', 'Y'],['D', 'O', 'N', 'K', 'E', 'Y'],['M', 'A', 'K', 'E'],['M', 'U', 'C', 'K', 'Y'],['C', 'O', 'O', 'K', 'I', 'E']]for row in reader:row = list(set(row)) # 去重,排序row.sort()ans.append(row) # 将添加好的数据添加到数组return ans # 返回处理好的数据集,为二维数组def show_confidence(rule):index = 1for item in rule:s = " {:<4d} {:.3f} {}=>{}".format(index, item[2], str(list(item[0])), str(list(item[1])))index += 1print(s)class Node:def __init__(self, node_name, count, parentNode):self.name = node_nameself.count = countself.nodeLink = None # 根据nideLink可以找到整棵树中所有nodename一样的节点self.parent = parentNode # 父亲节点self.children = {} # 子节点{节点名字:节点地址}class Fp_growth_plus():def data_compress(self, data_set):data_dic = {}for i in data_set:if frozenset(i) not in data_dic:data_dic[frozenset(i)] = 1else:data_dic[frozenset(i)] += 1return data_dicdef update_header(self, node, targetNode): # 更新headertable中的node节点形成的链表while node.nodeLink != None:node = node.nodeLinknode.nodeLink = targetNodedef update_fptree(self, items, count, node, headerTable): # 用于更新fptreeif items[0] in node.children:# 判断items的第一个结点是否已作为子结点node.children[items[0]].count += countelse:# 创建新的分支node.children[items[0]] = Node(items[0], count, node)# 更新相应频繁项集的链表,往后添加if headerTable[items[0]][1] == None:headerTable[items[0]][1] = node.children[items[0]]else:self.update_header(headerTable[items[0]][1], node.children[items[0]])# 递归if len(items) > 1:self.update_fptree(items[1:], count, node.children[items[0]], headerTable)def create_fptree(self, data_dic, min_support, flag=False): # 建树主函数'''根据data_dic创建fp树header_table结构为{"nodename":[num,node],..} 根据node.nodelink可以找到整个树中的所有nodename'''item_count = {} # 统计各项出现次数for t in data_dic: # 第一次遍历,得到频繁一项集for item in t:if item not in item_count:item_count[item] = data_dic[t]else:item_count[item] += data_dic[t]headerTable = {}for k in item_count: # 剔除不满足最小支持度的项if item_count[k] >= min_support:headerTable[k] = item_count[k]freqItemSet = set(headerTable.keys()) # 满足最小支持度的频繁项集if len(freqItemSet) == 0:return None, Nonefor k in headerTable:headerTable[k] = [headerTable[k], None] # element: [count, node]tree_header = Node('head node', 1, None)if flag:ite = tqdm(data_dic)else:ite = data_dicfor t in ite: # 第二次遍历,建树localD = {}for item in t:if item in freqItemSet: # 过滤,只取该样本中满足最小支持度的频繁项localD[item] = headerTable[item][0] # element : countif len(localD) > 0:# 根据全局频数从大到小对单样本排序order_item = [v[0] for v in sorted(localD.items(), key=lambda x: x[1], reverse=True)]# 用过滤且排序后的样本更新树self.update_fptree(order_item, data_dic[t], tree_header, headerTable)return tree_header, headerTabledef find_path(self, node, nodepath):'''递归将node的父节点添加到路径'''if node.parent != None:nodepath.append(node.parent.name)self.find_path(node.parent, nodepath)def find_cond_pattern_base(self, node_name, headerTable):'''根据节点名字,找出所有条件模式基'''treeNode = headerTable[node_name][1]cond_pat_base = {} # 保存所有条件模式基while treeNode != None:nodepath = []self.find_path(treeNode, nodepath)if len(nodepath) > 1:cond_pat_base[frozenset(nodepath[:-1])] = treeNode.counttreeNode = treeNode.nodeLinkreturn cond_pat_basedef create_cond_fptree(self, headerTable, min_support, temp, freq_items, support_data):# 最开始的频繁项集是headerTable中的各元素freqs = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1][0])] # 根据频繁项的总频次排序for freq in freqs: # 对每个频繁项freq_set = temp.copy()freq_set.add(freq)freq_items.add(frozenset(freq_set))if frozenset(freq_set) not in support_data: # 检查该频繁项是否在support_data中support_data[frozenset(freq_set)] = headerTable[freq][0]else:support_data[frozenset(freq_set)] += headerTable[freq][0]cond_pat_base = self.find_cond_pattern_base(freq, headerTable) # 寻找到所有条件模式基# 创建条件模式树cond_tree, cur_headtable = self.create_fptree(cond_pat_base, min_support)if cur_headtable != None:self.create_cond_fptree(cur_headtable, min_support, freq_set, freq_items, support_data) # 递归挖掘条件FP树def generate_L(self, data_set, min_support):data_dic = self.data_compress(data_set)freqItemSet = set()support_data = {}tree_header, headerTable = self.create_fptree(data_dic, min_support, flag=True) # 创建数据集的fptree# 创建各频繁一项的fptree,并挖掘频繁项并保存支持度计数self.create_cond_fptree(headerTable, min_support, set(), freqItemSet, support_data)max_l = 0for i in freqItemSet: # 将频繁项根据大小保存到指定的容器L中if len(i) > max_l: max_l = len(i)L = [set() for _ in range(max_l)]for i in freqItemSet:L[len(i) - 1].add(i)for i in range(len(L)):print("frequent item {}:{}".format(i + 1, len(L[i])))return L, support_datadef generate_R(self, data_set, min_support, min_conf):L, support_data = self.generate_L(data_set, min_support)rule_list = []sub_set_list = []for i in range(0, len(L)):for freq_set in L[i]:for sub_set in sub_set_list:if sub_set.issubset(freq_set) and freq_set - sub_set in support_data: # and freq_set-sub_set in support_dataconf = support_data[freq_set] / support_data[freq_set - sub_set]big_rule = (freq_set - sub_set, sub_set, conf)if conf >= min_conf and big_rule not in rule_list:# print freq_set-sub_set, " => ", sub_set, "conf: ", confrule_list.append(big_rule)sub_set_list.append(freq_set)rule_list = sorted(rule_list, key=lambda x: (x[2]), reverse=True)return rule_listif __name__ == "__main__":min_support = 3 # 最小支持度min_conf = 0.8 # 最小置信度data_set = load_data()print(data_set)fp = Fp_growth_plus()rule_list = fp.generate_R(data_set, min_support, min_conf)print("confidence:")show_confidence(rule_list)
执行结果示例
如果你刚好需要使用,那么修改为你需要的数据集、最小支持度,最小置信度即可,
数据集、最小支持度和置信度的位置
希望能对你有用,欢迎评论和指出错误,欢迎一键三连,就不设置收费才能看了。希望大家多多支持!!!此篇文章也有参考借鉴其他大佬的文章进行修改创造,如有侵权,请联系删除。
关联分析---Apriori算法和FPGrowth算法挖掘规则计算频繁项间的置信度相关推荐
- 关联分析Apriori算法和FP-growth算法初探
1. 关联分析是什么? Apriori和FP-growth算法是一种关联算法,属于无监督算法的一种,它们可以自动从数据中挖掘出潜在的关联关系.例如经典的啤酒与尿布的故事.下面我们用一个例子来切入本文对 ...
- 使用Apriori算法和FP-growth算法进行关联分析
目录 1. 关联分析 2. Apriori原理 3. 使用Apriori算法来发现频繁集 4. 使用FP-growth算法来高效发现频繁项集 5. 示例:从新闻网站点击流中挖掘新闻报道 扩展阅读 系列 ...
- 关联规则挖掘(Apriori算法和FP-Growth算法)
一.关联规则概述 1.关联规则分析用于在一个数据集中找出各种数据项之间的关联关系,广泛用于购物篮数据.个性化推荐.预警.时尚穿搭.生物信息学.医疗诊断.网页挖掘和科学数据分析中 2.关联规则分析又称购 ...
- 【Apriori算法和FP-growth算法】
Apriori算法 通过例题解析算法思路 1.频繁项集思路描述 通过支持度算出min_sup,进行基础比较,大于min_sup的写入频繁1项集,然后依次写出2项集,直到k项集. 2.强关联解题思路 依 ...
- 机器学习实战—使用FP-growth算法来高效发现频繁项集
FP-growth算法基于Apriori构建,但采用了高级的数据结构减少扫描次数,大大加快了算法速度.FP-growth算法只需要对数据库进行两次扫描,而Apriori算法对于每个潜在的频繁项集都会扫 ...
- 关联规则挖掘算法: Aprior算法和Fpgrowth算法
关联规则挖掘的目的是挖掘不同物品(item)之前的相关性,啤酒和尿布的故事就是一个典型的成功例子.关联规则挖掘思想简单高效,在广告推荐领域也有较多的应用,主要用于推荐模型落地前的流量探索以及构建规 ...
- 12使用FP-growth算法来高效发现频繁项集
第12章 使用FP-growth算法来高效发现频繁项集 一.背景 大家都用过搜索引擎.当我们输入一个单词或单词的一份,搜索引擎就会自动补全查询词项.例如:当我们在百度输入"为什么" ...
- 【机器学习实战】第12章 使用 FP-growth 算法来高效发现频繁项集
第12章 使用FP-growth算法来高效发现频繁项集 前言 在 第11章 时我们已经介绍了用 Apriori 算法发现 频繁项集 与 关联规则. 本章将继续关注发现 频繁项集 这一任务,并使用 FP ...
- Apriori算法和FP-Tree算法简介
Apriori关联分析算法 Apriori 算法是挖掘产生关联规则所需频繁项集的基本算法,也是最著名的关联分析算法之一. 1. Apriori 算法 Apriori 算法使用了逐层搜索的迭代方法,即用 ...
- 小白入门关联规则之子图模式的类Apriori方法和gSpan算法挖掘学习
关联规则之子图模式 关联规则之子图模式 文章目的 基本概念 类apriori方法 gSpan算法 DFS编码 最右扩展 实验研究 参考博客 参考文献 关联规则之子图模式 文章目的 了解子图模式在什么情 ...
最新文章
- 多校1010 Taotao Picks Apples
- 如何保护企业网络免受DDoS攻击?—Vecloud微云
- ScrollView反弹效果
- JPA EntityManager详解
- 接口中默认方法和静态方法_接口中的默认方法和静态方法
- junit:junit_简而言之,JUnit:另一个JUnit教程
- 【机器学习】机器学习中的异常值的识别和处理
- ospf避免环路_【网络干货】超全的OSPF路由协议技术汇总解析
- 新微擎 v1.7.9 图文回复 标题emoji
- Vue 学习笔记(4)Vue-cli4 项目搭建 + 目录结构 + 项目打包、部署
- dll反编译工具总结
- atitit 每季度日程表 每季度流程 v3 qaf.docx Ver history V2 add diary cyar data 3 cate V3 fix detail 3cate ,
- 基于深度学习的单目人体姿态估计方法综述(一)
- uri和url的区别与联系(一看就理解)
- eps在c语言,C语言中eps指的是什么东西?
- KF、EKF、ESKF的区别与联系
- [BZOJ4416][Shoi2013]阶乘字符串 状态压缩dp
- Lucene高亮显示详解
- word如何设置上标形式_word上标形式
- DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (xxx.xxx.com)\n 报错解决