【数据挖掘】Apriori算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hemk340200600/article/details/78202749

关联分析:在大数据中寻找有趣的关系,包括频繁项集或者关联规则频繁项集是指经常一起出现的物品的集合,关联关系暗示两种物品之间可能存在很强的关系。这种关联分析有什么用呢?根据常识,经常一起出现的可能有某种关系,比如商品A和商品B在同一个频繁项集里,那么可能说明购买商品A的人会选择购买商品B,或者反过来。那么商家就可以利用这个信息,将频繁项集的物品摆放在一起,以希望提高营业额。又或者网上购物时,可以根据频繁项集来给用户进行推荐,往往能收到很好的效果。

那么怎么确定频繁项集呢?我们需要依靠支持度置信度

支持度的定义是:数据集中包含该项集所占的比例。假如有[1,3,5],[1,2,3],[1,3,4],[2,3,4]这四个原始数据,可以看到4个数据中[1]出现了3次,那么[1]的支持度就是3/4。我们可以通过定义一个最小支持度,只保留满足最小支持度的项集。

置信度的定义是:在A出现的情况下,B出现在同一个项集的概率。即P(B|A)=P(AB)/P(A)。比如[1,3,5],[1,2,3],[1,3,4],[2,3,4]这四个数据,[2]的支持度为0.5,[2,4]的支持度为0.25,那么关联规则[2]→[4]的置信度为0.25/0.5=0.5。与最小支持度相对,也有最小置信度。如果一个关联规则大于最小置信度,则称为强关联规则。否则称为弱关联规则

 

Apriori规则频繁项集的所有非空子集也必须是频繁的。换句话说,如果一个项集的子集中包含非频繁项集,那这个项集我们就不用考虑了,因为他一定不是频繁项集。有n个元素的集合,如果穷举他的集合的话,时间复杂度将达到指数级。利用Apriori规则,我们可以将时间复杂度降低到可以接受的程度。

 

Apriori举例:

原始项集:[1,3,4],[2,3,5],[1,2,3,5],[2,5],最小支持度为0.5

第一次扫描:[1][2][3][5] ([4]因为支持度为0.25小于0.5被排除,根据Apriori规则,包含[4]的集合都不可能是频繁项集,因此之后的算法不用考虑[4])

候选集合:[1,2],[1,3],[1,5],[2,3],[2,5],[3,5]

第二次扫描:[2,3],[2,5],[1,3],[3,5](其余不符合最支持度)

候选集合:[2,3,5](为什么[1,3,5]不见了?因为[1,2],[1,5]都不是频繁项集,根据Apriori规则,他也不可能是频繁项集)

第三次扫描[2,3,5].

最终产生的频繁项集:[1],[2],[3],[5],[2,3],[2,5],[1,3],[3,5],[2,3,5]


python代码:

# -*- coding: utf-8 -*-
from numpy import *
import itertools
support_dic = {}
# 生成原始数据,用于测试
def loadDataSet():
    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
# 获取整个数据库中的一阶元素
# C1 = {1, 2, 3, 4, 5}
def createC1(dataSet):
    C1 = set([])
    for item in dataSet:
        C1 = C1.union(set(item))
    return [frozenset([i]) for i in C1]
# 输入数据库(dataset) 和 由第K-1层数据融合后得到的第K层数据集(Ck),
# 用最小支持度(minSupport)对 Ck 过滤,得到第k层剩下的数据集合(Lk)
def getLk(dataset, Ck, minSupport):
    global support_dic
    Lk = {}
    # 计算Ck中每个元素在数据库中出现次数
    for item in dataset:
        for Ci in Ck:
            if Ci.issubset(item):
                if not Ci in Lk:
                    Lk[Ci] = 1
                else:
                    Lk[Ci] += 1
    # 用最小支持度过滤
    Lk_return = []
    for Li in Lk:
        support_Li = Lk[Li] / float(len(dataSet))
        if support_Li >= minSupport:
            Lk_return.append(Li)
            support_dic[Li] = support_Li
    return Lk_return
# 将经过支持度过滤后的第K层数据集合(Lk)融合
# 得到第k+1层原始数据Ck1
'''连接步'''
def genLk1(Lk):
    Ck1 = []
    for i in range(len(Lk) - 1):
        for j in range(i + 1, len(Lk)):
            if sorted(list(Lk[i]))[0:-1] == sorted(list(Lk[j]))[0:-1]:
                Ck1.append(Lk[i] | Lk[j])
    return Ck1
# 遍历所有二阶及以上的频繁项集合
def genItem(freqSet):
    for i in range(1, len(freqSet)):
        for freItem in freqSet[i]:
            genRule(freItem)
# 输入一个频繁项,根据“置信度”生成规则
# 采用了递归,对规则树进行剪枝
def genRule(Item, minConf=0.5):
    if len(Item) >= 2:
        for element in itertools.combinations(list(Item), 1):
            if support_dic[Item] / float(support_dic[Item - frozenset(element)]) >= minConf:
                print(str([Item - frozenset(element)]) + "----->" + str(element))
                print(support_dic[Item] / float(support_dic[Item - frozenset(element)]))
                genRule(Item - frozenset(element))
# 输出结果
if __name__ == '__main__':
    dataSet = loadDataSet()
    result_list = []
    print(dataSet)
    Ck = createC1(dataSet)
    print(Ck)
    # 循环生成频繁项集合,直至产生空集
    while True:
        Lk = getLk(dataSet, Ck, 0.5)
        if not Lk:
            break
        result_list.append(Lk)
        Ck = genLk1(Lk)
        if not Ck:
            break
    # 输出频繁项及其“支持度”
    print(support_dic)
    # 输出规则
    genItem(result_list)


猜你喜欢

转载自blog.csdn.net/Hemk340200600/article/details/78202749