Apriori寻找频繁项集——python3.x实现


        Apriori 算法使用了逐层搜索的迭代方法,即用 k-项集探索(k+1)-项集。为提高按层次搜索并产生相应频繁项集的处理效率,Apriori 算法利用了一个重要性质,该性质还能有效缩小频繁项集的搜索空间。

        Apriori 性质:一个频繁项集的所有非空子集也必须是频繁项集。即假如项集 A 不满足最小支持度阈值,即 A 不是频繁的,则如果将项集 B 添加到项集 A 中,那么新项集(AUB)也不可能是频繁的。

        Apriori 算法简单来说主要有以下几个步骤:
        1)通过单遍扫描数据集,确定每个项的支持度。一旦完成这一步,就可得到所有频繁 1-项集的集合 F1。
        2)使用上一次迭代发现的频繁(k-1)-项集,产生新的候选k-项集。
        3)为了对候选项集的支持度计数,再次扫描一遍数据库,使用子集函数确定包含在每一个交易 t 中的所有候选 k-项集。
        4)计算候选项集的支持度计数后,算法将删除支持度计数小于支持度阈值的所有候选项集。
        5)重复步骤(2)、(3)、(4),当没有新的频繁项集产生时,算法结束。Apriori 算法是个逐层算法,它使用“产生——测试”策略来发现频繁项集。在由(k-1)-项集产生 k-项集的过程中“新产生的 k-项集先要确定它的所有的(k-1)-项真子集都是频繁的,如果有一个不是频繁的,那么它可以从当前的候选项集中去掉。

代码如下:

import time


def load_data():
    f = open(r'retail.txt', encoding='utf-8')
    data = []
    for line in f:
        records = line.split()
        every_line = []
        for item in records:
            every_line.append(int(item))
        data.append(every_line)
    return data


def create_l1(data, min_sup):
    sscnt = {}
    for i in data:
        for j in i:
                if frozenset({j}) not in sscnt:
                    sscnt[frozenset({j})] = 1
                else:
                    sscnt[frozenset({j})] += 1
    num_items = float(len(data))
    l1 = []
    sup_data = {}
    for k in sscnt:
        support = sscnt[k] / num_items
        if support >= min_sup:
            l1.append(k)
            sup_data[k] = support
    return l1, sup_data


# 从候选K项集到频繁K项集(支持度计算)
def ck_to_lk(data, ck, min_sup):
    sscnt = {}
    for i in data:
        for j in ck:
            if j.issubset(i):  # 判断j是否i的子集,返回的足布尔型数据
                if j not in sscnt:
                    sscnt[j] = 1
                else:
                    sscnt[j] += 1
    num_items = float(len(data))
    lk = []  # 频繁项集
    sup_data = {}
    for k in sscnt:
        support = sscnt[k] / num_items
        if support >= min_sup:
            lk.append(k)
            sup_data[k] = support
    return lk, sup_data


# 剪枝
def lk_to_ckk(lk, k):
    ck = []
    len_lk = len(lk)
    for i in range(len_lk):
        for j in range(i+1, len_lk):
            l1 = list(lk[i])[:k - 2]
            l2 = list(lk[j])[:k - 2]
            l1.sort()
            l2.sort()
            if l1 == l2:
                a = lk[i] | lk[j]
                if len(a) == k:
                    ck.append(lk[i] | lk[j])
    return ck


def apriori(data, min_sup=0.05):
    l1, sup_data = create_l1(data, min_sup)
    l = [l1]
    k = 2
    while len(l[k-2]) > 0:
        ck = lk_to_ckk(l[k-2], k)
        lk, supk = ck_to_lk(data, ck, min_sup)
        sup_data.update(supk)
        l.append(lk)
        k += 1
    print(sup_data)
    print(len(sup_data))
    return l, sup_data


if __name__ == '__main__':
    start = time.perf_counter()

    dataSet = load_data()
    L, sup_data = apriori(dataSet)

    end = time.perf_counter()
    print('Running time: %s Seconds' % (end - start))

数据集如图:

 支持度=0.2时,运行结果:

 支持度=0.02时,运行结果:

支持度=0.01时,运行结果:

 

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值