Apriori关联分析与实操

49 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

基础知识

在去杂货店买东西的过程,实际包含了许多机器学习的当前及未来应用,这包括物品的 展示方式、购物之后优惠券的提供以及用户忠诚度计划,等等。它们都离不开对大量数据的 分析。商店希望从顾客身上获得尽可能多的利润,所以他们必然会利用各种技术来达到这一 目的。 通过查看哪些商品经常在一起购买,可以帮助商店了解用户的购买行为。这种从数据海洋中 抽取的知识可以用于商品定价、市场促销、存货管理等环节。从大规模数据集中寻找物品间的隐 含关系被称作关联分析(association analysis)或者关联规则学习(association rule learning)。这 里的主要问题在于,寻找物品的不同组合是一项十分耗时的任务,所需的计算代价很高,蛮力搜 索方法并不能解决这个问题,所以需要用更智能的方法在合理的时间范围内找到频繁项集。本章 将介绍如何使用Aprior算法来解决上述问题。

总的来说,我们总结如下: 关联性分析:从大规模数据集中寻找物品间的隐含关系。 关系包括:频繁项集或者关联规则。 频繁项集:是经常出现在一起的物品集合。 关联规则:暗示两种物品中间可能存在很强的关系。

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

在这里插入图片描述

Apriori原理

在这里插入图片描述 在这里插入图片描述 这里引入一个很有趣的例子:

尿布与啤酒? 
关联分析中最有名的例子是“尿布与啤酒”。据报道,美国中西部的一家连锁店发现,男
人们会在周四购买尿布和啤酒。这样商店实际上可以将尿布与啤酒放在一块,并确保在周四全
价销售从而获利。当然,这家商店并没有这么做*。

Apriori算法的一般过程 (1) 收集数据:使用任意方法。 (2) 准备数据:任何数据类型都可以,因为我们只保存集合。 (3) 分析数据:使用任意方法。 (4) 训练算法:使用Apriori算法来找到频繁项集。 (5) 测试算法:不需要测试过程。 (6) 使用算法:用于发现频繁项集以及物品之间的关联规则。

算法实现

在这里插入图片描述 在这里插入图片描述 ==Apriori算法中的辅助函数== 在这里插入图片描述

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])
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.insert(0,key)
        supportData[key] = support
    return retList, supportData

==Apriori算法 ==

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

==关联规则生产的函数==

def generateRules(L, supportData, minConf=0.7):  #supportData is a dict coming from scanD
    bigRuleList = []
    for i in range(1, len(L)):#only get the sets with two or more items
        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 = [] #create new list to return
    for conseq in H:
        conf = supportData[freqSet]/supportData[freqSet-conseq] #calc confidence
        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)): #try further merging
        Hmp1 = aprioriGen(H, m+1)#create Hm+1 new candidates
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
        if (len(Hmp1) > 1):    #need at least two sets to merge
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)