数据仓库与数据挖掘论文

《数据仓库与数据挖掘》课程论文

题目: 关联分析Apriori算法的研究和案例实现

专业: 计算机科学与技术
学号: XXXXXXXXX
姓名: XXX

2018-2019学年第二学期
目录

  1. 研究现状 1
    1.1 算法简介 1
    1.2 研究现状 1
  2. 算法思想 2
    2.1 相关概念 2
    2.2 基本思想 3
  3. 算法步骤 4
  4. 算法应用 6
    4.1 所应用的数据集介绍 6
    4.2 核心代码 7
    4.3 实现页面截图 10
    5.总结 12

1.研究现状
1.1算法简介
Apriori算法是经典的挖掘频繁项集和关联规则的数据挖掘算法。A priori在拉丁语中指"来自以前"。当定义问题时,通常会使用先验知识或者假设,这被称作"一个先验"(a priori)。Apriori算法的名字正是基于这样的事实:算法使用频繁项集性质的先验性质,即频繁项集的所有非空子集也一定是频繁的。Apriori算法使用一种称为逐层搜索的迭代方法,其中k项集用于探索(k+1)项集。首先,通过扫描数据库,累计每个项的计数,并收集满足最小支持度的项,找出频繁1项集的集合。该集合记为L1。然后,使用L1找出频繁2项集的集合L2,使用L2找出L3,如此下去,直到不能再找到频繁k项集。每找出一个Lk需要一次数据库的完整扫描。Apriori算法使用频繁项集的先验性质来压缩搜索空间。
1.2研究现状
Apriori是Agrawal等于1993年设计的一个基本算法,首先提出了挖掘顾客交易数据库中项集间的关联规则问题,其核心方法是基于频繁项集理论的递推方法。算法提出后以后,很多研究人员对关联规则挖掘算法进行了大量研究,特别是对关联规则挖掘算法进行了大量的研究和优化。如Savasere等人设计了一个基于划分的算法,Mannila提出的基于采样的方法等。
近几年,随着研究者对于关联规则挖掘的深入研究,关联规则挖掘研究有了许多扩展,包括:事务间关联规则挖掘、空间关联规则挖掘、负关联规则挖掘、序列模式挖掘及正关联规则挖掘;另外,对度量的研究也有所突破。自从Chen,Hart,Brin和Motwani等人提出了强关联规则的兴趣度问题以后,强关联规则兴趣度问题的研究得到了很高的重视。后来评估关联规则兴趣度相应的一些优化方法的出现,促进了目前度量方法的进一步改进和完善。同时,Motwani和Silverstein把这方面的研究和讨论推广到相关的算法中。除这个方面外,其他方面的研究也得到了发展,如多层关联规则挖掘、区间数据关联规则挖掘、删除冗余规则、度量的改进研究、关联规则的有效增量更新和并行分布规则挖掘等等,这些关联规则挖掘算法在实际数据挖掘系统中的到了很好的应用。
2.算法思想
2.1相关概念
(1)项(item): 项指的是具体的一件东西,比如在购物篮的例子中,你的购物篮里面的大米,被子,红酒等等商品都是项;
(2)项集(itemset): 顾名思义,项的集合,由一个或多个项组成的一个整体,我们把由kk个项组成的项集叫kk项集;
(3)事务(transaction):一个事务,可以看做是发生的一次事件,比如一个人一次的购物清单,用符号TT表示,一般来说,TT包含一个它本身的身份——TIDTID以及事务中的一个项集。当然,如果我们收集很多这样的清单,构成一个数据库,这个数据库就能作为我们挖掘计算的依据了。这个库,用符号DD表示。
(4)关联规则:表示实体之间相关关系,用蕴含式A⇒BA⇒B表示A和B之间相关关系(A和B可以是两个项,也可以是两个项集),关联规则包含支持度(support)和置信度(confidence)两个层面指标;
(5)支持度(support):说的是所有事务中,A和B同时出现的次数与总的事务数的比例。换个说法,现实数据中,支持A和B这种关联的比例。用以下公式计算:
support(A⇒B)=P(A∪B)
其中,P(A∪B)的意思是事务中同时包含A和B的比例;
(6)置信度(confidence):A⇒BA⇒B的置信度说的是包含A的事务中,同时也包含B的事务所占的比例。用以下公式计算:
confidence(A⇒B)=P(B|A)
比如说,总共100个事务,有50个包含A,而这50个事务当中,又有20个同时也包含B,那么,confidence(A⇒B)=40%
了解了支持度(support)和置信度(confidence)两个概念,那么不妨可以再深入一步,拓展一个概念:绝对支持度;
支持度计数(绝对支持度):绝对支持度又叫支持度计数,频度或计数。上面我们定义的支持度其实也可以叫“相对支持度”,而绝对支持度则说的是一个实体出现的次数,比如:support(A) = A在全体事务数据库DD中出现的次数。这个概念很重要,因为依靠支持度计数我们就能通过support(A)support(A)和support(A∪B)support(A∪B)来计算置信度:
confidence(A⇒B)=P(B|A)=support(A∪B)support(A)
(7)强规则:我们将实体之间的关联规则定义为强规则,如果实体之间的相对支持度(support)和置信度(confidence)满足我们预定义的最小支持度阈值(min_sup)和最小置信度阈值(min_conf)。换句话说,只要我们在上面的概念5中定义的两个指标都满足,那么,实体之间就是极有强(关联)规则的;
(8)频繁项集:指的是频繁在事务中出现的项集,所谓“频繁”的标准就是这个项集出现的次数满足最小支持度计数(阈值)。
2.2 基本思想
该算法的基本思想是:首先找出所有的频集,这些项集出现的频繁性至少和预定义的最小支持度一样。然后由频集产生强关联规则,这些规则必须满足最小支持度和最小可信度。然后使用第1步找到的频集产生期望的规则,产生只包含集合的项的所有规则,其中每一条规则的右部只有一项,这里采用的是中规则的定义。一旦这些规则被生成,那么只有那些大于用户给定的最小可信度的规则才被留下来。为了生成所有频集,使用了递归的方法。
(1) L1 = find_frequent_1-itemsets(D);
(2) for (k=2;Lk-1 ≠Φ ;k++) {
(3) Ck = apriori_gen(Lk-1 ,min_sup);
(4) for each transaction t ∈ D {//scan D for counts
(5) Ct = subset(Ck,t);//get the subsets of t that are candidates
(6) for each candidate c ∈ Ct
(7) c.count++;
(8) }
(9) Lk ={c ∈ Ck|c.count≥min_sup}
(10) }
(11) return L= ∪ k Lk;
可能产生大量的候选集,以及可能需要重复扫描数据库,是Apriori算法的两大缺点。    
3.算法步骤
下面我们对Aprior算法流程做一个总结。
  输入:数据集合D,支持度阈值α
  输出:最大的频繁k项集
  (1)扫描整个数据集,得到所有出现过的数据,作为候选频繁1项集。k=1,频繁0项集为空集。
  (2)挖掘频繁k项集
    (a) 扫描数据计算候选频繁k项集的支持度
    (b) 去除候选频繁k项集中支持度低于阈值的数据集,得到频繁k项集。如果得到的频繁k项集为空,则直接返回频繁k-1项集的集合作为算法结果,算法结束。如果得到的频繁k项集只有一项,则直接返回频繁k项集的集合作为算法结果,算法结束。
    © 基于频繁k项集,连接生成候选频繁k+1项集。
  (3) 令k=k+1,转入步骤2。
从算法的步骤可以看出,Aprior算法每轮迭代都要扫描数据集,因此在数据集很大,数据种类很多的时候,算法效率很低。
我们下面这个简单的例子看看:

图3.1.1
  我们的数据集D有4条记录,分别是134,235,1235和25。现在我们用Apriori算法来寻找频繁k项集,最小支持度设置为50%。首先我们生成候选频繁1项集,包括我们所有的5个数据并计算5个数据的支持度,计算完毕后我们进行剪枝,数据4由于支持度只有25%被剪掉。我们最终的频繁1项集为1235,现在我们链接生成候选频繁2项集,包括12,13,15,23,25,35共6组。此时我们的第一轮迭代结束。
  进入第二轮迭代,我们扫描数据集计算候选频繁2项集的支持度,接着进行剪枝,由于12和15的支持度只有25%而被筛除,得到真正的频繁2项集,包括13,23,25,35。现在我们链接生成候选频繁3项集,123, 125,135和235共4组,这部分图中没有画出。通过计算候选频繁3项集的支持度,我们发现123,125和135的支持度均为25%,因此接着被剪枝,最终得到的真正频繁3项集为235一组。由于此时我们无法再进行数据连接,进而得到候选频繁4项集,最终的结果即为频繁3三项集235。

4.算法应用
4.1所应用的数据集介绍
以超市交易为数据集,所有商品的项集为I = {bread, beer, cake, cream, milk, tea}
某条交易如Ti = {bread, beer, milk},可以简化为Ti = {a, b, d}
data.txt数据集样本如下
a, d, e,f
a, d, e
c, e
e, f

数据集位于本地的D:\data目录下,数据集一共有270行,前24行的数据内容如图4.1所示

图4.1.1

4.2核心代码

# -*- coding: utf-8 -*-
"""
Created on Tue Jun 25 21:39:58 2019

@author: lyz
"""


def load_data_set():
    data_set = []
    fd = open("d:\data\data.txt", "r")
    for line in fd.readlines():
        line = line.strip('\n')
        data_set.append(line)
    return data_set

'''
直接从数据集构造1-候选集
'''
def create_C1(data_set):
    C1 = set()
    for t in data_set:
        for item in t:
            item_set = frozenset([item])
            C1.add(item_set)
    return C1

'''
判断是否满足
'''
def is_apriori(Ck_item, Lksub1):
    for item in Ck_item:
        sub_Ck = Ck_item - frozenset([item])
        if sub_Ck not in Lksub1:
            return False
    return True

'''
生成各个候选集Ck
'''
def create_Ck(Lksub1, k):
    Ck = set()
    len_Lksub1 = len(Lksub1)
    list_Lksub1 = list(Lksub1)
    for i in range(len_Lksub1):
        for j in range(1, len_Lksub1):
            l1 = list(list_Lksub1[i])
            l2 = list(list_Lksub1[j])
            l1.sort()
            l2.sort()
            if l1[0:k-2] == l2[0:k-2]:
                Ck_item = list_Lksub1[i] | list_Lksub1[j]
                if is_apriori(Ck_item, Lksub1):
                    Ck.add(Ck_item)
    return Ck

'''
通过候选集Ck生成频繁集Lk
'''
def generate_Lk_by_Ck(data_set, Ck, min_support, support_data):
    Lk = set()
    item_count = {}
    for t in data_set:
        for item in Ck:
            if item.issubset(t):
                if item not in item_count:
                    item_count[item] = 1
                else:
                    item_count[item] += 1
    t_num = float(len(data_set))
    for item in item_count:
        if (item_count[item] / t_num) >= min_support:
            Lk.add(item)
            support_data[item] = item_count[item] / t_num
    return Lk

'''
生成各阶频繁集,最小支持度为0.2
'''
def generate_L(data_set, k, min_support):
    support_data = {}
    C1 = create_C1(data_set)
    L1 = generate_Lk_by_Ck(data_set, C1, min_support, support_data)
    Lksub1 = L1.copy()
    L = []
    L.append(Lksub1)
    for i in range(2, k+1):
        Ci = create_Ck(Lksub1, i)
        Li = generate_Lk_by_Ck(data_set, Ci, min_support, support_data)
        Lksub1 = Li.copy()
        L.append(Lksub1)
    return L, support_data

'''
生成从频繁集关联规则分析
'''
def generate_big_rules(L, support_data, min_conf):
    big_rule_list = []
    sub_set_list = []
    for i in range(0, len(L)):
        for freq_set in L[i]:
            for sub_set in sub_set_list:
                if sub_set.issubset(freq_set):
                    conf = support_data[freq_set] / support_data[freq_set - sub_set]
                    big_rule = (freq_set - sub_set, sub_set, conf)
                    if conf >= min_conf and big_rule not in big_rule_list:
                        big_rule_list.append(big_rule)
            sub_set_list.append(freq_set)
    return big_rule_list

if __name__ == "__main__":
    data_set = load_data_set()
    L, support_data = generate_L(data_set, k=3, min_support=0.2)
    big_rules_list = generate_big_rules(L, support_data, min_conf=0.7)
    for Lk in L:
        print ("=" * 50)
        print ("frequent " + str(len(list(Lk)[0])) + "-itemsets\t\tsupport")
        print ("=" * 50)
        for freq_set in Lk:
            print (freq_set, support_data[freq_set])
    print()
    print ("Big Rules")
    for item in big_rules_list:
        print (item[0], "=>", item[1], "conf: ", item[2])

4.3实现页面截图

图 4.3.1

图4.3.2

图4.3.3

图4.3.4
5.总结
Aprior算法是一个非常经典的频繁项集的挖掘算法,很多算法都是基于Aprior算法而产生的,包括FP-Tree,GSP, CBA等。这些算法利用了Aprior算法的思想,但是对算法做了改进,数据挖掘效率更好一些,因此现在一般很少直接用Aprior算法来挖掘数据了,但是理解Aprior算法是理解其它Aprior类算法的前提,同时算法本身也不复杂,因此值得好好研究一番。
这次的收获主要有以下几点:同一行数据,最小支持度越小,那么产生的频繁项集维数越高,程序运行的时间越长;频繁项集的子集一定是频繁的,子集频繁父亲一定频繁;Apriori也存在缺点:第一,在每一步产生候选项目集时循环产生的组合过多,没有排除不应该参与组合的元素;第二,每次计算项集的支持度时,开销会随着数据的增多而成几何级增长。

  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值