关联分析——频繁项集的产生之Apriori算法

Apriori算法是一种经典的数据挖掘算法,用于从交易数据中发现频繁项集。该算法通过提取1-项集,生成候选k-项集并进行频繁项集的迭代查找,基于支持度进行剪枝。文章详细阐述了Apriori的工作流程,并给出了Python实现的概要。
部署运行你感兴趣的模型镜像

频繁项集的产生—Apriori算法

Apriori算法用于从数据集中提取频繁项集,以购物篮事务为例说明其过程:
在这里插入图片描述
提取频繁项集的过程如下:
在这里插入图片描述
Apriori算法的伪码如下:
在这里插入图片描述
在这里插入图片描述

Apriori算法的Python实现

给出数据集:

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

提取1-项集

# 生成候选1-项集
def createC1(data):
    c1 = []
    for task in data:
        for item in task:
            if [item] not in c1:
                c1.append([item])
    # 排序是因为之后生产频繁k-项集是采用F(k-1)*F(k-1)方法
    c1.sort()
    # frozenset()返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。
    return list(map(frozenset, c1))
# 候选1-项集的结果如下
c1 = createC1(data)
c1
[frozenset({1}),
 frozenset({2}),
 frozenset({3}),
 frozenset({4}),
 frozenset({5})]

提取频繁k-项集

基于支持度的剪枝原理可用下图表示:

其原理在于如果一个项集是频繁的,则它的所有子集一定也是频繁的。根据逆否命题可得:如果一个项集的某个子集是非频繁的,则该项集一定是非频繁的。

# 提取频繁k-项集
def scanData(data, C_k, minSupport):
    # 记录候选k-项集中项的支持度计数
    ssCnt = {}
    for task in data:
        for can in C_k:
            if can.issubset(task):
                ssCnt[can] = ssCnt.get(can, 0) + 1
    # 根据最小支持度计数提取频繁项集
    retlist = []
    F_k = {}
    for key in ssCnt:
        support = ssCnt[key] / len(data)
        if support >= minSupport:
            retlist.insert(0, key)
            F_k[key] = support
    
    return retlist, F_k

# F1_l记录频繁1-项集
# F_1记录频繁1-项集中各项集的支持度
F1_l, F_1 = scanData(data, c1, 0.5)
print(F1_l)
[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]
print(F_1)
{frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({2}): 0.75, frozenset({5}): 0.75}

对应伪码的第2步和第12步。

生成候选k-项集

生成候选k-项集采用F(k-1) * F(k-1)方法,其原理如下:
在这里插入图片描述

# 采用F(k-1)*F(k-1)法:通过频繁项集列表F_k-1生成候选项集列表C_k
def aprioriGen(F_l, k):
    C_l = []
    for i in range(len(F_l)-1):
        for j in range(i+1, len(F_l)):
            # 对于频繁k-1项集合并规则为:前k-2项相同第k-1项不同
            # 提取频繁k-1项集的前k-2项
            l1 = list(F_l[i])[:k-2]
            l2 = list(F_l[j])[:k-2]
            l1.sort()
            l2.sort()
            if l1 == l2:
                C_l.append(F_l[i] | F_l[j])
    
    return C_l

C2_l = aprioriGen(F1_l, 2)
C2_l
[frozenset({2, 5}),
 frozenset({3, 5}),
 frozenset({1, 5}),
 frozenset({2, 3}),
 frozenset({1, 2}),
 frozenset({1, 3})]

对应伪码的第5步。

Apriori算法

def apriori(data, minsupport):
    # 生成候选1-项集
    C1 = createC1(data)
    # 提取频繁1-项集
    F1_l, F1 = scanData(data, C1, minsupport)
    # 返回频繁项集和频繁项集对应的支持度
    L = [F1_l] 
    F = F1
    # 逐层迭代,直到不再生成新的频繁项集
    k = 2
    while len(L[k-2]) > 0: 
        # 根据频繁k-1项集生成候选k-项集
        Ck_l = aprioriGen(L[k-2], k)
        # 从候选K-项集中提取频繁k-项集
        Fk_l, Fk = scanData(data, Ck_l, minsupport)
        L.append(Fk_l)
        F.update(Fk)
        k += 1
    
    return L, F
L, F = apriori(data, 0.2)
# 频繁项集
print(L)
[[frozenset({5}), frozenset({2}), frozenset({4}), frozenset({3}), frozenset({1})], [frozenset({1, 2}), frozenset({1, 5}), frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3}), frozenset({1, 4}), frozenset({3, 4})], [frozenset({1, 3, 5}), frozenset({1, 2, 3}), frozenset({1, 2, 5}), frozenset({2, 3, 5}), frozenset({1, 3, 4})], [frozenset({1, 2, 3, 5})], []]
# 频繁项集何其对应的支持度
print(F)
{frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({4}): 0.25, frozenset({2}): 0.75, frozenset({5}): 0.75, frozenset({3, 4}): 0.25, frozenset({1, 4}): 0.25, 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({1, 3, 4}): 0.25, frozenset({2, 3, 5}): 0.5, frozenset({1, 2, 5}): 0.25, frozenset({1, 2, 3}): 0.25, frozenset({1, 3, 5}): 0.25, frozenset({1, 2, 3, 5}): 0.25}

封装

class Apriori:
    
    def __init__(self, minsupport):
        self.minsupport = minsupport
    
    def createC1(self, data):
        c1 = []
        for task in data:
            for item in task:
                if [item] not in c1:
                    c1.append([item])
            # 排序是因为之后生产频繁k-项集是采用F(k-1)*F(k-1)方法
            c1.sort()
        # frozenset()返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。
        return list(map(frozenset, c1))
    
    def scanData(self, data, C_k, minSupport):
        # 记录候选k-项集中项的支持度计数
        ssCnt = {}
        for task in data:
            for can in C_k:
                if can.issubset(task):
                    ssCnt[can] = ssCnt.get(can, 0) + 1
        # 根据最小支持度计数提取频繁项集
        retlist = []
        F_k = {}
        for key in ssCnt:
            support = ssCnt[key] / len(data)
            if support >= minSupport:
                retlist.insert(0, key)
                F_k[key] = support

        return retlist, F_k
    
    def aprioriGen(self, F_l, k):
        C_l = []
        for i in range(len(F_l)-1):
            for j in range(i+1, len(F_l)):
                # 对于频繁k-1项集合并规则为:前k-2项相同第k-1项不同
                # 提取频繁k-1项集的前k-2项
                l1 = list(F_l[i])[:k-2]
                l2 = list(F_l[j])[:k-2]
                l1.sort()
                l2.sort()
                if l1 == l2:
                    C_l.append(F_l[i] | F_l[j])

        return C_l
    
    def apriori(self, data):
        minsupport = self.minsupport
        # 生成候选1-项集
        C1 = self.createC1(data)
        # 提取频繁1-项集
        F1_l, F1 = self.scanData(data, C1, minsupport)
        # 返回频繁项集和频繁项集对应的支持度
        L = [F1_l] 
        F = F1
        # 逐层迭代,直到不再生成新的频繁项集
        k = 2
        while len(L[k-2]) > 0: 
            # 根据频繁k-1项集生成候选k-项集
            Ck_l = self.aprioriGen(L[k-2], k)
            # 从候选K-项集中提取频繁k-项集
            Fk_l, Fk = self.scanData(data, Ck_l, minsupport)
            L.append(Fk_l)
            F.update(Fk)
            k += 1

        return L, F

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值