浅谈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的web.py框架中url的设定方法
Jul 11 Python
解决python删除文件的权限错误问题
Apr 24 Python
Python调用adb命令实现对多台设备同时进行reboot的方法
Oct 15 Python
如何通过python画loss曲线的方法
Jun 26 Python
python 梯度法求解函数极值的实例
Jul 10 Python
python如何实现不可变字典inmutabledict
Jan 08 Python
Python编程快速上手——Excel表格创建乘法表案例分析
Feb 28 Python
Django+python服务器部署与环境部署教程详解
Mar 30 Python
Python实现爬取并分析电商评论
Jun 19 Python
Scrapy-Redis之RedisSpider与RedisCrawlSpider详解
Nov 18 Python
Django中使用Celery的方法步骤
Dec 07 Python
使用opencv-python如何打开USB或者笔记本前置摄像头
Jun 21 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
WINDOWS服务器安装多套PHP的另类解决方案
2006/10/09 PHP
jQuery 使用手册(三)
2009/09/23 Javascript
jQuery 打造动态下滑菜单实现说明
2010/04/15 Javascript
js鼠标左右键 键盘值小结
2010/06/11 Javascript
js 利用className得到对象的实现代码
2011/11/15 Javascript
页面装载js及性能分析方法介绍
2014/03/21 Javascript
jQuery实现列表内容的动态载入特效
2015/08/08 Javascript
jquery带有索引按钮且自动轮播切换特效代码分享
2015/09/15 Javascript
每天一篇javascript学习小结(RegExp对象)
2015/11/17 Javascript
一种基于浏览器的自动小票机打印实现方案(js版)
2016/07/26 Javascript
jQuery.uploadify文件上传组件实例讲解
2016/09/23 Javascript
js继承实现方法详解
2016/12/16 Javascript
Bootstrap CSS布局之按钮
2016/12/17 Javascript
js实现显示手机号码效果
2017/03/09 Javascript
JS实现延迟隐藏功能的方法(类似QQ头像鼠标放上展示信息)
2017/12/28 Javascript
vue项目打包后打开页面空白解决办法
2018/06/29 Javascript
关于JavaScript中高阶函数的魅力详解
2018/09/07 Javascript
vue.js实现二级菜单效果
2019/10/19 Javascript
JavaScript装箱及拆箱boxing及unBoxing用法解析
2020/06/15 Javascript
如何运行Python程序的方法
2013/04/21 Python
Python中列表、字典、元组、集合数据结构整理
2014/11/20 Python
Ruby使用eventmachine为HTTP服务器添加文件下载功能
2016/04/20 Python
对python特殊函数 __call__()的使用详解
2019/07/02 Python
详解如何在cmd命令窗口中搭建简单的python开发环境
2019/08/29 Python
Python中zip()函数的简单用法举例
2019/09/02 Python
Python devel安装失败问题解决方案
2020/06/09 Python
PyCharm安装PyQt5及其工具(Qt Designer、PyUIC、PyRcc)的步骤详解
2020/11/02 Python
详解Html5微信支付爬坑之路
2018/07/24 HTML / CSS
世界上最大的铁人三项商店:Tri UK
2020/11/04 全球购物
国庆宣传标语
2014/06/30 职场文书
国庆庆典邀请函
2015/02/02 职场文书
开会通知
2015/04/20 职场文书
优秀党员先进事迹材料2016
2016/02/29 职场文书
Python基础之进程详解
2021/05/21 Python
js作用域及作用域链工作引擎
2022/07/07 Javascript
Win10鼠标宏怎么设置?win10系统鼠标宏的设置方法
2022/08/14 数码科技