机器学习实践之使用Apriori算法进行关联分析

时间:2021-04-23 16:48:57

本文根据最近学习机器学习书籍网络文章的情况,特将一些学习心得做了总结,详情如下.如有不当之处,请各位大拿多多指点,在此谢过。


一、概述

1、背景故事

      日常生活中,当我们去商店去购物的时候,实际上都包含了机器学习的当下和未来的场景应用,这包括物品的展示方式、购物之后的优惠券的提供、用户忠诚度计划等等。这些其实都离不开对大量数据的分析。商店希望从顾客身上获得更多的利润,所以必然使用各种技术来达到这一目的。

      忠诚度计划是指顾客可以利用会员卡获得一定的购物折扣,利用这一计划,商店可以了解顾客购买的物品。当然,即使不使用会员卡,商店也可以查看到顾客购买物品时所使用信用卡的信用记录。即使顾客不使用信用卡而用现金支付代替,商店也可以查看到顾客购买物品的组合。

      通过查看哪些商品一起购买,商店可以了解顾客的购物行为。这种从大量数据海洋中提取的信息可以用于指定商品定价、市场促销、存货管理等环节。从大规模数据海洋中寻找物品之间隐含的关系被称为关联分析(Associationanalysis)或关联规则分析(AssociationRuleLearning)。这里的主要问题在于,寻找物品的不同组合是一项艰巨的任务,所需要的计算代价很高,蛮力搜索不能解决这一问题,需要使用更智能的方法在合理的实际范围内找到频繁项集。这里先讨论关联分析,然后梳理Apriori算法原理。

2、相关概念及分析

关联分析是一种在大规模数据集中寻找有趣关系的任务。这些关系可以分为两种:频繁项集或关联规则。频繁项集是经常一块出现的物品的集合。关联规则是暗示两种物品可能存在很强的关系。我们可以通过下图给出商店的交易清单,对频繁项集和关联规则的概念进行进一步分析。

       机器学习实践之使用Apriori算法进行关联分析

      通过上图,结合频繁项集的概念,我们知道{豆奶,尿布,葡萄酒}是频繁项集的一个例子,因为频繁项集是指经常一块出现的物品的集合。当然,通过下面的数据集也可以找到诸如尿布-->葡萄酒之间的关联规则。这意味着顾客购买了尿布也很可能会购买葡萄酒。使用频繁项集和关联规则可以使商店更好地理解顾客的购物行为。

      当我们面对大量数据进行频繁项集或关联规则归类时,可能会面临些疑问:怎么样才算有趣?这个有趣的定义谁来决定?当寻找频繁项集时,频繁(Frequent)的定义是什么?这里我们从支持度和可信度的角度来解答。

       支持度(Support)是指数据集中包含该项集中的记录所占的比例。从11-1图中,我们可以知道{豆奶}的支持度是4/5{豆奶,尿布}的支持度是3/5,因为5条记录中有3条包含{豆奶,尿布}。支持度是针对项集而言的,所以可以定义一个最小支持度,只保留满足最小支持度的项集。

       可信度或置信度(confidence)是针对一条诸如{尿布}-→{葡萄酒}的关联规则而定义的。这条规则的可信度被定义为“支持度{尿布,葡萄酒}/支持度{尿布}”。从图11-1中可知,由于{尿布,葡萄酒}的支持度是3/5,{尿布}的支持度是4/5,所以“尿布-->葡萄酒”的可信度是3/4,即0.75。这就说明,对于包含“尿布”的所有记录中,我们的规则对于其中的75%的记录都是有效的。

         支持度和可信度是用来量化关联分析是否成功的方法。倘若需要找到支持度大于0.8的所有项集,如何进行?一种传统的方法是生成一个物品的所有可能组合清单,然后对每一种组合统计出其出现的频繁度,但当商品梳理庞大时,效率极其低下,那么,有一中叫做APriori算法原理,可以减少关联规则学习时所需要的计算量。

3Apriori算法的一般流程

  • 收集数据: 使用任意方法。
  • 准备数据: 任何数据类型都可以,因为这里指保存集合。
  • 分析数据: 使用任何方法。
  • 训练算法: 使用Apriori算法来找到频繁项集。
  • 测试算法: 不需要测试过程。
  • 使用算法: 用于发现频繁项集以及物品之间的关联规则。

4Apriori的相关特性

  • 优点: 易编码实现。
  • 缺点: 在大数据集上可能很慢。
  • 适用数据类型:数值型或者标称型数据。

二、Apriori算法原理

       假设在一家经营商品种类不多的商店中,店主对于一起被购买的商品组合很感兴趣。这里有四种商品:商品0、商品1、商品2、商品3。那么所有可能被一起购买的商品组合总计有哪些?这些商品组合可能只包含一种商品,比如商品1,也可能包含两种、三种或者所有四种的组合。当然,这里我们并不关心顾客购买了3件商品0或者10件商品1的情况,而是更关注顾客购买一种或多种商品的组合。下图11-2给出了物品组合的所有可能。

     机器学习实践之使用Apriori算法进行关联分析

        图中物品编号代替物品本身。目标已经很清楚就是找到一起购买的物品组合。前面的方法是通过集合的支持度来度量其出现的频率,具体计算过程如下:

一个集合的支持度是指有多少比例的交易记录包含该集合。如何对一个给定集合,例如{0,3},来计算其支持度?遍历每一条记录并查找包含03,如果记录确实同时包含03,则增加总计数值。在扫描完所有数据之后,使用统计得到的总数除以总的交易记录数即可得到其对应支持度。这里还只是针对集合{0,3}的支持度计算,如果要对每种可能集合的支持度计算,需要重复上面过程很多次。在图11-2中,即使只是针对只有4种物品的集合,也需要遍历15次(2^N-1=2^4-1=15),显然随着物品数目的增加遍历次数也在急剧增加。

        为了降低计算的时间,相关人员发现了一种叫做Apriori算法原理。Aprirori原理可以帮助我们减少可能感兴趣的项集。Apriori原理是讲如果某个项集是频繁的,则它的所有项集也是频繁的。以图11-2为例,如果{{1,2}是频繁的,那么{1}{2}一定也是频繁的。反之,如果一个项集是非频繁的,则它的所有超集也是非频繁的,如图11-3所示。

              机器学习实践之使用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}就不必再计算对应支持度,因为它们已经不符合我们是要求。所以,使用Apriori算法原理可以避免项集数目指数级增加,从而在合理的时间内找到频繁项集。

三、使用Apriori算法发现频繁项集

          前面提到,关联分析的目标有两个:发现频繁项集和发现关联规则。首先发现频繁项集,然后再找到关联规则。

         Apriori算法是发现频繁项集的一种方法。Apriori算法的两个输入参数分别是最小支持度和数据集。该算法首先会生成单个物品的项集列表。接着扫描交易记录查看哪些项集满足最小支持度的要求,过滤掉不满足最小支持度的集合。然后,对剩下的集合进行组合以生成包含两个元素的项集。接着,再重复扫描交易记录,过滤掉不满足最小支持度的集合。该过程重复进行直到过滤掉所有项集。

1、 生成候选项集

创建一个用于构建初始集合的函数,也会创建一个通过扫描数据集以寻找交易记录子集的函数,数据扫描伪代码如下:

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

对每个候选项集can

检查下can是否是tran的子集: 如果是,则增加can 的计数值

对每个候选项集can

如果其支持度不低于最小值,则保留该项集

返回所有频繁项集列表


辅助函数如下:

#加载数据集
def loadDataSet():
    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
#生成所有单个物品的项集列表
def createC1(dataSet):
    C1 = []
    for transaction in dataSet:
        for item in transaction:
       
            if not [item] in C1:
           
                C1.append([item])
    #对C1排序           
    C1.sort()
    #use frozen set so we can use it as a key in a dict
   list(map(frozenset,C1))
    return list(map(frozenset, C1))


def scanD(D, Ck, minSupport):
    ssCnt = {}
   
    for tid in D:
        for can in Ck:
            if can.issubset(tid):
                if not can in ssCnt: ssCnt[can]=1
                else: ssCnt[can] += 1
    numItems = float(len(D))
    retList = []
    supportData = {}
    
    for key in ssCnt:
        support = ssCnt[key]/numItems
        if support >= minSupport:
            
            retList.insert(0,key)
          
            supportData[key] = support
    return retList, supportData

执行

c =list(map(frozenset,c))
c

得到:

[frozenset({1}), frozenset({2}), frozenset({3})]

执行

d[c[0]] = 1
d[c[0]]

得到1

2Apriori算法完整版

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

当集合中项的数目大于0

构建一个k个项目组成的候选项集的列表

检查数据以确认每个项集都是频繁的

保留频繁项集并构建k+1项组成的候选项集的列表

实现过程如下:

#creates Ck
def aprioriGen(Lk, k): 
    retList = []
    lenLk = len(Lk)
    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: #if first k-2 elements are equal
                #set union
                retList.append(Lk[i] | Lk[j])
    return retList

def apriori(dataSet, minSupport = 0.5):
    #生成所有单个物品的项集列表
    C1 = createC1(dataSet)
    
    D = list(map(set, dataSet))
   
    L1, supportData = scanD(D, C1, minSupport)
    
    L = [L1]

    k = 2
    #迭代L,直到L[k-1]为空
    while (len(L[k-2]) > 0):
        Ck = aprioriGen(L[k-2], k)
        Lk, supK = scanD(D, Ck, minSupport)#scan DB to get Lk
        supportData.update(supK)
        L.append(Lk)
        k += 1
    return L, supportData    

执行

dataSet =loadDataSet()
dataSet

得到

[[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]

执行

C1 =createC1(dataSet)
C1

得到

[frozenset({1}),
 frozenset({2}),
 frozenset({3}),
 frozenset({4}),
 frozenset({5})]

执行

D = list(map(set,dataSet))
D

得到

[{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}]

执行

L1, suppData0 =scanD(D,C1,0.5)
L1

得到

[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]

执行

suppData0

得到

{frozenset({1}): 0.5,
 frozenset({3}): 0.75,
 frozenset({2}): 0.75,
 frozenset({5}): 0.75}

3、从频繁项集中挖掘关联规则

       上面介绍了用于寻找频繁项集的Apriori的算法,现在要解决的问题是如何找出关联规则。

       要找到关联规则,首先要从一个频繁项集开始。集合中的元素是不重复的,但我们想知道基于这些元素能否获得其他内容。某个元素或某个元素集合可能会推导出另外一个元素。在上面提到的商店的例子中,若有一个频繁项集{豆奶,莴苣},则就可能有一条关联规则“豆奶”-->“莴苣”。这也就是说,从统计上来讲,如果这个顾客购买了豆奶,那他同时会有很大的概率取购买莴苣。但是反过来不一定成立。也就是说,即使“豆奶”-->“莴苣”统计上显著,但“莴苣”-->“豆奶”统计不一定成立。

        前面已经讲了频繁项集的量化定义,即满足最小支持度要求。同样,对应关联规则而言,也有其对应的量化指标,即可信度。一条规则X-→Y的可信度定义为support(X|Y)/support(X)Python下,“|”表示集合的并操作,数学上集合并的符号是U。这里X|Y是指所有出现在集合X或集合Y中的元素。

前面已经计算出了所有频繁项集的支持度,接下来计算可信度。

         一条频繁项集可以产生多少条关联规则呢?

         下图11-4所示,给出的是项集{0,1,2,3}产生的所有关联规则。为了得到感兴趣的规则,先生成一个可能的规则列表,然后,测试每条规则的可信度。若可信度不满足最小要求,则去掉该条规则。

机器学习实践之使用Apriori算法进行关联分析

         与上面提到的频繁项集生成一样,可以为每个频繁项集生成多个关联规则。通过减少关联规则的数目且确保问题的可解性,可以大大减少计算工作量。如果某条规则不满足最小可信度的要求,则该条规则的所有子集也不会满足最小可信度的要求。以图11-4为例,假如规则0,1,2-→3不满足最小可信度要求,则可知任何左部为{0,1,2}子集的规则也不会满足最小可信度要求。如图11-4中阴影部分所示。即12 -> 03 , 02-> 13 , 01 -> 23 ,2-> 013, 1 -> 023, 0-> 123都不满足最小可信度要求

          可以从一个频繁项集开始,构建一个规则列表,其中规则右部只包含一个元素,然后对这些规则进行测试。接下来合并剩余所有规则来构建一个新的规则列表,其中规则右部包含两个元素,这种方法被称为分级法。

实现过程


#supportData is a dict coming from scanD
def generateRules(L, supportData, minConf=0.7):  
    bigRuleList = []
    #only get the sets with two or more items
   
    for i in range(1, len(L)):
        for freqSet in L[i]:
          
            H1 = [frozenset([item]) for item in freqSet]
         
            if (i > 1):
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
            
            else:
                calcConf(freqSet, H1, supportData, bigRuleList, minConf)
    return bigRuleList         

def calcConf(freqSet, H, supportData, brl, minConf=0.7):
    #create new list to return
    #存储满足最小可信度的规则的后件集合,以便之后再次合并时使用
    prunedH = [] 
    #对候选项集H进行迭代,选择出符合最小可信度的关联规则
    for conseq in H:

        conf = supportData[freqSet]/supportData[freqSet-conseq] #calc confidence
        print(freqSet - conseq,freqSet,supportData[freqSet-conseq],supportData[freqSet])
        if conf >= minConf: 
            print(freqSet-conseq,'-->',conseq,'conf:',conf)
            brl.append((freqSet-conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH

def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    #获取候选项集项数
    m = len(H[0])
    #try further merging
    if (len(freqSet) > (m + 1)): 
        #create Hm+1 new candidates
        
        Hmp1 = aprioriGen(H, m+1)
        #得出满足最小可信度的候选关联规则
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
        if (len(Hmp1) > 1):    #need at least two sets to merge
      
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

执行

dataSet =loadDataSet()
L, suppData =apriori(dataSet, minSupport = 0.5)
rulues =generateRules(L, suppData, minConf = 0.7)

得到

frozenset({3}) frozenset({2, 3}) 0.75 0.5
frozenset({2}) frozenset({2, 3}) 0.75 0.5
frozenset({5}) frozenset({3, 5}) 0.75 0.5
frozenset({3}) frozenset({3, 5}) 0.75 0.5
frozenset({5}) frozenset({2, 5}) 0.75 0.75
frozenset({5}) --> frozenset({2}) conf: 1.0
frozenset({2}) frozenset({2, 5}) 0.75 0.75
frozenset({2}) --> frozenset({5}) conf: 1.0
frozenset({3}) frozenset({1, 3}) 0.75 0.5
frozenset({1}) frozenset({1, 3}) 0.5 0.5
frozenset({1}) --> frozenset({3}) conf: 1.0
frozenset({5}) frozenset({2, 3, 5}) 0.75 0.5
frozenset({3}) frozenset({2, 3, 5}) 0.75 0.5
frozenset({2}) frozenset({2, 3, 5}) 0.75 0.5

执行rulues得到

[(frozenset({5}),frozenset({2}), 1.0),
 (frozenset({2}), frozenset({5}), 1.0),
 (frozenset({1}), frozenset({3}), 1.0)]


执行
rules = generateRules(L, suppData, minConf = 0.5)
得到
frozenset({3}) frozenset({2, 3}) 0.75 0.5
frozenset({3}) --> frozenset({2}) conf: 0.6666666666666666
frozenset({2}) frozenset({2, 3}) 0.75 0.5
frozenset({2}) --> frozenset({3}) conf: 0.6666666666666666
frozenset({5}) frozenset({3, 5}) 0.75 0.5
frozenset({5}) --> frozenset({3}) conf: 0.6666666666666666
frozenset({3}) frozenset({3, 5}) 0.75 0.5
frozenset({3}) --> frozenset({5}) conf: 0.6666666666666666
frozenset({5}) frozenset({2, 5}) 0.75 0.75
frozenset({5}) --> frozenset({2}) conf: 1.0
frozenset({2}) frozenset({2, 5}) 0.75 0.75
frozenset({2}) --> frozenset({5}) conf: 1.0
frozenset({3}) frozenset({1, 3}) 0.75 0.5
frozenset({3}) --> frozenset({1}) conf: 0.6666666666666666
frozenset({1}) frozenset({1, 3}) 0.5 0.5
frozenset({1}) --> frozenset({3}) conf: 1.0
frozenset({5}) frozenset({2, 3, 5}) 0.75 0.5
frozenset({5}) --> frozenset({2, 3}) conf: 0.6666666666666666
frozenset({3}) frozenset({2, 3, 5}) 0.75 0.5
frozenset({3}) --> frozenset({2, 5}) conf: 0.6666666666666666
frozenset({2}) frozenset({2, 3, 5}) 0.75 0.5
frozenset({2}) --> frozenset({3, 5}) conf: 0.6666666666666666
执行rulues
得到
[(frozenset({3}), frozenset({2}), 0.6666666666666666),
 (frozenset({2}), frozenset({3}), 0.6666666666666666),
 (frozenset({5}), frozenset({3}), 0.6666666666666666),
 (frozenset({3}), frozenset({5}), 0.6666666666666666),
 (frozenset({5}), frozenset({2}), 1.0),
 (frozenset({2}), frozenset({5}), 1.0),
 (frozenset({3}), frozenset({1}), 0.6666666666666666),
 (frozenset({1}), frozenset({3}), 1.0),
 (frozenset({5}), frozenset({2, 3}), 0.6666666666666666),
 (frozenset({3}), frozenset({2, 5}), 0.6666666666666666),
 (frozenset({2}), frozenset({3, 5}), 0.6666666666666666)]

四、发现毒蘑菇案例

1、项目背景

       有一个关于肋形蘑菇的23种特征的数据集,每一个特征都包含一个标称数据值。RobertoBayardo对蘑菇数据集进行了解析,将每个蘑菇样本转换成一个特征集合。其中,枚举了每个特征的所有可能值,

       若某个样本包含特征,则该特征对应的整数值被包含在数据集中。第一个特征表示有毒或可食。若样本有毒,则值为2;可食则值为1。下一个特征是蘑菇伞的形状,有6种可能值,分别用3-8整数来表示。

2、样本形式

机器学习实践之使用Apriori算法进行关联分析


3、模型实现

       为了找到蘑菇中存在的公共特征,可以运行Apriori算法来寻找包含特征值为2的频繁项集。

mushDataSet =[ line.split() for line in open('mushroom.dat').readlines()]

在数据集上运行Apriori算法

L , suppData =apriori(mushDataSet , minSupport = 0.3)

在结果中搜索包含有毒特征值2的频繁项集

for item in L[1]:

ifitem.intersection('2'):print(item)

得到结果

frozenset({'2', '28'})
frozenset({'53', '2'})
frozenset({'23', '2'})
frozenset({'34', '2'})
frozenset({'36', '2'})
frozenset({'59', '2'})
frozenset({'63', '2'})
frozenset({'2', '67'})
frozenset({'76', '2'})
frozenset({'85', '2'})
frozenset({'2', '86'})
frozenset({'2', '90'})
frozenset({'2', '93'})
frozenset({'2', '39'})

也可以对更大的项集进行重复上述过程

for item in L[3]:

ifitem.intersection('2'):print(item)

得到



frozenset({'2', '28', '34', '39'})
frozenset({'2', '28', '86', '34'})
frozenset({'2', '28', '34', '90'})
frozenset({'2', '28', '34', '63'})
frozenset({'2', '28', '34', '85'})
frozenset({'2', '28', '59', '39'})
frozenset({'2', '28', '59', '34'})
frozenset({'2', '28', '86', '59'})
frozenset({'2', '28', '59', '90'})
frozenset({'2', '28', '59', '63'})
frozenset({'2', '28', '59', '85'})
frozenset({'2', '28', '63', '39'})
frozenset({'2', '28', '86', '63'})
frozenset({'2', '28', '63', '85'})
frozenset({'2', '28', '85', '39'})
frozenset({'2', '28', '86', '85'})
frozenset({'2', '28', '85', '90'})
frozenset({'2', '28', '86', '90'})
frozenset({'2', '28', '86', '39'})
frozenset({'2', '28', '39', '90'})
frozenset({'2', '28', '34', '53'})
frozenset({'2', '34', '53', '39'})
frozenset({'2', '34', '53', '85'})
frozenset({'2', '86', '34', '53'})
frozenset({'2', '34', '53', '90'})
frozenset({'2', '86', '53', '85'})
frozenset({'2', '53', '85', '90'})
frozenset({'2', '53', '85', '39'})
frozenset({'2', '28', '53', '85'})
frozenset({'2', '86', '53', '90'})
frozenset({'2', '86', '53', '39'})
frozenset({'2', '53', '39', '90'})
frozenset({'2', '28', '86', '53'})
frozenset({'2', '28', '53', '90'})
frozenset({'2', '28', '53', '39'})
frozenset({'36', '2', '23', '85'})
frozenset({'36', '2', '86', '23'})
frozenset({'36', '2', '23', '93'})
frozenset({'36', '2', '23', '63'})
frozenset({'2', '23', '63', '85'})
frozenset({'2', '86', '23', '63'})
frozenset({'2', '86', '23', '85'})
frozenset({'2', '23', '85', '90'})
frozenset({'2', '23', '85', '93'})
frozenset({'2', '86', '23', '39'})
frozenset({'2', '86', '23', '90'})
frozenset({'2', '23', '39', '93'})
frozenset({'2', '86', '23', '93'})
frozenset({'2', '90', '23', '93'})
frozenset({'2', '34', '39', '23'})
frozenset({'36', '2', '34', '23'})
frozenset({'36', '2', '34', '85'})
frozenset({'36', '2', '86', '34'})
frozenset({'36', '2', '34', '90'})
frozenset({'36', '2', '34', '93'})
frozenset({'2', '34', '63', '23'})
frozenset({'36', '2', '34', '63'})
frozenset({'2', '34', '63', '85'})
frozenset({'2', '86', '34', '63'})
frozenset({'2', '34', '63', '90'})
frozenset({'2', '34', '63', '93'})
frozenset({'2', '67', '34', '39'})
frozenset({'2', '34', '76', '85'})
frozenset({'2', '86', '34', '76'})
frozenset({'2', '34', '85', '23'})
frozenset({'2', '67', '34', '85'})
frozenset({'2', '86', '34', '85'})
frozenset({'2', '34', '85', '90'})
frozenset({'2', '34', '85', '93'})
frozenset({'2', '86', '34', '39'})
frozenset({'2', '86', '34', '23'})
frozenset({'67', '2', '86', '34'})
frozenset({'2', '34', '39', '90'})
frozenset({'2', '34', '23', '90'})
frozenset({'2', '86', '34', '90'})
frozenset({'2', '34', '39', '93'})
frozenset({'2', '34', '23', '93'})
frozenset({'2', '86', '34', '93'})
frozenset({'2', '90', '34', '93'})
frozenset({'36', '2', '86', '39'})
frozenset({'36', '2', '39', '90'})
frozenset({'36', '2', '86', '90'})
frozenset({'36', '2', '39', '93'})
frozenset({'36', '2', '86', '93'})
frozenset({'36', '2', '90', '93'})
frozenset({'2', '59', '39', '23'})
frozenset({'2', '59', '39', '34'})
frozenset({'2', '59', '23', '34'})
frozenset({'36', '2', '59', '23'})
frozenset({'36', '2', '59', '34'})
frozenset({'36', '2', '59', '85'})
frozenset({'36', '2', '86', '59'})
frozenset({'36', '2', '59', '90'})
frozenset({'36', '2', '59', '93'})
frozenset({'2', '59', '63', '23'})
frozenset({'2', '59', '63', '34'})
frozenset({'36', '2', '59', '63'})
frozenset({'2', '59', '63', '85'})
frozenset({'2', '86', '59', '63'})
frozenset({'2', '59', '63', '90'})
frozenset({'2', '59', '63', '93'})
frozenset({'2', '59', '85', '23'})
frozenset({'2', '59', '85', '34'})
frozenset({'2', '86', '59', '85'})
frozenset({'2', '59', '85', '90'})
frozenset({'2', '59', '85', '93'})
frozenset({'2', '86', '59', '39'})
frozenset({'2', '86', '59', '23'})
frozenset({'2', '86', '59', '34'})
frozenset({'2', '59', '39', '90'})
frozenset({'2', '59', '23', '90'})
frozenset({'2', '59', '34', '90'})
frozenset({'2', '86', '59', '90'})
frozenset({'2', '59', '39', '93'})
frozenset({'2', '59', '23', '93'})
frozenset({'2', '59', '34', '93'})
frozenset({'2', '86', '59', '93'})
frozenset({'2', '90', '59', '93'})
frozenset({'36', '2', '63', '85'})
frozenset({'36', '2', '86', '63'})
frozenset({'36', '2', '63', '90'})
frozenset({'36', '2', '63', '93'})
frozenset({'2', '86', '63', '85'})
frozenset({'2', '63', '85', '90'})
frozenset({'2', '63', '85', '93'})
frozenset({'2', '86', '63', '39'})
frozenset({'2', '63', '39', '90'})
frozenset({'2', '86', '63', '90'})
frozenset({'2', '63', '39', '93'})
frozenset({'2', '86', '63', '93'})
frozenset({'2', '90', '63', '93'})
frozenset({'2', '86', '76', '85'})
frozenset({'2', '86', '76', '39'})
frozenset({'36', '2', '85', '39'})
frozenset({'2', '67', '85', '39'})
frozenset({'2', '86', '85', '39'})
frozenset({'36', '2', '86', '85'})
frozenset({'67', '2', '86', '85'})
frozenset({'2', '85', '39', '90'})
frozenset({'36', '2', '85', '90'})
frozenset({'2', '86', '85', '90'})
frozenset({'2', '85', '39', '93'})
frozenset({'36', '2', '85', '93'})
frozenset({'2', '86', '85', '93'})
frozenset({'2', '90', '85', '93'})
frozenset({'67', '2', '86', '39'})
frozenset({'2', '90', '86', '93'})
frozenset({'2', '86', '39', '90'})
frozenset({'2', '86', '39', '93'})
frozenset({'2', '90', '39', '93'})
frozenset({'36', '2', '23', '39'})
frozenset({'2', '23', '63', '39'})
frozenset({'2', '23', '85', '39'})
frozenset({'36', '2', '34', '39'})
frozenset({'2', '34', '63', '39'})
frozenset({'2', '34', '76', '39'})
frozenset({'2', '34', '85', '39'})
frozenset({'36', '2', '59', '39'})
frozenset({'2', '59', '63', '39'})
frozenset({'2', '59', '85', '39'})
frozenset({'36', '2', '63', '39'})
frozenset({'2', '63', '85', '39'})
frozenset({'2', '76', '85', '39'})

   五、小结

        关联分析是用于发现大数据集中元素间有趣关系的一种工具集,可以采用两种方式来量化这些有趣的关系。第一种方式是使用频繁项集,它会给出经常在一起出现的元素项。第二种方式是关联规则,每条关联规则意味着元素项之间的“如果...那么...”关系。

       发现元素项间不同的组合是十分耗时的工作任务,这就需要占用大量的计算资源,所以采用更智能的方法在合理的时间范围内找到频繁项集为其解决之道。而Apriori算法正是实现此目标的一种方法,它可以使用自身原理减少在数据库上进行检查的集合数目。Apriori原理是:如果一个元素项是不频繁的,则所有包含该元素的超集也是不频繁的。Apriori算法从单元素项集开始,通过组合满足最小支持度要求的项集形式来形成更大的集合。支持度用来度量一个集合在原始数据中出现的频率。

      每次增加频繁项集的大小,Apriori算法都会重新扫描整个数据集。当数据集很大时,就会显著降低发现频繁项集的速度。