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算法挖掘规则计算频繁项间的置信度相关推荐

  1. 关联分析Apriori算法和FP-growth算法初探

    1. 关联分析是什么? Apriori和FP-growth算法是一种关联算法,属于无监督算法的一种,它们可以自动从数据中挖掘出潜在的关联关系.例如经典的啤酒与尿布的故事.下面我们用一个例子来切入本文对 ...

  2. 使用Apriori算法和FP-growth算法进行关联分析

    目录 1. 关联分析 2. Apriori原理 3. 使用Apriori算法来发现频繁集 4. 使用FP-growth算法来高效发现频繁项集 5. 示例:从新闻网站点击流中挖掘新闻报道 扩展阅读 系列 ...

  3. 关联规则挖掘(Apriori算法和FP-Growth算法)

    一.关联规则概述 1.关联规则分析用于在一个数据集中找出各种数据项之间的关联关系,广泛用于购物篮数据.个性化推荐.预警.时尚穿搭.生物信息学.医疗诊断.网页挖掘和科学数据分析中 2.关联规则分析又称购 ...

  4. 【Apriori算法和FP-growth算法】

    Apriori算法 通过例题解析算法思路 1.频繁项集思路描述 通过支持度算出min_sup,进行基础比较,大于min_sup的写入频繁1项集,然后依次写出2项集,直到k项集. 2.强关联解题思路 依 ...

  5. 机器学习实战—使用FP-growth算法来高效发现频繁项集

    FP-growth算法基于Apriori构建,但采用了高级的数据结构减少扫描次数,大大加快了算法速度.FP-growth算法只需要对数据库进行两次扫描,而Apriori算法对于每个潜在的频繁项集都会扫 ...

  6. 关联规则挖掘算法: Aprior算法和Fpgrowth算法

      关联规则挖掘的目的是挖掘不同物品(item)之前的相关性,啤酒和尿布的故事就是一个典型的成功例子.关联规则挖掘思想简单高效,在广告推荐领域也有较多的应用,主要用于推荐模型落地前的流量探索以及构建规 ...

  7. 12使用FP-growth算法来高效发现频繁项集

    第12章 使用FP-growth算法来高效发现频繁项集 一.背景 大家都用过搜索引擎.当我们输入一个单词或单词的一份,搜索引擎就会自动补全查询词项.例如:当我们在百度输入"为什么" ...

  8. 【机器学习实战】第12章 使用 FP-growth 算法来高效发现频繁项集

    第12章 使用FP-growth算法来高效发现频繁项集 前言 在 第11章 时我们已经介绍了用 Apriori 算法发现 频繁项集 与 关联规则. 本章将继续关注发现 频繁项集 这一任务,并使用 FP ...

  9. Apriori算法和FP-Tree算法简介

    Apriori关联分析算法 Apriori 算法是挖掘产生关联规则所需频繁项集的基本算法,也是最著名的关联分析算法之一. 1. Apriori 算法 Apriori 算法使用了逐层搜索的迭代方法,即用 ...

  10. 小白入门关联规则之子图模式的类Apriori方法和gSpan算法挖掘学习

    关联规则之子图模式 关联规则之子图模式 文章目的 基本概念 类apriori方法 gSpan算法 DFS编码 最右扩展 实验研究 参考博客 参考文献 关联规则之子图模式 文章目的 了解子图模式在什么情 ...

最新文章

  1. 多校1010 Taotao Picks Apples
  2. 如何保护企业网络免受DDoS攻击?—Vecloud微云
  3. ScrollView反弹效果
  4. JPA EntityManager详解
  5. 接口中默认方法和静态方法_接口中的默认方法和静态方法
  6. junit:junit_简而言之,JUnit:另一个JUnit教程
  7. 【机器学习】机器学习中的异常值的识别和处理
  8. ospf避免环路_【网络干货】超全的OSPF路由协议技术汇总解析
  9. 新微擎 v1.7.9 图文回复 标题emoji
  10. Vue 学习笔记(4)Vue-cli4 项目搭建 + 目录结构 + 项目打包、部署
  11. dll反编译工具总结
  12. atitit 每季度日程表 每季度流程 v3 qaf.docx Ver history V2 add diary cyar data 3 cate V3 fix detail 3cate ,
  13. 基于深度学习的单目人体姿态估计方法综述(一)
  14. uri和url的区别与联系(一看就理解)
  15. eps在c语言,C语言中eps指的是什么东西?
  16. KF、EKF、ESKF的区别与联系
  17. [BZOJ4416][Shoi2013]阶乘字符串 状态压缩dp
  18. Lucene高亮显示详解
  19. word如何设置上标形式_word上标形式
  20. DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (xxx.xxx.com)\n 报错解决

热门文章

  1. Jackme空气净化器 去除雾霾呵护家人健康神器
  2. python编程从入门到实践
  3. PHP发卡自动源码,PHP自动化售货发卡网源码
  4. vs 2015 密钥
  5. SPC软件:全程监控食品质量
  6. RTI_DDS自定义插件开发 5 专属区域(_xxEA)
  7. Microsoft SQL Server 2008 R2 软件安装
  8. MTK Android 配置pmic电源
  9. NOIp2017 题解
  10. MATLAB深度学习网络包 Alexnet / Googlenet / Vgg19