浅谈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字典操作简明总结
Apr 13 Python
python安装与使用redis的方法
Apr 19 Python
用 Python 爬了爬自己的微信朋友(实例讲解)
Aug 25 Python
python实现图像识别功能
Jan 29 Python
python实现人人自动回复、抢沙发功能
Jun 08 Python
详解Python发送email的三种方式
Oct 18 Python
Python爬虫图片懒加载技术 selenium和PhantomJS解析
Sep 18 Python
Python input函数使用实例解析
Nov 22 Python
Python连接Hadoop数据中遇到的各种坑(汇总)
Apr 14 Python
python实现企业微信定时发送文本消息的示例代码
Nov 24 Python
Python+Appium实现自动抢微信红包
May 21 Python
Python中使用tkFileDialog实现文件选择、保存和路径选择
May 20 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
discuz 首页四格:最新话题+最新回复+热门话题+精华文章插件
2007/08/19 PHP
php 带逗号千位符数字的处理方法
2012/01/10 PHP
基于php iconv函数的使用详解
2013/06/09 PHP
php跨域cookie共享使用方法
2014/02/20 PHP
分享PHP守护进程类
2015/12/30 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
详解PHP5.6.30与Apache2.4.x配置
2017/06/02 PHP
PHP实现限制IP访问及提交次数的方法详解
2017/07/17 PHP
详解PHP如何更好的利用PHPstorm的自动提示
2017/08/18 PHP
显示js对象所有属性和方法的函数
2009/10/16 Javascript
jQuery getJSON 处理json数据的代码
2010/07/26 Javascript
弹出层之1:JQuery.Boxy (一) 使用介绍
2011/10/06 Javascript
jQuery 中使用JSON的实现代码
2011/12/01 Javascript
js给页面加style无效果的解决方法
2014/01/20 Javascript
jquery实现聚光灯效果的方法
2015/02/06 Javascript
JS中利用localStorage防止页面动态添加数据刷新后数据丢失
2017/03/10 Javascript
Vue.js仿微信聊天窗口展示组件功能
2017/08/11 Javascript
快速解决vue-cli不能初始化webpack模板的问题
2018/03/20 Javascript
JavaScript实现封闭区域布尔运算的示例代码
2018/06/25 Javascript
axios对请求各种异常情况处理的封装方法
2018/09/25 Javascript
JavaScript常用内置对象用法分析
2019/07/09 Javascript
layer的prompt弹出框,点击回车,触发确定事件的方法
2019/09/06 Javascript
Vue3+elementui plus创建项目的方法
2020/12/01 Vue.js
vue3 watch和watchEffect的使用以及有哪些区别
2021/01/26 Vue.js
Vue中避免滥用this去读取data中数据
2021/03/02 Vue.js
利用python发送和接收邮件
2016/09/27 Python
python实现Excel文件转换为TXT文件
2019/04/28 Python
python django下载大的csv文件实现方法分析
2019/07/19 Python
python实现回旋矩阵方式(旋转矩阵)
2019/12/04 Python
Python使用xlrd实现读取合并单元格
2020/07/09 Python
Python使用windows设置定时执行脚本
2020/11/12 Python
英国探险旅游专家:Explore
2018/12/20 全球购物
Nanushka官网:匈牙利服装品牌
2019/08/14 全球购物
《我的伯父鲁迅先生》教学反思
2014/02/12 职场文书
cf搞笑广告词
2014/03/14 职场文书
合伙经营协议书范本
2014/04/18 职场文书