河北工业大学数据挖掘实验三 应用 Apriori 算法挖掘频繁项集

一、实验目的

(1)熟悉Apriori 频繁项集挖掘算法。
(2)根据管理层的需求,确定数据挖掘的任务,明确数据挖掘的功能,也就是明确要挖掘什么。
(3)由确定的数据挖掘任务,从实验一处理后的结果中,采用切块或切片等联机分析处理技术,选择出挖掘任务相关数据。
(4)编写 Apriori 算法的程序,对任务相关数据运行 Apriori算法,挖掘出所有的频繁项集。
(5)写出实验报告。

二、实验原理

1、Apriori 算法

Apriori 使用一种称作逐层搜索的迭代方法,k 项集用于探索(k+1)项集。首先,通过扫描数据库,累计每个项的计数,并收集满足最小支持度的项,找出频繁 1 项集的集合。该集合记作 L1。然后,L1 用于找频繁 2 项集的集合L2,L2 用于找 L3,如此下去,直到不能再找到频繁 k 项集。找每个 Lk 需要一次数据库全扫描。

2、提高频繁项集逐层产生的效率

Apriori 性质:频繁项集的所有非空子集也必须是频繁的。

三、实验内容和步骤

1、实验内容

在给定的数据中提取统一购物篮购买的商品信息,由这些数据构成事务数据
库D,挖掘其中的频繁项集 L。挖掘频繁项集的算法描述如下:
Apriori 算法:使用逐层迭代找出频繁项集
输入:事务数据库 D;最小支持度阈值。输出:D 中的频繁项集 L。

  1. 挖掘频繁 1-项集
  2. 调用 apriori_gen 方法生成候选频繁
  3. 扫描事务数据库 D ,统计候选频繁 k-项集的计数,满足最小支持度的 k-项集即为频繁k-项集
  4. 合并频繁 k-项集(k>0)
    算法在根据频繁 k-1 项集生成频繁 K 项集过程中要计算频繁 K 项集中每个元素的支持度,并计算 K 项集中每个 k-1 项子集是否在 Fk-1 中,上述两条任何一条不满足,则删去这个 K 项集中的元素。

2、实验步骤

1、打开试验用数据,读取出同一流水号的商品ID并取前5位,生成以行为单位生成事务数据集 transitions;
2、 生成频繁一项集
3、候选集产生算法
4、判断候选集的元素

3、程序框图

在这里插入图片描述

4、实验样本

实验一处理后的data.csv

5、实验代码

#!/usr/bin/env python  
# -*- coding: utf-8 -*-
#
# Copyright (C) 2021 #
# @Time    : 2022/5/30 21:29
# @Author  : Yang Haoyuan
# @Email   : 2723701951@qq.com
# @File    : Exp3.pyDa
# @Software: PyCharm
from numpy import *
import pandas as pd
from apyori import apriori
import argparse

parser = argparse.ArgumentParser(description='Exp3')
parser.add_argument('--Dataset', type=str, choices=["1019", "1020", "1021"])
parser.add_argument('--minSup', type=float)

parser.set_defaults(augment=True)
args = parser.parse_args()
print(args)


# 读取数据集
def loadDataSet():
    data = pd.read_csv("data.csv")
    data_19 = data[:7693]
    data_20 = data[7693:17589]
    data_21 = data[17589:]

    # 按照流水号分组,把同一个篮子里的商品分到一组
    data_df_list = [data_19.groupby(['SerNo'])['GoodID'], data_20.groupby(['SerNo'])['GoodID'],
                    data_21.groupby(['SerNo'])['GoodID']]
    list_ = []
    list_re = []

    for df in data_df_list:
        df_ = pd.DataFrame(df)
        for i in range(df_.shape[0]):
            tmp = []
            # 将每个篮子里的商品编号添加到同一事务项
            l = df_.loc[i][1].values.tolist()
            for gid in l:
                tmp.append(str(gid)[:5])
            # 添加至项集
            list_.append(tmp)
        list_re.append(list_)

    return list_re[0], list_re[1], list_re[2]


# 创造1-项集C1
def createC1(dataSet):
    C1 = []
    # 遍历dataset中每一个事务中的每一个item,加入C1
    for transaction in dataSet:
        for item in transaction:
            if not [item] in C1:
                C1.append([item])
    # 将C1的每一项映射为冻结集合
    # 为什么使用冻结集合?
    # 因为在集合的关系中,有集合的中的元素是另一个集合的情况,但是普通集合(set)本身是可变的,
    # 那么它的实例就不能放在另一个集合中(set中的元素必须是不可变类型)。
    # 所以,frozenset提供了不可变的集合的功能,当集合不可变时,它就满足了作为集合中的元素的要求,就可以放在另一个集合中了。
    # python要求字典的键是可哈希的,set是可变的,不可哈希,frozenset是不可变的,可哈希
    return list(map(frozenset, C1))


# 计算支持度,筛选满足要求的k-项集成为频繁项集Lk
def scanD(dataSet, Ck, minSupport):
    ssCnt = {}
    # 遍历计算Ck中的每一项在Dataset中的出现次数
    for tid in dataSet:
        for can in Ck:
            if can.issubset(tid):
                if not can in ssCnt:
                    ssCnt[can] = 1
                else:
                    ssCnt[can] += 1
    # 数据集中总共的事务数量
    numItems = float(len(dataSet))
    retList = []
    supportData = {}
    # 计算Ck中每一项的支持度
    for key in ssCnt:
        support = ssCnt[key]
        if support >= minSupport:
            # 大于最小支持度加入结果集合
            retList.append(key)
            # 记录支持度数据
            supportData[key] = support
    return retList, supportData


# 从Lk频繁项集中产生Ck+1
def aprioriGen(Lk, k):
    lenLk = len(Lk)
    # 临时字典,存储
    temp = []
    for i in range(lenLk):
        for j in range(i + 1, lenLk):
            # 两两合并,执行了 lenLk!次
            L1 = Lk[i] | Lk[j]
            if len(L1) == k:
                if L1 not in temp:
                    # 如果合并后的子项元素有k个,满足要求
                    temp.append(L1)

    return temp


def apriori(dataSet, minSupport=0.5):
    # 构建C1
    C1 = createC1(dataSet)
    print("C1: ", C1)
    print('\n')

    D = list(map(set, dataSet))

    # 构建L1,获取置信度
    L1, supportData = scanD(D, C1, minSupport)
    # print("Support Data for C1: ", supportData)
    # print('\n')
    print("L1: ", L1)
    print('\n')

    Lk_List = [L1]
    k = 2
    while len(Lk_List[k - 2]) > 0:
        print()
        # 构建Ck
        Ck = aprioriGen(Lk_List[k - 2], k)
        # Ck为空,不能合并,迭代终止
        if not Ck:
            print("项集为空")
            print('\n')
            break
        print("C" + str(k) + ": ", Ck)
        print('\n')
        # 构建LK,获取Ck各项的支持度
        Lk, supK = scanD(D, Ck, minSupport)
        supportData.update(supK)
        # 新的Lk加入Lk_List
        Lk_List.append(Lk)
        # print("Support Data for C" + str(k) + ": ", supK)
        # print('\n')

        # 频繁项集为空,终止迭代
        if not Lk:
            print("C" + str(k) + "频繁项集为空")
            print('\n')
            break
        print("L" + str(k) + ": ", Lk)
        print('\n')
        k += 1

    return Lk_List, supportData


if __name__ == "__main__":
    dataSet19, dataSet20, dataSet21 = loadDataSet()
    # 根据参数对不同数据集进行挖掘
    if args.Dataset == "1019":
        L, suppData = apriori(dataSet19, args.minSup)
        print(L)
        # print(suppData)
    if args.Dataset == "1020":
        L, suppData = apriori(dataSet20, args.minSup)
        # print(L)
        print(suppData)
    if args.Dataset == "1021":
        L, suppData = apriori(dataSet21, args.minSup)
        print(L)
        # print(suppData)

四、实验结果

挖掘1020数据集中的频繁模式,最小支持度30,结果如下图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、实验分析

本次实验主要是Apriori算法的实现。
算法实现的关键在与数据结构的选取。Python中有“Set”类型,但是因为在集合的关系中,有集合的中的元素是另一个集合的情况,但是普通集合(set)本身是可变的,那么它的实例就不能放在另一个集合中(set中的元素必须是不可变类型)。所以采用frozenset,也就是“冻结集合”存放每一个事务项。
Apriori算法的基本思想是:首先找出所有的频集,这些项集出现的频繁性至少和预定义的最小支持度一样。然后由频集产生强关联规则,这些规则必须满足最小支持度和最小可信度。然后使用第1步找到的频集产生期望的规则,产生只包含集合的项的所有规则,其中每一条规则的右部只有一项,这里采用的是中规则的定义。一旦这些规则被生成,那么只有那些大于用户给定的最小可信度的规则才被留下来。为了生成所有频集,使用了递归的方法。这导致算法的挖掘速度较慢。

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ace2NoU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值