机器学习实战之Apriori

1. 关联分析

1.1 定义

       关联分析是一种在大规模数据上寻找物品间隐含关系的一种任务.这种关系有2种形式:频繁项集和关联规则.

(1) 频繁项集(frequent item sets): 经常出现在一起的物品的集合;

       
(2) 关联规则(association rules): 暗示两种物品之间可能存在很强的关系.

1.2 量化关联分析是否成功的算法

      
支持度和可信度是用来量化关联分析是否成功的方法.

      
(1)支持度(support) : 一个项集的支持度被定义为数据集中包含该项集的记录所占的比例.
支持度针对项集而言,可以设置最小支持度,只保留满足最小支持度的项集.以下图中的清 单为例,
{豆奶}的支持度为4/5;{豆奶,尿布}的支持度为3/5.

      
(2) 可信度或置信度(confidence) : 针对关联规则定义的. 例如:
规则{尿布}->{葡萄酒}的可信度被定义为
"支持度{尿布,葡萄酒}/支持度{尿布}"  . 支持度{尿布,葡萄酒}为3/5 , 支持度{尿布}
为4/5, 即这条规则可信度为3/4. 这意味着对于包含"尿布"的所有记录,我们的规则对其中75%的记录都适用.




2. Apriori

2.1 问题: 假设一家商店里只有4种商品:0,1,2,3. 下图显示了所有可能被购买的商品组合:




对于单个项集的支持度,
通过遍历每条记录并检查该记录是否包含该项集来计算.但是对于包含N种物品的数据集共有中项集组合,重复计算上述过程是不现实的.

2.2 Apriori原理

   
Apriori原理能够减少计算量. 

    其内容是:
若某个项集是频繁的, 那么它的子集也是频繁的; 则其逆否命题也是正确的,即 若一个项集是非频繁的,
则它的所有超集也是非频繁的.

    举例说明:
已知阴影项集{2,3}是非频繁的。利用这个知识,我们就知道项集{0,2,3},{1,2,3}以及{0,1,2,3}也是非频繁的。也就是说,一旦计算出了{2,3}的支持度,知道它是非频繁的后,就可以紧接着排除{0,2,3}、{1,2,3}和{0,1,2,3}。使用该原理可以避免项集数目的指数增长,从而在合理时间内计算出频繁项集.




2.3 实现Apriori算法来发现频繁项集

(1) Apriori算法是发现频繁项集的一种方法. 其两个输入参数分别是数据集和最小支持度.

(2) Apriori算法流程: 

首先生成所有单个物品的项集列表; 然后扫描交易记录查看哪些项集满足最小支持度要求,去掉不满足最小支持度的项集.

对剩下来的集合进行组合以生成包含两个元素的项集;
然后扫描交易记录查看哪些项集满足最小支持度要求,去掉不满足最小支持度的项集.

上述过程重复直到所有项集都被去掉

(3) Apriori算法生成频繁项集的伪代码

数据集中的每条交易记录tran:

         
对每个候选项集can:

                      
检查交易记录tran是否包含候选项集can:

                      
若包含,则增加can的计数;

对每个候选项集:

        
若该候选项集的支持度不低于最小支持度, 则保留; 反之, 则去掉.

返回所有频繁项集列表

其具体实现代码如下:

#c1是所有单个物品的集合

def createC1(dataSet):

    c1 =
[]

    for
transaction in dataSet:

  
   
 for item in transaction:

  
   
   
 if not [item] in c1:

  
   
   
   
 c1.append([item])

  
 c1.sort()

    return
map(frozenset,c1)  #frozenset是不能改变的集合,用户不能修改



#由ck得到lk的过程,即从ck选出支持度不小于指定值的项构成lk

def scanD(data,ck,minSupport):

  
 #统计每个候选项集及其对应的出现次数  
 

    ssCnt =
{}

    for
transaction in data:

  
   
 for can in ck:

  
   
   
 if can.issubset(transaction):

  
   
   
   
 if not ssCnt.has_key(can):

  
   
   
   
   
 ssCnt[can] = 1

  
   
   
   
 else:

  
   
   
   
   
 ssCnt[can] = 1



  
 #去掉不满足最小支持度的候选项集

    numItems =
float(len(data))

    retList = []
#存储满足支持度不低于最小值的项集

    supportData
= {} #存储所有项集及其支持度

    for key in
ssCnt:

  
   
 support = ssCnt[key]/numItems

  
   
 if support >= minSupport:

  
   
   
 retList.insert(0,key)

  
   
 supportData[key] = support

    return
retList,supportData #返回的retlist是ck中满足最小支持度项集的集合

(4) Apriori完整的实现

整个Apriori算法的伪代码如下:

当集合中项的个数大于0时:

          
构建一个k个项组成的候选项集的列表(k从1开始)

          
遍历数据集来筛选并保留候选项集列表中满足最小支持度的项集

          
构建由k 1个项组成的候选项集的列表

以下是实现代码:

#由频繁集lk和项集个数生成候选集ck,其中lk中每一项中含有元素k-1个,生成的ck中每一项中含有元素k个

def aprioriGen(lk,k):

    retList =
[]

    lenlk =
len(lk)

  
 #retList可能会为空

    for i in
range(lenlk):

  
   
 for j in range(i
1,lenlk): 

  
   
 #只有在两项中前k-2个元素一样时,将这两个集合合并(这样合并得到的大小就为k)

  
   
   
   
   
   
 

  
   
   
 l1 = list(lk[i])[:k-2]

  
   
   
 l2 = list(lk[j])[:k-2]

  
   
   
 l1.sort();
l2.sort()  
   
   
 

  
   
   
 if l1 == l2:

  
   
   
   
 retList.append(lk[i] | lk[j])

    return
retList

*** 在候选项集生成过程中, 只有在前k-2个项相同时才合并, 原始频繁项集中每一项含有k-1个元素,
为了合成得到每一项大小是k的候选项集列表,只有在前k-2项相同时,最后一项不同时,才有可能得到频繁项集.注意这里不是两两合并,
因为限制了候选项集的大小.

def apriori(dataSet,minSupport =
0.5):

  
 #单独产生c1,l1  
 

    c1 =
createC1(dataSet)

    data =
map(set,dataSet)

  
 l1,supportData = scanD(data,c1,minSupport)
#得到l1,大小为1的频繁项集集合

    

  
 #由l1得到c2,c2得到l2,依次循环

    l =
[l1]

    k = 2

  
 #当lk为空时,退出循环

    while
(len(l[k-2]) > 0):

  
   
 ck = aprioriGen(l[k-2],k)

  
   
 lk,supportK = scanD(data,ck,minSupport)

  
   
 supportData.update(supportK)

  
   
 l.append(lk)

  
   
 k = 1

    return
l,supportData #所有的频繁集及其支持度

3. 从频繁项集中挖掘相关规则

3.1 关联规则的量化指标是可信度. 

      
一条规则P?H的可信度定义为support(P |
H)/support(P),其中“|”表示P和H的并集。可见可信度的计算是基于项集的支持度的。

      
下图给出一个频繁项集{0,1,2,3}产生的关联规则,
其中阴影区域给出的是低可信度的规则.可以发现如果{0,1,2}?{3}是一条低可信度规则,那么所有其他以3作为后件(箭头右部包含3)的规则均为低可信度的.因为{3}的支持度肯定比包含3的项集的支持度要高,
即分子没变,但是分母增加, 则得到的可信度就降低了.

         
结论:若某条规则不满足最小可信度要求, 则其规则的所有子集也不会满足最小可信度要求. 以图4为例,假设规则{0,1,2} ?
{3}并不满足最小可信度要求,那么就知道任何左部为{0,1,2}子集的规则也不会满足最小可信度要求。

        
利用此结论可以大大减少需要测试的规则数目.

3.2 关联规则生成函数

函数generateRules()是主函数,调用另2个函数.其他两个函数是rulesFromConseq()和calcConf(),分别用于生成候选规则集合以及对规则进行评估(计算可信度)。

(1)
函数generateRules()有3个参数:频繁项集列表L、包含那些频繁项集支持数据的字典supportData、最小可信度阈值minConf。函数最后要生成一个包含可信度的规则列表bigRuleList,后面可以基于可信度对它们进行排序。L和supportData正好为函数apriori()的输出。该函数遍历L中的每一个频繁项集,并对每个频繁项集构建只包含单个元素集合的列表H1。代码中的i指示当前遍历的频繁项集包含的元素个数,freqSet为当前遍历的频繁项集(回忆L的组织结构是先把具有相同元素个数的频繁项集组织成列表,再将各个列表组成一个大列表,所以为遍历L中的频繁项集,需要使用两层for循环)。

#关联规则生成函数

def generateRules(L,supportData,minConf=0.7):

  
 #存储所有关联规则  
 

    bigRuleList
= []



    for i in
range(1,len(L)): #一条关联规则至少需要2个元素,故下标从1开始

  
   
 for freqSet in L[i]: #frequent为大小为i的项集

  
   
   
 H1 = [] #对每个频繁项集构了,建只包含单个元素的集合,即可以出现在规则右边

  
   
   
 for item in freqSet:

  
   
   
   
 H1.append(frozenset([item]))

  
   
   
 if (i > 1):

  
   
   
   
 H1 =
calcConf(freqSet,H1,supportData,bigRuleList,minConf)

  
   
   
   
 #包含三个及以上元素的频繁集

  
   
   
   
 rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf)

else:

  
   
   
   
 #包含两个元素的频繁集

  
   
   
   
 calcConf(freqSet,H1,supportData,bigRuleList,minConf)

return
bigRuleList

(2)calcConf函数: 计算规则的可信度,并过滤出满足最小可信度要求的规则.
返回值prunedH保存规则列表的右部,这个值将在下一个函数rulesFromConseq()中用到。

函数实现代码如下:

#处理包含两个元素的频繁集,计算规则的可信度,并过滤出满足最小可信度要求的规则

def calcConf(freqSet,H,supportData,brl,minConf=0.7):

  
 #保存关联规则的列表

    prunedH =
[]



    for conseq
in H:

  
   
 #对一个频繁集合,其分母都是一样的,supprot{1,2}/support{1},supprot{1,2}/support{2}

conf =
supportData[freqSet]/supportData[freqSet-conseq]

  
   
 if conf >= minConf:

  
   
   
 print freqSet - conseq,
'---->',conseq,'  conf:',conf

  
   
   
 brl.append((freqSet-conseq,conseq,conf))

  
   
   
 prunedH.append(conseq)

    return
prunedH

(2) rulesFromConseq()函数; 根据当前候选规则集H生成下一层候选规则集 ;

      
H为规则右边可能出现的频繁项集, H中元素的长度逐渐增大; 比如 原频繁集包含3个元素,则出现在规则右边的元素可能有1个,2个;
假设规则{0,1,2} ?
{3}并不满足最小可信度要求,那么就知道任何左部为{0,1,2}子集的规则也不会满足最小可信度要求,即不考虑{0,1} ?
{2,3}。因此我们先从右边只有一个元素时开始,只有存在可以出现在规则右边的元素,右边才有可能出现元素个数为2的情况.数据分析师培训



代码如下:

#根据当前候选规则集H生成下一层候选规则集,H是可以出现在规则右边的元素列表

def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.7):

  
 #可以出现在规则右边的元素个数[1]=1,[1,2]=2,从1个元素增加直到小于freqSet的总个数都行

m =
len(H[0])



    if
(len(freqSet) > (m 1)):

  
   
 hmp1 = aprioriGen(H,m 1) #产生大小为m
1的频繁集列表,(1,2->3)->(1->2,3),生成下一层H

hmp1 =
calcConf(freqSet,hmp1,supportData,brl,minConf)

  
   
 if (len(hmp1) >
1):#规则右边的元素个数还可以增加

  
   
   
 rulesFromConseq(freqSet,hmp1,supportData,brl,minConf)

机器学习实战之Apriori的更多相关文章

  1. 基于Python的机器学习实战:Apriori

    目录: 1.关联分析 2. Apriori 原理 3. 使用 Apriori 算法来发现频繁集 4.从频繁集中挖掘关联规则 5. 总结 1.关联分析  返回目录 关联分析是一种在大规模数据集中寻找有趣 ...

  2. 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...

  3. Python两步实现关联规则Apriori算法,参考机器学习实战,包括频繁项集的构建以及关联规则的挖掘

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  4. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

    机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析 关键字:Apriori.关联规则挖掘.频繁项集作者:米仓山下时间:2018 ...

  5. 机器学习实战笔记(Python实现)-00-readme

    近期学习机器学习,找到一本不错的教材<机器学习实战>.特此做这份学习笔记,以供日后翻阅. 机器学习算法分为有监督学习和无监督学习.这本书前两部分介绍的是有监督学习,第三部分介绍的是无监督学 ...

  6. 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...

  7. 【机器学习实战】Machine Learning in Action 代码 视频 项目案例

    MachineLearning 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远 Machine Learning in Action (机器学习实战) | ApacheCN(apa ...

  8. 机器学习实战(Machine Learning in Action)学习笔记————10.奇异值分解(SVD)原理、基于协同过滤的推荐引擎、数据降维

    关键字:SVD.奇异值分解.降维.基于协同过滤的推荐引擎作者:米仓山下时间:2018-11-3机器学习实战(Machine Learning in Action,@author: Peter Harr ...

  9. 学习笔记之机器学习实战 (Machine Learning in Action)

    机器学习实战 (豆瓣) https://book.douban.com/subject/24703171/ 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中 ...

随机推荐

  1. LUOGU P3161 [CQOI2012]模拟工厂 (贪心)

    传送门 解题思路 贪心,首先因为\(n\)比较小,可以\(2^n\)枚举子集.然后判断的时候就每次看后面的如果用最大生产力生产能不能达成目标,解一个二次函数. 代码 #include<iostr ...

  2. python模块operator对排序的辅助功能

    一.介绍 该operator模块导出一组与Python的内部运算符相对应的高效函数.例如,等同于表达式.函数名称是用于特殊类方法的函数名称; 为方便起见,还提供了没有前导和尾随的变体.operator ...

  3. VS2010-MFC(菜单:VS2010菜单资源详解)

    转自:http://www.jizhuomi.com/software/210.html 上一节讲了标签控件Tab Control以后,常用控件的内容就全部讲完了,当然并没有包括所有控件,主要是一些很 ...

  4. Pascal 排序算法

    Pascal 排序   排序 排序就是将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程.排序问题是一个十分重要的问题,并且排序的方法有很多种: 例子:输入20个数,将它们按照从高到低的次序排 ...

  5. PAT甲级——A1115 Counting Nodes in a BST【30】

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  6. 矩阵连乘 /// 区间DP oj1900

    题目大意: 输入t :t为测试用例个数 接下来t个测试 每个测试用例 第一行输入n: n为矩阵个数 保证n个矩阵依序是可乘的 接下来n行 每行输入p,q:p为长度q为宽度 对给定的n个矩阵确定一个计算 ...

  7. selenium基础(警告框的处理)

    selenium基础(警告框的处理) 在webdriver中处理JavaScript所产生的的警告框有三种类型 alert confirm prompt 划转到警告框的方法是:driver.switc ...

  8. vue 利用intersectionOberver实现全局appear/disappear事件

    搬运自:https://juejin.im/post/5cd10959f265da03a00fe5c6 效果: demo地址: https://codepen.io/deepkolos/pen/OYP ...

  9. LeetCode 206.反转链表(Python3)

    题目: 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶:你可 ...

  10. Oracle如何用单字段或多字段进行查重

    最近在整理数据形成信用报告,发现重复的数据真的多,梳理都好久.我就做个笔记把去掉重复数据的方法整理下来.方便我后期查阅. 我将我目前已知的两种去重方法分为:视图去重和表去重.原理就是有无rowid这个 ...