浅谈Python实现Apriori算法介绍


Posted in Python onDecember 20, 2017

导读:

随着大数据概念的火热,啤酒与尿布的故事广为人知。我们如何发现买啤酒的人往往也会买尿布这一规律?数据挖掘中的用于挖掘频繁项集和关联规则的Apriori算法可以告诉我们。本文首先对Apriori算法进行简介,而后进一步介绍相关的基本概念,之后详细的介绍Apriori算法的具体策略和步骤,最后给出Python实现代码。

1.Apriori算法简介

Apriori算法是经典的挖掘频繁项集和关联规则的数据挖掘算法。A priori在拉丁语中指"来自以前"。当定义问题时,通常会使用先验知识或者假设,这被称作"一个先验"(a priori)。Apriori算法的名字正是基于这样的事实:算法使用频繁项集性质的先验性质,即频繁项集的所有非空子集也一定是频繁的。Apriori算法使用一种称为逐层搜索的迭代方法,其中k项集用于探索(k+1)项集。首先,通过扫描数据库,累计每个项的计数,并收集满足最小支持度的项,找出频繁1项集的集合。该集合记为L1。然后,使用L1找出频繁2项集的集合L2,使用L2找出L3,如此下去,直到不能再找到频繁k项集。每找出一个Lk需要一次数据库的完整扫描。Apriori算法使用频繁项集的先验性质来压缩搜索空间。

2. 基本概念

  1. 项与项集:设itemset={item1, item_2, …, item_m}是所有项的集合,其中,item_k(k=1,2,…,m)成为项。项的集合称为项集(itemset),包含k个项的项集称为k项集(k-itemset)。
  2. 事务与事务集:一个事务T是一个项集,它是itemset的一个子集,每个事务均与一个唯一标识符Tid相联系。不同的事务一起组成了事务集D,它构成了关联规则发现的事务数据库。
  3. 关联规则:关联规则是形如A=>B的蕴涵式,其中A、B均为itemset的子集且均不为空集,而A交B为空。
  4. 支持度(support):关联规则的支持度定义如下:

浅谈Python实现Apriori算法介绍

其中浅谈Python实现Apriori算法介绍表示事务包含集合A和B的并(即包含A和B中的每个项)的概率。注意与P(A or B)区别,后者表示事务包含A或B的概率。

置信度(confidence):关联规则的置信度定义如下:

浅谈Python实现Apriori算法介绍

项集的出现频度(support count):包含项集的事务数,简称为项集的频度、支持度计数或计数。

频繁项集(frequent itemset):如果项集I的相对支持度满足事先定义好的最小支持度阈值(即I的出现频度大于相应的最小出现频度(支持度计数)阈值),则I是频繁项集。

强关联规则:满足最小支持度和最小置信度的关联规则,即待挖掘的关联规则。

3. 实现步骤

一般而言,关联规则的挖掘是一个两步的过程:

  1. 找出所有的频繁项集
  2. 由频繁项集产生强关联规则

3.1挖掘频繁项集

3.1.1相关定义

连接步骤:频繁(k-1)项集Lk-1的自身连接产生候选k项集Ck

Apriori算法假定项集中的项按照字典序排序。如果Lk-1中某两个的元素(项集)itemset1和itemset2的前(k-2)个项是相同的,则称itemset1和itemset2是可连接的。所以itemset1与itemset2连接产生的结果项集是{itemset1[1], itemset1[2], …, itemset1[k-1], itemset2[k-1]}。连接步骤包含在下文代码中的create_Ck函数中。

剪枝策略

由于存在先验性质:任何非频繁的(k-1)项集都不是频繁k项集的子集。因此,如果一个候选k项集Ck的(k-1)项子集不在Lk-1中,则该候选也不可能是频繁的,从而可以从Ck中删除,获得压缩后的Ck。下文代码中的is_apriori函数用于判断是否满足先验性质,create_Ck函数中包含剪枝步骤,即若不满足先验性质,剪枝。

删除策略

基于压缩后的Ck,扫描所有事务,对Ck中的每个项进行计数,然后删除不满足最小支持度的项,从而获得频繁k项集。删除策略包含在下文代码中的generate_Lk_by_Ck函数中。

3.1.2 步骤

  1.  每个项都是候选1项集的集合C1的成员。算法扫描所有的事务,获得每个项,生成C1(见下文代码中的create_C1函数)。然后对每个项进行计数。然后根据最小支持度从C1中删除不满足的项,从而获得频繁1项集L1。
  2. 对L1的自身连接生成的集合执行剪枝策略产生候选2项集的集合C2,然后,扫描所有事务,对C2中每个项进行计数。同样的,根据最小支持度从C2中删除不满足的项,从而获得频繁2项集L2。
  3. 对L2的自身连接生成的集合执行剪枝策略产生候选3项集的集合C3,然后,扫描所有事务,对C3每个项进行计数。同样的,根据最小支持度从C3中删除不满足的项,从而获得频繁3项集L3。
  4. 以此类推,对Lk-1的自身连接生成的集合执行剪枝策略产生候选k项集Ck,然后,扫描所有事务,对Ck中的每个项进行计数。然后根据最小支持度从Ck中删除不满足的项,从而获得频繁k项集。

3.2 由频繁项集产生关联规则

一旦找出了频繁项集,就可以直接由它们产生强关联规则。产生步骤如下:

对于每个频繁项集itemset,产生itemset的所有非空子集(这些非空子集一定是频繁项集);

对于itemset的每个非空子集s,如果浅谈Python实现Apriori算法介绍,则输出浅谈Python实现Apriori算法介绍,其中min_conf是最小置信度阈值。

4. 样例以及Python实现代码

下图是《数据挖掘:概念与技术》(第三版)中挖掘频繁项集的样例图解。

浅谈Python实现Apriori算法介绍

本文基于该样例的数据编写Python代码实现Apriori算法。代码需要注意如下两点:

  1. 由于Apriori算法假定项集中的项是按字典序排序的,而集合本身是无序的,所以我们在必要时需要进行set和list的转换;
  2. 由于要使用字典(support_data)记录项集的支持度,需要用项集作为key,而可变集合无法作为字典的key,因此在合适时机应将项集转为固定集合frozenset。
"""
# Python 2.7
# Filename: apriori.py
# Author: llhthinker
# Email: hangliu56[AT]gmail[DOT]com
# Blog: http://www.cnblogs.com/llhthinker/p/6719779.html
# Date: 2017-04-16
"""


def load_data_set():
  """
  Load a sample data set (From Data Mining: Concepts and Techniques, 3th Edition)
  Returns: 
    A data set: A list of transactions. Each transaction contains several items.
  """
  data_set = [['l1', 'l2', 'l5'], ['l2', 'l4'], ['l2', 'l3'],
      ['l1', 'l2', 'l4'], ['l1', 'l3'], ['l2', 'l3'],
      ['l1', 'l3'], ['l1', 'l2', 'l3', 'l5'], ['l1', 'l2', 'l3']]
  return data_set


def create_C1(data_set):
  """
  Create frequent candidate 1-itemset C1 by scaning data set.
  Args:
    data_set: A list of transactions. Each transaction contains several items.
  Returns:
    C1: A set which contains all frequent candidate 1-itemsets
  """
  C1 = set()
  for t in data_set:
    for item in t:
      item_set = frozenset([item])
      C1.add(item_set)
  return C1


def is_apriori(Ck_item, Lksub1):
  """
  Judge whether a frequent candidate k-itemset satisfy Apriori property.
  Args:
    Ck_item: a frequent candidate k-itemset in Ck which contains all frequent
         candidate k-itemsets.
    Lksub1: Lk-1, a set which contains all frequent candidate (k-1)-itemsets.
  Returns:
    True: satisfying Apriori property.
    False: Not satisfying Apriori property.
  """
  for item in Ck_item:
    sub_Ck = Ck_item - frozenset([item])
    if sub_Ck not in Lksub1:
      return False
  return True


def create_Ck(Lksub1, k):
  """
  Create Ck, a set which contains all all frequent candidate k-itemsets
  by Lk-1's own connection operation.
  Args:
    Lksub1: Lk-1, a set which contains all frequent candidate (k-1)-itemsets.
    k: the item number of a frequent itemset.
  Return:
    Ck: a set which contains all all frequent candidate k-itemsets.
  """
  Ck = set()
  len_Lksub1 = len(Lksub1)
  list_Lksub1 = list(Lksub1)
  for i in range(len_Lksub1):
    for j in range(1, len_Lksub1):
      l1 = list(list_Lksub1[i])
      l2 = list(list_Lksub1[j])
      l1.sort()
      l2.sort()
      if l1[0:k-2] == l2[0:k-2]:
        Ck_item = list_Lksub1[i] | list_Lksub1[j]
        # pruning
        if is_apriori(Ck_item, Lksub1):
          Ck.add(Ck_item)
  return Ck


def generate_Lk_by_Ck(data_set, Ck, min_support, support_data):
  """
  Generate Lk by executing a delete policy from Ck.
  Args:
    data_set: A list of transactions. Each transaction contains several items.
    Ck: A set which contains all all frequent candidate k-itemsets.
    min_support: The minimum support.
    support_data: A dictionary. The key is frequent itemset and the value is support.
  Returns:
    Lk: A set which contains all all frequent k-itemsets.
  """
  Lk = set()
  item_count = {}
  for t in data_set:
    for item in Ck:
      if item.issubset(t):
        if item not in item_count:
          item_count[item] = 1
        else:
          item_count[item] += 1
  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] / t_num
  return Lk


def generate_L(data_set, k, min_support):
  """
  Generate all frequent itemsets.
  Args:
    data_set: A list of transactions. Each transaction contains several items.
    k: Maximum number of items for all frequent itemsets.
    min_support: The minimum support.
  Returns:
    L: The list of Lk.
    support_data: A dictionary. The key is frequent itemset and the value is support.
  """
  support_data = {}
  C1 = create_C1(data_set)
  L1 = generate_Lk_by_Ck(data_set, C1, min_support, support_data)
  Lksub1 = L1.copy()
  L = []
  L.append(Lksub1)
  for i in range(2, k+1):
    Ci = create_Ck(Lksub1, i)
    Li = generate_Lk_by_Ck(data_set, Ci, min_support, support_data)
    Lksub1 = Li.copy()
    L.append(Lksub1)
  return L, support_data


def generate_big_rules(L, support_data, min_conf):
  """
  Generate big rules from frequent itemsets.
  Args:
    L: The list of Lk.
    support_data: A dictionary. The key is frequent itemset and the value is support.
    min_conf: Minimal confidence.
  Returns:
    big_rule_list: A list which contains all big rules. Each big rule is represented
            as a 3-tuple.
  """
  big_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):
          conf = 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 big_rule_list:
            # print freq_set-sub_set, " => ", sub_set, "conf: ", conf
            big_rule_list.append(big_rule)
      sub_set_list.append(freq_set)
  return big_rule_list


if __name__ == "__main__":
  """
  Test
  """
  data_set = load_data_set()
  L, support_data = generate_L(data_set, k=3, min_support=0.2)
  big_rules_list = generate_big_rules(L, support_data, min_conf=0.7)
  for Lk in L:
    print "="*50
    print "frequent " + str(len(list(Lk)[0])) + "-itemsets\t\tsupport"
    print "="*50
    for freq_set in Lk:
      print freq_set, support_data[freq_set]
  print
  print "Big Rules"
  for item in big_rules_list:
    print item[0], "=>", item[1], "conf: ", item[2]

代码运行结果截图如下:

浅谈Python实现Apriori算法介绍

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python下载Bing图片(代码)
Nov 07 Python
python用来获得图片exif信息的库实例分析
Mar 16 Python
合并百度影音的离线数据( with python 2.3)
Aug 04 Python
python编程开发之textwrap文本样式处理技巧
Nov 13 Python
Python中__init__.py文件的作用详解
Sep 18 Python
python中csv文件的若干读写方法小结
Jul 04 Python
Python文件读写常见用法总结
Feb 22 Python
python切片的步进、添加、连接简单操作示例
Jul 11 Python
Python 转换文本编码实现解析
Aug 27 Python
django 多对多表的创建和插入代码实现
Sep 09 Python
Python tkinter和exe打包的方法
Feb 05 Python
pytorch进行上采样的种类实例
Feb 18 Python
利用Python如何生成hash值示例详解
Dec 20 #Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 #Python
python实现神经网络感知器算法
Dec 20 #Python
Python代码实现KNN算法
Dec 20 #Python
详解appium+python 启动一个app步骤
Dec 20 #Python
浅谈Django自定义模板标签template_tags的用处
Dec 20 #Python
Python实现感知机(PLA)算法
Dec 20 #Python
You might like
这部番真是良心,画质好到像风景区,剧情让人跟着小公会热血沸腾
2020/03/10 日漫
ThinkPHP之用户注册登录留言完整实例
2014/07/22 PHP
ecshop 2.72如何修改后台访问地址
2015/03/03 PHP
php  PATH_SEPARATOR判断当前服务器系统类型实例
2016/10/28 PHP
PHP实现微信图片上传到服务器的方法示例
2017/06/29 PHP
javascript 表格排序和表头浮动效果(扩展SortTable)
2009/04/07 Javascript
JQUBar 基于JQUERY的柱状图插件
2010/11/23 Javascript
JavaScript判断DOM何时加载完毕的技巧
2012/11/11 Javascript
JavaScript对象的property属性详解
2014/04/01 Javascript
给html超链接设置事件不使用href来完成跳
2014/04/20 Javascript
举例详解AngularJS中ngShow和ngHide的使用方法
2015/06/19 Javascript
jquery获得当前html页面源码的方法
2015/07/14 Javascript
Bootstrap基本组件学习笔记之导航(10)
2016/12/07 Javascript
深入解析js轮播插件核心代码的实现过程
2017/04/14 Javascript
vue 使用eventBus实现同级组件的通讯
2018/03/02 Javascript
Servlet3.0与纯javascript通过Ajax交互的实例详解
2018/03/18 Javascript
浅谈KOA2 Restful方式路由初探
2019/03/14 Javascript
通过实例解析JavaScript for in及for of区别
2020/06/15 Javascript
使用简单工厂模式来进行Python的设计模式编程
2016/03/01 Python
Python3实现发送QQ邮件功能(文本)
2017/12/15 Python
Python实现改变与矩形橡胶的线条的颜色代码示例
2018/01/05 Python
Python爬豆瓣电影实例
2018/02/23 Python
在python中利用numpy求解多项式以及多项式拟合的方法
2019/07/03 Python
Python文件操作方法详解
2020/02/09 Python
Django crontab定时任务模块操作方法解析
2020/09/10 Python
HTML5里autofocus自动聚焦属性使用介绍
2016/06/22 HTML / CSS
金牌葡萄酒俱乐部:Gold Medal Wine Club
2017/11/02 全球购物
如何客观的进行自我评价
2013/12/17 职场文书
珍珠奶茶店创业计划书
2014/01/11 职场文书
合唱兴趣小组活动总结
2014/07/10 职场文书
没有孩子的离婚协议书怎么写
2014/09/17 职场文书
师范生见习报告
2014/10/31 职场文书
2014年学校团委工作总结
2014/12/20 职场文书
消防验收申请报告
2015/05/15 职场文书
关于SpringBoot 使用 Redis 分布式锁解决并发问题
2021/11/17 Redis
Nginx 502 bad gateway错误解决的九种方案及原因
2022/08/14 Servers