数据挖掘-关联分析 Apriori算法和FP-growth 算法

?1.关联分析概念

关联分析是从大量数据中发现项集之间有趣的关联和相关联系。

?

?定义:
1、事务:每一条交易称为一个事务,如上图包含5个事务。
2、项:交易的每一个物品称为一个项,例如豆奶,啤酒等。 
3、项集:包含零个或多个项的集合叫做项集,例如{尿布,啤酒}。
4、k?项集:包含k个项的项集叫做k-项集,例如 {豆奶,橙汁}叫做2-项集。
5、支持度计数:一个项集出现在几个事务当中,它的支持度计数就是几。例如{尿布, 啤酒}出现在事务002、003和005中,所以           它的支持度计数是3。
6、支持度:支持度计数除于总的事务数。例如上例中总的事务数为5,{尿布, 啤酒}的支持度计数为3,所以它的支持度是                       3÷5=60%,说明有60%的人同时买了尿布, 啤酒。

7、频繁项集:支持度大于或等于某个阈值的项集就叫做频繁项集。例如阈值设为50%时,因为{尿布,啤酒}的支持度是60%,所以        它是频繁项集。
8、前件和后件:对于规则{尿布}→{啤酒},{Diaper}叫做前件,{啤酒}叫做后件。
9、置信度:对于规则{尿布}→{啤酒},{尿布,啤酒}的支持度计数除于{尿布}的支持度计数,为这个规则的置信度。

例如规则{尿布}→{啤酒}的置信度为3÷3=100%。说明买了尿布的人100%也买了 啤酒。

10、强关联规则:大于或等于最小支持度阈值和最小置信度阈值的规则叫做强关联规则。

?频繁项集(frequent item sets)是经常出现在一块儿的物品的集合.

?关联规则(association rules)暗示两种物品之间可能存在很强的关系。

?1)支持度

?Surpport(A->B)= P(AB)  ,支持度表示事件A 和事件B 同时出现的概率。

?2)置信度

?Confidence(A->B) = P(B/A) = P(AB)/ P(A) ,置信度表示 A 事件出现时,B 事件出现的概率。

?关联分析的最终目标就是要找出强关联规则。

?2.Apriori算法原理

?Apriori算法是一种最有影响的挖掘布尔关联规则频繁项集的算法。算法的名字基于这样的事实:算法使用频繁项集性质的先验知识,正如我们将看到的。Apriori使用一种称作逐层搜索的迭代方法,k-项集用于探索(k+1)-项集。首先,找出频繁1-项集的集合。该集合记作L1。L1 用于找频繁2-项集的集合L2,而L2 用于找L3,如此下去,直到不能找到频繁k-项集。找每个Lk需要一次数据库扫描。

先验定理:如果一个项集是频繁的,则它的所有子集一定也是频繁的。

?

如图所示,假定{c,d,e}是频繁项集。显而易见,任何包含项集{c,d,e}的事务一定包含它的子集{c,d},{c,e},{d,e},{c},{d}和{e}。这样,如果{c,d,e}是频繁的,则它的所有子集一定也是频繁的。

?

如果项集{a,b}是非频繁的,则它的所有超集也一定是非频繁的。即一旦发现{a,b}是非频繁的,则整个包含{a,b}超集的子图可以被立即剪枝。这种基于支持度度量修剪指数搜索空间的策略称为基于支持度的剪枝。

这种剪枝策略依赖于支持度度量的一个关键性质,即一个项集的支持度绝不会超过它的子集的支持度。这个性质也称支持度度量的反单调性

参考博客有很详细的例子。

?

Apriori算法 
优点:易编码实现。’ 
缺点:在大数据集上可能较慢。 
适用数据类型:数值型或者标称型数据。

3.算法实现:

#coding=gbk
# apriori算法的实现
def load_dataset(): #定义数据集
    return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]

def create_C1(dataSet): #得到数据集中的每个数据,且进行排序
    C1 =[]
    for transantion in dataSet:
        for item in transantion:
            if not [item] in C1:
                C1.append([item])   #储存 I1, I2,。。需要使其不重复
    C1.sort()
    #use frozen set so we can use it as a key in a dict
    #应该输出 1,2,3,4,5
    return list(map(frozenset, C1))  #  将C1中的每个集合映射为frozenset,之后可以作为字典的键,

dataSet = load_dataset()
ck = create_C1(dataSet)
print(ck)        # 输出:[frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]

#测试代码
# # map(function, sequence)
# c2 = [[2,4],[5,8],[3]]
# c2.sort()
# a = list(map(frozenset, c2))
# print(a)    #[frozenset({2, 4}), frozenset({3}), frozenset({8, 5})]
# print(a[0]) # frozenset({2, 4})

# Apriori算法首先构建集合 C1 ,然后扫描数据集判断这些只有一个元素的项集是否满足最小支持度的要求。那些满足最低要求的项集构成集合 L1 。
# 而 L1 中的元素相互组合构成 C2 , C2 再进一步过滤变为 L2 。

#该函数使 C1 生成L1,ck为全部的数据项
def scanD(D, Ck, minSupport):   #参数D 为数据集, Ck为候选项列表, 最小支持度
    ssCnt= {}       #存储数据项1,2,。。及其出现的次数

    for tid in D:       #遍历数据集
        for can in Ck:  #遍历候选项 1,2,3,4,5,
            if can.issubset(tid):   #判断候选项是否含数据集中的各项
                if not can in ssCnt:
                    ssCnt[can] =1
                else:
                    ssCnt[can]+=1   #有则进行加一操作,   1,2,3,4,5 的数据项的个数, 为了计算支持度
    numItems = float(len(D))    #计算数据集大小
    retList = []        #使L1 初始化, 保存大于最小支持度的数据项
    supportData = {}    #使用字典记录支持度
    for key in ssCnt:
        support = ssCnt[key]/ numItems  #求得支持度
        if support >= minSupport:       #如果支持度大于用户给的最小支持度, 对小于的数据项进行去除。
            retList.insert(0,  key) #保存到列表中
        else:
            supportData[key]= support   #输出去除项的支持度
    return retList, supportData

#测试:
r, s = scanD(dataSet, ck, 0.5)
print(r)    #[frozenset({1}), frozenset({3}), frozenset({2}), frozenset({5})]
print(s)    #{frozenset({4}): 0.25}

数据集为:总共有4 分

1, 3, 4
2, 3, 5
1, 2, 3, 5
2, 5
C1 出现次数
1) 2
2) 3
3) 3
4) 1
5) 3

4)的支持度为 1/4 为 0.25  < 0.5  = minSupport  ,所以将其舍去

整个Apriori算法的伪代码如下:

当集合中项的个数大于0时:
    构建一个k个项组成的候选项集的列表
    检查数据以确认每个项集都是频繁的
    保留频繁项集并构建k+1项组成的候选项集的列表(向上合并)

#Apriori 算法实现
# 输入参数为 频繁项集列表 Lk 与  项集元素个数 k , 输出为 Ck
def aprioriGen(Lk, k):
    retList = []
    lenLk = len(Lk)
    for i in range(lenLk):
        for j in range(i+1, lenLk): #两两组合遍历 (1,2,3,5)
            L1 = list(Lk[i])[:k-2]
            L2 = list(Lk[j])[:k-2]  #用列表储存 k-2 项的项集
            L1.sort(); L2.sort()
            if L1 == L2:
                retList.append(Lk[i] | Lk[j])   #若2个集合的前 k-2 个项相同时, 则将两个集合合并
    return retList

def apriori(dataSet, minSupport =0.5):
    C1 = create_C1(dataSet)
    D = list(map(set, dataSet))
    L1, supportData = scanD(D, C1, minSupport)  #生成L1
    L =[L1]
    k =2
    while (len(L[k-2]) > 0):        #创建 包含更多的项集的列表, 直到下一个项集为空 ,终止循环。
        Ck = aprioriGen(L[k-2], k)
        Lk, supk = scanD(D, Ck, minSupport) #再次在数据库上扫描一遍
        supportData.update(supk)
        L.append(Lk)        #在1 -项集上增加 2-项集
        k +=1
    return L, supportData 

a= [1,2,3]
a.append([[12],[13],[16]])
print(a)    #[1, 2, 3, [[12], [13], [16]]]

#apriori 测试
print(‘------apriori test -------‘)
dataSet = load_dataset()
L, supportData = apriori(dataSet)

print(L)#[[frozenset({1}), frozenset({3}), frozenset({2}), frozenset({5})], [frozenset({3, 5}), frozenset({1, 3}),
# frozenset({2, 5}), frozenset({2, 3})], [frozenset({2, 3, 5})], []]

print(L[0]) #  [frozenset({1}), frozenset({3}), frozenset({2}), frozenset({5})]
print(L[1]) #  [frozenset({3, 5}), frozenset({1, 3}), frozenset({2, 5}), frozenset({2, 3})]
print(L[2]) #[frozenset({2, 3, 5})]
print(L[3]) # [] 频繁项集为空, 所以的出频繁项集 为{2,3,5} 

#查看全部项集的支持度
print(supportData)  # 部分输出:{frozenset({5}): 0.75, frozenset({3}): 0.75, frozenset({2, 3, 5}): 0.5,

函数 aprioriGen() 的输入参数为频繁项集列表 Lk 与项集元素个数 k ,输出为 Ck 。举例来说,该函数以{0}、{1}、{2}作为输入,会生成{0,1}、{0,2}以及{1,2}。要完成这一点,首先创建一个空列表,然后计算 Lk 中的元素数目。通过循环来比较 Lk 中的每一个元素与其他元素,紧接着,取列表中的两个集合进行比较。如果这两个集合的前面 k-2 个元素都相等,那么就将这两个集合合成一个大小为 k 的集合 。这里使用集合的并操作来完成。

apriori函数首先创建 C1 然后读入数据集将其转化为 D (集合列表)来完 
成。程序中使用 map 函数将 set() 映射到 dataSet 列表中的每一项。scanD() 函数来创建 L1 ,并将 L1 放入列表 L 中。 L 会包含 L1 、 L2 、 L3 …。现在有了 L1 ,后面会继续找 L2 , L3 …,这可以通过 while 循环来完成,它创建包含更大项集的更大列表,直到下一个大的项集为空。Lk 列表被添加到 L ,同时增加 k 的值,增大项集个数,重复上述过程。最后,当 Lk 为空时,程序返回 L 并退出。

参考blog

从频繁项中挖掘关联规则

#从频繁项集中挖掘关联规则

#产生关联规则
#参数为 L 为频繁项集, supportData 为全部项集的支持度, mincof 设置最小的置信度为 0.7
def generateRules(L, supportData, minconf = 0.7):
    bigRuleList = []    #存储所有的关联规则
    for i in range(1,len(L)):   #只获取2 个或更多项集
        for freqSet in L[i]:
            #遍历L 中每一个频繁项集,对每个项集创建值包含单个元素的 列表
            H1 = [frozenset([item]) for item in freqSet]
            #如果频繁项集数目超过2 个, 就对其进行进一步的合并
            if (i>1 ):
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minconf)
            else:
                #第一层时, 后件数为1
                calcConf(freqSet, H1, supportData, bigRuleList, minconf)
    return bigRuleList

#生成候选规则集合: 计算规则的置信度,以及找到满足最小置信度的规则
def calcConf(freqSet, H1, supportData, brl, minconf=0.7):
    #针对项集只有2 个元素时, 计算置信度
    prunedH = []    #返回一个满足最小置信度的规则列表
    for conseq in H1:       #遍历H 中的所有项集, 并计算它们的置信度
        conf =  supportData[freqSet] / supportData[freqSet-conseq]  #计算置信度
        if conf >= minconf:     ##满足最小置信度要求, 则打印
            print(freqSet-conseq, ‘-->‘, conseq,‘conf:‘, conf)
            brl.append((freqSet - conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH

#进行合并
def rulesFromConseq(freqSet, H1, supportData, brl, minconf = 0.7):
    #参数:freqSet是频繁项, H 是可以出现在规则右边的列表
    m = len(H1[0])
    if (len(freqSet) > (m+1)):  #如果 频繁项集元素数目大于单个集合的元素数
        Hmp1 = aprioriGen(H1, m+1)  #  合并具有相同部分的集合
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minconf)   #计算置信度
        if (len(Hmp1) > 1):
            #使用递归进一步组合
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minconf)

#测试关联规则输出
print()
print(‘-------generateRules test-------‘)
rules = generateRules(L, supportData, minconf=0.5)
print(rules)
# -------generateRules test-------
# frozenset({5}) --> frozenset({3}) conf: 0.6666666666666666
# frozenset({3}) --> frozenset({5}) conf: 0.6666666666666666
# frozenset({3}) --> frozenset({1}) conf: 0.6666666666666666
# frozenset({1}) --> frozenset({3}) conf: 1.0
# frozenset({5}) --> frozenset({2}) conf: 1.0
# frozenset({2}) --> frozenset({5}) conf: 1.0
# frozenset({3}) --> frozenset({2}) conf: 0.6666666666666666
# frozenset({2}) --> frozenset({3}) conf: 0.6666666666666666
# frozenset({5}) --> frozenset({2, 3}) conf: 0.6666666666666666
# frozenset({3}) --> frozenset({2, 5}) conf: 0.6666666666666666
# frozenset({2}) --> frozenset({3, 5}) conf: 0.6666666666666666
# [(frozenset({5}), frozenset({3}), 0.6666666666666666),。。。。。。。

4.FP-growth 算法原理:

相比于apriori 算法, FP-growth 算法可高效发现 频繁项集 。

FP-growth 算法例子可查看。

python代码参考

参考:https://blog.csdn.net/zhazhayaonuli/article/details/53322541

https://www.cnblogs.com/qwertWZ/p/4510857.html

原文地址:https://www.cnblogs.com/junge-mike/p/9335048.html

时间: 2024-12-05 00:16:52

数据挖掘-关联分析 Apriori算法和FP-growth 算法的相关文章

Aprior算法、FP Growth算法

数据挖掘中有一个很重要的应用,就是Frequent Pattern挖掘,翻译成中文就是频繁模式挖掘.这篇博客就想谈谈频繁模式挖掘相关的一些算法. 定义 何谓频繁模式挖掘呢?所谓频繁模式指的是在样本数据集中频繁出现的模式.举个例子,比如在超市的交易系统中,记载了很多次交易,每一次交易的信息包括用户购买的商品清单.如果超市主管是个有心人的话,他会发现尿不湿,啤酒这两样商品在许多用户的购物清单上都出现了,而且频率非常高.尿不湿,啤酒同时出现在一张购物单上就可以称之为一种频繁模式,这样的发掘就可以称之为

使用Apriori算法和FP-growth算法进行关联分析(Python版)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

使用Apriori算法和FP-growth算法进行关联分析

系列文章:<机器学习>学习笔记 最近看了<机器学习实战>中的第11章(使用Apriori算法进行关联分析)和第12章(使用FP-growth算法来高效发现频繁项集).正如章节标题所示,这两章讲了无监督机器学习方法中的关联分析问题.关联分析可以用于回答"哪些商品经常被同时购买?"之类的问题.书中举了一些关联分析的例子: 通过查看哪些商品经常在一起购买,可以帮助商店了解用户的购买行为.这种从数据海洋中抽取的知识可以用于商品定价.市场促销.存活管理等环节. 在美国国会

FP—Growth算法

FP_growth算法是韩家炜老师在2000年提出的关联分析算法,该算法和Apriori算法最大的不同有两点: 第一,不产生候选集,第二,只需要两次遍历数据库,大大提高了效率,用31646条测试记录,最小支持度是2%, 用Apriori算法要半个小时但是用FP_growth算法只要6分钟就可以了,效率非常明显. 它的核心是FP_tree,一种树型数据结构,特点是尽量把相同元素用一个节点表示,这样就大大减少了空间,和birch算法有类似的思想.还是以如下数据为例. 每一行表示一条交易,共有9行,既

Frequent Pattern 挖掘之二(FP Growth算法)(转)

FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结构,叫做frequent-pattern tree(频繁模式树).下面就详细谈谈如何构造这个树,举例是最好的方法.请看下面这个例子: 这张表描述了一张商品交易清单,abcdefg代表商品,(ordered)frequent items这一列是把商品按照降序重新进行了排列,这个排序很重要,我们操作的所

Redis源码分析(二十三)--- CRC循环冗余算法和RAND随机数算法

今天开始研究Redis源码中的一些工具类的代码实现,工具类在任何语言中,实现的算法原理应该都是一样的,所以可以借此机会学习一下一些比较经典的算法.比如说我今天看的Crc循环冗余校验算法和rand随机数产生算法. CRC算法全称循环冗余校验算法.CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去.在接收端, 则根据信息码和CRC码之间所遵循的规则进

关联分析-Apriori法python代码注解

自己的一点点领悟,可能会有点小错误,欢迎交流^_^ 获得频繁项集 主要思想 python代码 def loadDataSet(): return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]] createC1(dataSet)获得所有第一层的所有项集 def createC1(dataSet): C1 = [] for transaction in dataSet: for item in transaction: if not [item] in C1: C1.appen

Hadoop Mapreduce 中的FileInputFormat类的文件切分算法和host选择算法

文件切分算法 文件切分算法主要用于确定InputSplit的个数以及每个InputSplit对应的数据段. FileInputFormat以文件为单位切分成InputSplit.对于每个文件,由以下三个属性值确定其对应的InputSplit的个数. goalSize:根据用户期望的InputSplit数据计算,即totalSize/numSplit.totalSize为文件总大小:numSplit为用户设定的Map Task个数,默认情况下是1. minSize:InputSplit的最小值,由

机器学习算法-Apriori关联分析

引文: 学习一个算法,我们最关心的并不是算法本身,而是一个算法能够干什么,能应用到什么地方.很多的时候,我们都需要从大量数据中提取出有用的信息,从大规模数据中寻找物品间的隐含关系叫做关联分析(association analysis)或者关联规则学习(association rule learning).比如在平时的购物中,那些商品一起捆绑购买销量会比较好,又比如购物商城中的那些推荐信息,都是根据用户平时的搜索或者是购买情况来生成的.如果是蛮力搜索的话代价太高了,所以Apriori就出现了,就是