Apriori算法寻找频繁集

0. 前言

上篇博客对Apriori算法的原理进行了总结,下面希望来实现以下这个算法。

1. Apriori算法寻找频繁集步骤

假定Apriori算法的输入参数是最小支持度(minSupport)和数据集。该算法首先会生成所有单个物品的项集列表,接着会扫描所有的记录,查看这些项集是否满足最小支持度的要求,不满足的会被消除掉;接着对满足的项集进行组合,生成包含2个元素的项集,再重新扫描数据集,消除掉不满足最小支持度的项集。重复上面的步骤,直至所有项集都被去掉。
可能文字的叙述太过生硬,下面用一个例子来说明。下面是数据集,此处设置最小支持度为0.5:

ID商品
1方便面,火腿肠
2方便面,尿布,啤酒,橙汁
3火腿肠 ,尿布,啤酒,可乐
4方便面,火腿肠,尿布,啤酒
5方便面,火腿肠,尿布,可乐

算法流程:
在这里插入图片描述
由于最小支持度设置为0.5,所以对于包含1个物品的集合中,{橙汁}和{可乐}支持度分别为1/5=0.2、2/5=0.4,不满足最小支持度,所以就被消除掉了。包含多个物品的集合也是同样的计算方法。

故上面最终得到的频繁集有:
{方便面},{火腿肠},{尿布},{啤酒};{方便面,火腿肠},{方便面、尿布},{火腿肠,尿布},{尿布,啤酒}。

2. 代码实现Apriori算法寻找频繁集

参照《机器学习实战》一书实现

  1. 创造数据集
def load_dataset():
    """构造数据集"""
    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
  1. 创建c1集合
def create_c1(dataSet):
    """创建包含一个元素的所有候选项集的集合"""
    c1 = []
    for tran in dataSet:
        for item in tran:
            if not [item] in c1:
                c1.append([item])
    c1.sort()
    return c1
  1. 计算候选数据集支持度
def scan_dataset(D, Ck, minSupport):
    """计算候选数据集CK在数据集D中的支持度,返回大于最小支持度的数据"""
    ssCnt = {}  # 存放所有候选集和频率
    for tid in D:
        for can in map(frozenset, 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
  1. 测试
dataSet = load_dataset()
print("数据集:\n", dataSet)
c1 = create_c1(dataSet)
print("包含一个元素候选项集:\n", c1)
L1, supportData = scan_dataset(dataSet, c1, 0.5)  # 最小支持度为0.5
print("频繁项集支持度:\n", supportData)
print("满足最小支持度的频繁项集:\n", L1)

输出结果:

数据集:
 [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
包含一个元素候选项集:
 [[1], [2], [3], [4], [5]]
频繁项集支持度:
 {frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({4}): 0.25, frozenset({2}): 0.75, frozenset({5}): 0.75}
满足最小支持度的频繁项集:
 [frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]

  1. Apriori算法
def aprioriGen(Lk, k):
    """计算可能的候选项集"""
    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):
    """找满足最小支持度的频繁项集"""
    c1 = create_c1(dataSet)
    D = list(map(set, dataSet))
    L1, supportData = scan_dataset(D, c1, minSupport)
    L = [L1]
    k = 2
    while (len(L[k-2])>0):
        Ck = aprioriGen(L[k - 2], k)
        Lk, supK = scan_dataset(D, Ck, minSupport)
        supportData.update(supK)
        if len(Lk) == 0:
            break
        L.append(Lk)
        k += 1
    return L, supportData
  1. 测试
dataSet = load_dataset()
print("数据集:\n", dataSet)
L, supportData = apriori(dataSet)
print("频繁项集支持度:\n", supportData)
print("满足最小支持度的频繁项集:\n", L)
print("L0下可能的候选项集:\n", aprioriGen(L[0], 2))

Lt, supportDatat = apriori(dataSet, minSupport=0.7)
print("满足最小支持度为70%的频繁项集:\n", Lt)

输出结果:

数据集:
 [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
频繁项集支持度:
 {frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({4}): 0.25, frozenset({2}): 0.75, frozenset({5}): 0.75, frozenset({1, 3}): 0.5, frozenset({2, 5}): 0.75, frozenset({3, 5}): 0.5, frozenset({2, 3}): 0.5, frozenset({1, 5}): 0.25, frozenset({1, 2}): 0.25, frozenset({2, 3, 5}): 0.5}
满足最小支持度的频繁项集:
 [[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})], [frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})], [frozenset({2, 3, 5})]]
L0下可能的候选项集:
 [frozenset({2, 5}), frozenset({3, 5}), frozenset({1, 5}), frozenset({2, 3}), frozenset({1, 2}), frozenset({1, 3})]
满足最小支持度为70%的频繁项集:
 [[frozenset({5}), frozenset({2}), frozenset({3})], [frozenset({2, 5})]]
  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值