美文网首页数据挖掘
频繁项集挖掘Apriori算法及其Python实现

频繁项集挖掘Apriori算法及其Python实现

作者: 贰拾贰画生 | 来源:发表于2015-05-26 17:38 被阅读8574次

Apriori算法是通过限制候选产生发现频繁项集。

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

为了提高频繁项集逐层产生的效率,一种称为先验性质(Apriori property)的重要性质用于压缩搜索空间。

先验性质:频繁项集的所有非空子集也一定是频繁的。

其实,算法的描述理解起来是困难的,有例子帮助理解最好不过。恩,盗图一张。

20130609110737296.png
Python实现:

我们的期望:

输入:数据库中数据和最小支持度
输出:频繁项集
例:
输入:数据,[['A','B','C','D'],['B','C','E'],['A','B','C','E'],['B','D','E'],['A','B','C','D']];最小支持度:0.7
输出:[['B'], ['C'], ['B', 'C']]

写一个方法 def apriori(D, minSup),参数D就是输入的数据库数据,minSup是最小支持度。

def apriori(D, minSup):
    
    '''频繁项集用keys表示,
    key表示项集中的某一项,
    cutKeys表示经过剪枝步的某k项集。
    C表示某k项集的每一项在事务数据库D中的支持计数
    '''
    #先求出1项集的集合及其支持计数,注意此处C1是字典,key为项集,value是计数,与下不同,下的C是列表只有计数
    C1 = {}
    for T in D:
        for I in T:
            if I in C1:
                C1[I] += 1
            else:
                C1[I] = 1

    _keys1 = C1.keys()

    #此处对keys的存储格式进行处理,为了方便后边由此得出k+1项集的集合
    keys1 = []
    for i in _keys1:
        keys1.append([i])

    n = len(D)
    cutKeys1 = []
    #对keys1(1项集)进行剪枝步
    for k in keys1[:]:
        if C1[k[0]]*1.0/n >= minSup:
            cutKeys1.append(k)
    
    cutKeys1.sort()

总之,对于1项集要进行特殊处理,然后再用迭代的方法求k+1项集。
好,迭代来了:

    all_keys = []
    while keys != []:
        C = getC(D, keys)
        cutKeys = getCutKeys(keys, C, minSup, D)
        for key in cutKeys:
            all_keys.append(key)
        keys = aproiri_gen(cutKeys)

    return all_keys

注意,all_keys是全局变量,存储所有通过剪枝步的k项集。
函数getC(D, keys)是对keys中的每一个key进行计数,函数getCutKeys(keys, C, minSup, D)是剪枝步的实现,函数aproiri_gen(cutKeys)是由k项集获得k+1项集(连接步)。

这样,算法Apriori就实现了,输入输出试一下:

D = [['A','B','C','D'],['B','C','E'],['A','B','C','E'],['B','D','E'],['A','B','C','D']]
F = apriori(D, 0.7)
print '\nfrequent itemset:\n', F
屏幕快照 2015-05-26 下午5.35.16.png
把最小支持度改成0.5试试:
屏幕快照 2015-05-26 下午5.36.39.png
恩,没有问题。

完整代码见:https://github.com/youthpasses/apriori

相关文章

网友评论

  • 0616ce368a01:朋友,有对的代码吗,笑哭
    杜小韩日记:https://github.com/Felixyon/SimpleApriori
    同学,我有对题主的代码稍作修改,你看看能不能用
  • 月桜叶花:{A,C}{B,C}{B,E}{C,E}-->用你的剪枝代码(aproiri_gen(keys1)这个方法)进行剪枝得到的集合是{A,B,C}{A,B,C,E}{A,C,E}{B,C,E}和你上面画的图不一样啊
    贰拾贰画生:@月桜叶花 en 你说的对,C3中应只有{B,C,E},抱歉这张图是从别人那拷的 没仔细看
    月桜叶花:@贰拾贰画生 Apriori的原理是如果某个项集是频繁的,那么它的子集也是频繁的。反过来说,如果一个项集是非频繁的,那么它的所有超集也是非频繁的。那为什么在C3集合中还会有{A,E}的超集
    贰拾贰画生:@月桜叶花 那张图就是个例子,跟代码无关
  • 0c82867934f2:代码中这一段
    C = getC(D, keys)
    cutKeys = getCutKeys(keys, C, minSup, D)

    但是在整个getCutKeys函数中,更本没有用到这个 C 参数啊,

    def getCutKeys(keys, C, minSup, D):
    '''剪枝步'''
    for key in keys[:]:
    num = 0
    for T in D:
    if keyInT(key, T):
    num += 1
    if num * 1.0 / len(D) < minSup:
    keys.remove(key)

    return keys
    贰拾贰画生:@papersnakes 啊,谢谢。我已经改好了~ :+1:

本文标题:频繁项集挖掘Apriori算法及其Python实现

本文链接:https://www.haomeiwen.com/subject/zrerqttx.html