机器学习实战第十一章 - 使用Apriori算法进行关联分析

一,关联分析(或关联规则学习)

关联分析是一种在大规模数据集中寻找有趣关系的任务。这些关系主要有两种形式:

  • 频繁项集:经常出现在一块的物品的集合。
  • 关联规则:暗示两种物品之间可能存在很强的关系。

量化关联分析是否成功的评价准则也有两个:

  • 支持度(support):支持度是针对频繁项集来定义的,一个项集的支持度被定义为数据集中包含该项集的记录所占的比例。
  • 置信度(confidence):置信度是针对关联规则来定义的。例如{尿布}->{啤酒}这条关联规则的置信度为:support({尿布,啤酒})/support({尿布})。

二,Apriori原理

对于包含N种物品的数据集共有 2N1 2 N − 1 种项集组合。
例如4个物品的项集组合如下:
机器学习实战第十一章 - 使用Apriori算法进行关联分析_第1张图片

如果暴力寻找频繁项集会及其的耗时,为了加快寻找的速度,需要用到Apriori原理。

Apriori原理:如果某个项集是频繁的,那么它的所有子集也是频繁的。虽然直观上看并没有什么帮助,但是如果反过来看就有用了。也就是说也就是说如果一个项集是非频繁集,那么它的所有超集也是非频繁的。如下图所示:
机器学习实战第十一章 - 使用Apriori算法进行关联分析_第2张图片

使用该规则就可以避免项集数目的指数增长,从而在合理时间内计算出频繁项集。

三,使用Apriori算法来发现频繁集

关联分析的目标包括两个:发现频繁项集和发现关联目标。首先需要找到频繁项集,然后才能获得关联规则。
Apriori算法只需要两个参数:数据集和最小支持度。

1,生成候选项集

其中主要的一个辅助函数就是扫描数据集过滤掉那些支持度过低的项集。scanD()伪代码如下:

对数据集中的每一条记录trans
对每个候选集can:
    检查can是否是tran的子集:
        如果是,则增加can的计数。
对每个候选项集:
    如果其支持度不低于最小值,则保留该项集。
返回所有频繁项集列表

Python代码如下:

def loadDataSet():
    return [[1,3,4,],[2,3,5],[1,2,3,5],[2,5]]
def createC1(dataSet):
    C1 = []
    for trans in dataSet:
        for item in trans:
            if [item] not in C1:
                    C1.append([item])
    C1.sort()
    return [frozenset(t) for t in C1]
def scanD(D,Ck,minSupport):
    ssCnt = {}
    for tid in D:
        for can in Ck:
            if can.issubset(tid):
                if can not 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.append(key)
        supportData[key] = support
    return retList,supportData

2,组织完整的Apriori算法

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

当集合中项的个数大于0时
    构建一个k个项组成的候选项集的列表
    检查数据以确定每个项集都是频繁的
    保留频繁项集并构建k+1项组成的候选项集的列表

Python代码如下:

def aprioriGen(Lk,k):  #create Ck
    retList = []
    lenLk = len(Lk)
    for i in range(lenLk):
        for j in range(i+1,lenLk):
            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
def apriori(dataSet,minSupport=0.5):
    D = list(map(set,dataSet))
    C1 = createC1(dataSet)
    L1,supportData = scanD(D,C1,minSupport)
    L = [L1]
    k = 2
    while len(L[k-2])>0:
        Ck = aprioriGen(L[k-2],k)
        Lk,supK = scanD(D,Ck,minSupport)
        supportData.update(supK)
        L.append(Lk)
        k += 1
    return L,supportData

四,从频繁项集中挖掘关联规则

1,从一个频繁项集中产生关联规则

我们先生成一个可能的关联规则列表,然后测试每条规则的可信度,如果可信度不低于最小要求,就去掉该规则。
例如项集{0,1,2,3}产生的所有关联规则如下:
机器学习实战第十一章 - 使用Apriori算法进行关联分析_第3张图片

怎样来减少需要测试的规则数目的?
利用这一性质:如果某条规则不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度的要求。如上图阴影部分所示:012->3不满足,则右件包含3的规则都不满足要求。

从频繁项集中挖掘关联规则主要思想如下:

  1. 首先从一个频繁项集开始,接着创建一个规则列表,其中规则右部只包含一个元素,然后对这些规则进行测试。
  2. 接下来合并所有剩余规则来创建一个新的规则列表,其中规则右部包含两个元素。
  3. 循环下去。

这种方法也被成为分级法。

2,Python代码实现

def generateRules(L, supportData, minConf=0.7):
    bigRuleList = []
    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):
    prunedH = []
    for conseq in H:
        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
def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    m = len(H[0])
    if (len(freqSet) > (m + 1)):
        Hmp1 = aprioriGen(H, m + 1)
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
        if (len(Hmp1) > 1):
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

主要难度在rulesFromConseq()。

你可能感兴趣的:(机器学习)