浅谈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 相关文章推荐
centos 下面安装python2.7 +pip +mysqld
Nov 18 Python
将Python代码打包为jar软件的简单方法
Aug 04 Python
Python中的异常处理相关语句基础学习笔记
Jul 11 Python
Python多线程实现同步的四种方式
May 02 Python
Python socket实现简单聊天室
Apr 01 Python
Python爬取商家联系电话以及各种数据的方法
Nov 10 Python
python利用百度AI实现文字识别功能
Nov 27 Python
kali中python版本的切换方法
Jul 11 Python
python实现图片横向和纵向拼接
Mar 05 Python
VSCode基础使用与VSCode调试python程序入门的图文教程
Mar 30 Python
Selenium之模拟登录铁路12306的示例代码
Jul 31 Python
python3 googletrans超时报错问题及翻译工具优化方案 附源码
Dec 23 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
PHP 常用函数库和一些实用小技巧
2009/01/01 PHP
浅析PHP数据导出知识点
2018/02/17 PHP
PHP中abstract(抽象)、final(最终)和static(静态)原理与用法详解
2020/06/05 PHP
js获取元素在浏览器中的绝对位置
2010/07/24 Javascript
JS实现黑色大气的二级导航菜单效果
2015/09/18 Javascript
JS实现鼠标滑过链接改变网页背景颜色的方法
2015/10/20 Javascript
浅谈JavaScript函数的四种存在形态
2016/06/08 Javascript
jQuery中table数据的值拷贝和拆分
2017/03/19 Javascript
微信小程序 五星评分的实现实例
2017/08/04 Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
2017/10/17 Javascript
使用mock.js随机数据和使用express输出json接口的实现方法
2018/01/07 Javascript
详解Vue.js v-for不支持IE9的解决方法
2018/12/29 Javascript
bootstrap-paginator服务器端分页使用方法详解
2020/02/13 Javascript
[01:38]DOTA2第二届亚洲邀请赛中国区预选赛出线战队晋级之路
2017/01/17 DOTA
python的类变量和成员变量用法实例教程
2014/08/25 Python
Python的Tornado框架的异步任务与AsyncHTTPClient
2016/06/27 Python
深入理解python中的select模块
2017/04/23 Python
python的多重继承的理解
2017/08/06 Python
利用python批量修改word文件名的方法示例
2017/10/17 Python
详解Python在七牛云平台的应用(一)
2017/12/05 Python
Python实现找出数组中第2大数字的方法示例
2018/03/26 Python
django+mysql的使用示例
2018/11/23 Python
Python模块、包(Package)概念与用法分析
2019/05/31 Python
python自动化测试之异常及日志操作实例分析
2019/11/09 Python
解决import tensorflow导致jupyter内核死亡的问题
2021/02/06 Python
CSS3系列之3D制作方法案例
2017/08/14 HTML / CSS
天猫超市:阿里巴巴打造的网上超市
2016/11/02 全球购物
日本乐天官方海外转运服务:Rakuten Global Express
2018/11/30 全球购物
运动鞋、街头服装、手表和手袋的实时市场:StockX
2020/11/25 全球购物
工程管理造价应届生求职信
2013/11/13 职场文书
高中班级口号
2014/06/09 职场文书
厨师长岗位职责范本
2014/08/25 职场文书
先进班组材料范文
2014/12/25 职场文书
工程款申请报告
2015/05/15 职场文书
2016年区委书记抓基层党建工作公开承诺书
2016/03/25 职场文书
MySQL存储过程及语法详解
2022/08/05 MySQL